当前位置: 首页 > news >正文

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.xdnf.cn/news/475741.html

相关文章:

  • 100G QSFP28 BIDI光模块一览:100G单纤高速传输方案|易天光通信
  • 组件导航 (Navigation)+flutter项目搭建-混合开发+分栏
  • Android 中 权限分类及申请方式
  • HNU工训--计算机串口数据收发与测量
  • 安科瑞AcrelEMS3.0企业微电网智慧能源平台-安科瑞 蒋静
  • .NET Core liunx二进制文件安装
  • 22、能源监控与优化 - 数据中心模拟 - /能源管理组件/data-center-energy-monitoring
  • CSS面试题汇总
  • 中文分词与数据可视化02
  • 接触感知 钳位电路分析
  • [模型部署] 3. 性能优化
  • 我的 PDF 工具箱:CodeBuddy 打造 PDFMagician 的全过程记录
  • Java 并发编程归纳总结(可重入锁 | JMM | synchronized 实现原理)
  • 【LeetCode 热题 100】动态规划 系列
  • 从 Vue3 回望 Vue2:生命周期的清晰化——从混乱钩子到明确时机
  • 2025年渗透测试面试题总结-安恒[实习]安全服务工程师(题目+回答)
  • git克隆github项目到本地的三种方式
  • Vue百日学习计划Day16-18天详细计划-Gemini版
  • matlab建立整车模型,求汽车的平顺性
  • 【Golang笔记01】Goland基础语法规则
  • Leaflet 自定义瓦片地图与 PHP 大图切图算法 解决大图没办法在浏览器显示的问题
  • 容器编排利器-k8s入门指南
  • 移植RTOS,发现任务栈溢出怎么办?
  • 哪个品牌的智能对讲机好用?推荐1款,能扛事更智能
  • MySQL基础
  • Jenkins教程
  • 2025云智算技术白皮书
  • 青少年编程与数学 02-019 Rust 编程基础 16课题、包、单元包及模块
  • rust语言,与c,go语言一样也是编译成二进制文件吗?
  • Claude Prompt-Caching 方案调研