C#將1GB大圖裁剪為8張圖片

C#處理超大圖片(1GB)需要特別注意內存管理和性能優化。以下是幾種高效裁剪方案:

方法1:使用System.Drawing分塊處理(內存優化版)

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;class Program
{static void Main(){string sourceImagePath = "1GB_Image.bmp";string outputFolder = "CroppedImages";if (!Directory.Exists(outputFolder)){Directory.CreateDirectory(outputFolder);}// 獲取圖片尺寸但不加載全部內容using (var image = Image.FromFile(sourceImagePath)){int totalWidth = image.Width;int totalHeight = image.Height;// 計算每塊尺寸 (2x4網格)int chunkWidth = totalWidth / 2;int chunkHeight = totalHeight / 4;// 分塊裁剪for (int row = 0; row < 4; row++){for (int col = 0; col < 2; col++){int x = col * chunkWidth;int y = row * chunkHeight;// 確保最后一塊包含剩余部分int width = (col == 1) ? totalWidth - x : chunkWidth;int height = (row == 3) ? totalHeight - y : chunkHeight;CropImage(sourceImagePath,Path.Combine(outputFolder, $"part_{row}_{col}.jpg"),x, y, width, height);}}}}static void CropImage(string sourcePath, string destPath, int x, int y, int width, int height){// 使用流式處理避免全圖加載using (var source = new Bitmap(sourcePath))using (var dest = new Bitmap(width, height))using (var graphics = Graphics.FromImage(dest)){graphics.DrawImage(source,new Rectangle(0, 0, width, height),new Rectangle(x, y, width, height),GraphicsUnit.Pixel);// 保存為JPEG減少體積dest.Save(destPath, ImageFormat.Jpeg);Console.WriteLine($"已保存: {destPath} ({width}x{height})");}}
}

方法2:使用ImageSharp(現代跨平臺方案)

首先安裝NuGet包:

Install-Package SixLabors.ImageSharp

實現代碼:

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Jpeg;class Program
{static async Task Main(){string sourcePath = "1GB_Image.jpg";string outputDir = "CroppedImages";Directory.CreateDirectory(outputDir);// 配置內存選項處理大圖var configuration = Configuration.Default.Clone();configuration.MemoryAllocator = new SixLabors.ImageSharp.Memory.ArrayPoolMemoryAllocator();// 分塊加載和處理using (var image = await Image.LoadAsync(configuration, sourcePath)){int totalWidth = image.Width;int totalHeight = image.Height;int chunkWidth = totalWidth / 2;int chunkHeight = totalHeight / 4;for (int row = 0; row < 4; row++){for (int col = 0; col < 2; col++){int x = col * chunkWidth;int y = row * chunkHeight;int width = (col == 1) ? totalWidth - x : chunkWidth;int height = (row == 3) ? totalHeight - y : chunkHeight;// 克隆并裁剪區域using (var cropped = image.Clone(ctx => ctx.Crop(new Rectangle(x, y, width, height)))){string outputPath = Path.Combine(outputDir, $"part_{row}_{col}.jpg");await cropped.SaveAsync(outputPath, new JpegEncoder {Quality = 80 // 適當壓縮});Console.WriteLine($"已保存: {outputPath}");}}}}}
}

方法3:使用內存映射文件處理超大圖

using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Drawing;
using System.Drawing.Imaging;class Program
{static void Main(){string sourcePath = "1GB_Image.bmp";string outputDir = "CroppedImages";Directory.CreateDirectory(outputDir);// 獲取BMP文件頭信息var bmpInfo = GetBmpInfo(sourcePath);int width = bmpInfo.Width;int height = bmpInfo.Height;int bytesPerPixel = bmpInfo.BitsPerPixel / 8;int stride = width * bytesPerPixel;// 計算分塊int chunkWidth = width / 2;int chunkHeight = height / 4;// 使用內存映射文件處理using (var mmf = MemoryMappedFile.CreateFromFile(sourcePath, FileMode.Open)){for (int row = 0; row < 4; row++){for (int col = 0; col < 2; col++){int x = col * chunkWidth;int y = row * chunkHeight;int cropWidth = (col == 1) ? width - x : chunkWidth;int cropHeight = (row == 3) ? height - y : chunkHeight;// 創建目標位圖using (var dest = new Bitmap(cropWidth, cropHeight, PixelFormat.Format24bppRgb)){var destData = dest.LockBits(new Rectangle(0, 0, cropWidth, cropHeight),ImageLockMode.WriteOnly,dest.PixelFormat);try{// 計算源文件偏移量(BMP文件頭54字節 + 數據偏移)long offset = 54 + (height - y - 1) * stride + x * bytesPerPixel;// 逐行復制for (int line = 0; line < cropHeight; line++){using (var accessor = mmf.CreateViewAccessor(offset - line * stride, cropWidth * bytesPerPixel)){byte[] lineData = new byte[cropWidth * bytesPerPixel];accessor.ReadArray(0, lineData, 0, lineData.Length);IntPtr destPtr = destData.Scan0 + (line * destData.Stride);System.Runtime.InteropServices.Marshal.Copy(lineData, 0, destPtr, lineData.Length);}}}finally{dest.UnlockBits(destData);}string outputPath = Path.Combine(outputDir, $"part_{row}_{col}.jpg");dest.Save(outputPath, ImageFormat.Jpeg);Console.WriteLine($"已保存: {outputPath}");}}}}}static (int Width, int Height, int BitsPerPixel) GetBmpInfo(string filePath){using (var fs = new FileStream(filePath, FileMode.Open))using (var reader = new BinaryReader(fs)){// 讀取BMP頭if (reader.ReadChar() != 'B' || reader.ReadChar() != 'M')throw new Exception("不是有效的BMP文件");fs.Seek(18, SeekOrigin.Begin); // 跳轉到寬度信息int width = reader.ReadInt32();int height = reader.ReadInt32();fs.Seek(28, SeekOrigin.Begin); // 跳轉到位深信息int bitsPerPixel = reader.ReadInt16();return (width, height, bitsPerPixel);}}
}

方法4:使用Magick.NET(專業圖像處理)

首先安裝NuGet包:

Install-Package Magick.NET-Q16-x64

實現代碼:

using ImageMagick;
using System;
using System.IO;class Program
{static void Main(){string sourcePath = "1GB_Image.tif";string outputDir = "CroppedImages";Directory.CreateDirectory(outputDir);// 設置資源限制MagickNET.SetResourceLimit(ResourceType.Memory, 1024 * 1024 * 1024); // 1GB// 使用像素流處理大圖using (var image = new MagickImage(sourcePath)){int width = image.Width;int height = image.Height;int chunkWidth = width / 2;int chunkHeight = height / 4;for (int row = 0; row < 4; row++){for (int col = 0; col < 2; col++){int x = col * chunkWidth;int y = row * chunkHeight;int cropWidth = (col == 1) ? width - x : chunkWidth;int cropHeight = (row == 3) ? height - y : chunkHeight;using (var cropped = image.Clone(new MagickGeometry{X = x,Y = y,Width = cropWidth,Height = cropHeight})){string outputPath = Path.Combine(outputDir, $"part_{row}_{col}.jpg");cropped.Quality = 85;cropped.Write(outputPath);Console.WriteLine($"已保存: {outputPath}");}}}}}
}

裁剪方案選擇建議

方法????????優點缺點使用場景
System.Drawing內置庫,簡單內存占用高Windows小圖處理
ImageSharp跨平臺,現代API?? ?學習曲線需要跨平臺支持
內存映射內存效率高復雜,僅限BMP超大圖處理
Magick.NET功能強大需要安裝專業圖像處理

注意事項

  1. 內存管理:處理1GB圖片需要至少2-3GB可用內存
  2. 文件格式:BMP/TIFF適合處理,JPEG可能有壓縮問題
  3. 磁盤空間:確保有足夠空間存放輸出文件
  4. 異常處理:添加try-catch處理IO和內存不足情況
  5. 性能優化:
  • 使用64位應用程序
  • 增加GC內存限制:<gcAllowVeryLargeObjects enabled="true"/>
  • 分批處理減少內存壓力

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/905902.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/905902.shtml
英文地址,請注明出處:http://en.pswp.cn/news/905902.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux系統啟動相關:vmlinux、vmlinuz、zImage,和initrd 、 initramfs,以及SystemV 和 SystemD

目錄 一、vmlinux、vmlinuz、zImage、bzImage、uImage 二、initrd 和 initramfs 1、initrd&#xff08;Initial RAM Disk&#xff09; 2、initramfs&#xff08;Initial RAM Filesystem&#xff09; 3、initrd vs. initramfs 對比 4. 如何查看和生成 initramfs 三、Syste…

AIStarter Windows 版本迎來重磅更新!模型插件工作流上線,支持 Ollama / ComfyUI 等多平臺本地部署模型統一管理

如果你正在使用 AIStarter 工具進行本地 AI 模型部署 &#xff0c;那么這條消息對你來說非常重要&#xff01; 在最新推出的 AIStarter Windows 正式版更新中 &#xff0c;官方對整個平臺進行了功能重構和性能優化&#xff0c;尤其是新增了「模型插件工作流 」功能&#xff0c…

深入理解橋接模式:解耦抽象與實現的設計藝術

一、為什么需要橋接模式&#xff1f;從“類爆炸”問題說起 你是否遇到過這樣的開發困境&#xff1f; 當需要為系統擴展新功能時&#xff0c;繼承體系像滾雪球一樣越變越臃腫&#xff1a;新增一種遙控器類型&#xff0c;需要為電視、音響各寫一個子類&#xff1b;新增一種設備類…

Java 中的泛型原理與實踐案例

引言&#xff1a;為什么需要泛型 在Java 5之前&#xff0c;集合類只能存儲Object類型的對象&#xff0c;這帶來了兩個主要問題&#xff1a; 類型不安全&#xff1a;可以向集合中添加任何類型的對象&#xff0c;容易出錯繁瑣的類型轉換&#xff1a;從集合中取出元素時需要手動…

springboot3+vue3融合項目實戰-大事件文章管理系統-獲取文章分類詳情

GetMapping("/detail")public Result<Category> detail(Integer id){Category c categoryService.findById(id);return Result.success(c);}在CategoryService接口增加 Category findById(Integer id); 在CategoryServiceImpl增加 Overridepublic Category f…

從零開始創建一個 Next.js 項目并實現一個 TodoList 示例

Next.js 是一個基于 React 的服務端渲染框架&#xff0c;它提供了很多開箱即用的功能&#xff0c;如自動路由、API 路由、靜態生成、增量靜態再生等。本文將帶你一步步創建一個 Next.js 項目&#xff0c;并實現一個簡單的 TodoList 功能。 效果地址 &#x1f9f1; 安裝 Next.j…

分布式鎖: Redisson紅鎖(RedLock)原理與實現細節

分布式鎖是分布式系統的核心基礎設施&#xff0c;但 單節點 Redis 鎖在高可用場景下存在致命缺陷&#xff1a;當 Redis 主節點宕機時&#xff0c;從節點可能因異步復制未完成而丟失鎖信息&#xff0c;導致多個客戶端同時持有鎖。為此&#xff0c;Redis 作者 Antirez 提出了 Red…

c++多態面試題之(析構函數與虛函數)

有以下問題展開 析構函數要不要定義成虛函數&#xff1f;基類的析構函數要不要定義成虛函數&#xff1f;如果不定義會有什么問題&#xff0c;定義了在什么場景下起作用。 1. 基類析構函數何時必須定義為虛函數&#xff1f; 當且僅當通過基類指針&#xff08;或引用&#xff09;…

Python高級進階:Vim與Vi使用指南

李升偉 整理 在 Python 高級進階中&#xff0c;使用 Vim 或 Vi 作為代碼編輯器可以顯著提升開發效率&#xff0c;尤其是在遠程服務器開發或快速腳本編輯時。以下是關于它們在 Python 開發中的高級應用詳解&#xff1a; 1. Vim/Vi 簡介 Vi&#xff1a;經典的 Unix 文本編輯器…

Dify中使用插件LocalAI配置模型供應商報錯

服務器使用vllm運行大模型&#xff0c;今天在Dify中使用插件LocalAI配置模型供應商后&#xff0c;使用工作流的時候&#xff0c;報錯&#xff1a;“Run failed: PluginInvokeError: {"args":{},"error_type":"ValueError","message":&…

深度學習驅動下的目標檢測技術:原理、算法與應用創新(二)

三、主流深度學習目標檢測算法剖析 3.1 R - CNN 系列算法 3.1.1 R - CNN 算法詳解 R - CNN&#xff08;Region - based Convolutional Neural Networks&#xff09;是將卷積神經網絡&#xff08;CNN&#xff09;應用于目標檢測領域的開創性算法&#xff0c;其在目標檢測發展歷…

【Umi】項目初始化配置和用戶權限

app.tsx import { RunTimeLayoutConfig } from umijs/max; import { history, RequestConfig } from umi; import { getCurrentUser } from ./services/auth; import { message } from antd;// 獲取用戶信息 export async function getInitialState(): Promise<{currentUse…

[學習] RTKLib詳解:qzslex.c、rcvraw.c與solution.c

RTKLib詳解&#xff1a;qzslex.c、rcvraw.c與solution.c 本文是 RTKLlib詳解 系列文章的一篇&#xff0c;目前該系列文章還在持續總結寫作中&#xff0c;以發表的如下&#xff0c;有興趣的可以翻閱。 [學習] RTKlib詳解&#xff1a;功能、工具與源碼結構解析 [學習]RTKLib詳解…

移植RTOS,發現任務棧溢出怎么辦?

目錄 1、硬件檢測方法 2、軟件檢測方法 3、預防堆棧溢出 4、處理堆棧溢出 在嵌入式系統中&#xff0c;RTOS通過管理多個任務來滿足嚴格的時序要求。任務堆棧管理是RTOS開發中的關鍵環節&#xff0c;尤其是在將RTOS移植到新硬件平臺時。堆棧溢出是嵌入式開發中常見的錯誤&am…

window 顯示驅動開發-使用有保證的協定 DMA 緩沖區模型

Windows Vista 的顯示驅動程序模型保證呈現設備的 DMA 緩沖區和修補程序位置列表的大小。 修補程序位置列表包含 DMA 緩沖區中命令引用的資源的物理內存地址。 在有保證的協定模式下&#xff0c;用戶模式顯示驅動程序知道 DMA 緩沖區和修補程序位置列表的確切大小&#xff0c;…

SD-HOST Controller design-----SD CLK 設計

hclk的分頻電路&#xff0c;得到的分頻時鐘作為sd卡時鐘。 該模塊最終輸出兩個時鐘&#xff1a;一個為fifo_sd_clk,另一個為out_sd_clk_dft。當不分頻時&#xff0c;fifo_sd_clk等于hclk&#xff1b;當分頻時候&#xff0c;div_counter開始計數&#xff0c;記到相應分頻的時候…

完全背包問題中「排列數」與「組合數」的核心區別

&#x1f3af; 一句話理解 求組合數&#xff08;不計順序&#xff09; → 外層遍歷物品&#xff0c;內層遍歷背包容量 求排列數&#xff08;計順序&#xff09; → 外層遍歷背包容量&#xff0c;內層遍歷物品 &#x1f3b2; 舉例說明 假設有硬幣 [1, 2, 3]&#xff0c;目標金…

NHANES指標推薦:MDS

文章題目&#xff1a;The association between magnesium depletion score (MDS) and overactive bladder (OAB) among the U.S. population DOI&#xff1a;10.1186/s41043-025-00846-x 中文標題&#xff1a;美國人群鎂耗竭評分 &#xff08;MDS&#xff09; 與膀胱過度活動癥…

C++:字符串操作函數

strcpy() 功能&#xff1a;把一個字符串復制到另一個字符串。 #include <iostream> #include <cstring> using namespace std;int main() {char src[] "Hello";char dest[10];strcpy(dest, src);cout << "Copied string: " << …

1基·2臺·3空間·6主體——藍象智聯解碼可信數據空間的“數智密碼”

近日&#xff0c;由全國數據標準化技術委員會編制的《可信數據空間 技術架構》技術文件正式發布&#xff0c;標志著我國數據要素流通體系向標準化、規范化邁出關鍵一步。該文件從技術功能、業務流程、安全要求三大維度對可信數據空間進行系統性規范&#xff0c;為地方、行業及企…