如何在C#中裁剪固定起始点(0,0)、固定尺寸的图片?
图片裁剪需求与问题代码
- 待裁剪图片
- 已裁剪图片
需求:裁剪已有图片,裁剪区域尺寸固定为866×520,起始点始终为(0, 0)。尝试过StackOverflow上的方法但无效,当前使用的代码如下:
private void Converter(Image image, int count) { string name = String.Format("imgTemp\img{0}.bmp", count); Image img = image; Bitmap org = new Bitmap(img, 866, 520); Bitmap target = org.Clone(new Rectangle(0, 0, 866, 520), PixelFormat.Format1bppIndexed); // 将图片转换为单色,并调整为该尺寸 target.SetResolution(1, 1); if (File.Exists(name)) { GC.Collect(); GC.WaitForPendingFinalizers(); File.Delete(name); target.Save(name, ImageFormat.Bmp); target.Dispose(); } else { target.Save(name, ImageFormat.Bmp); target.Dispose(); } lbFicheiros.Items.Add(name); }
问题分析与修正方案
原代码存在的问题
- 逻辑顺序错误:先将原图缩放到866×520,再裁剪相同尺寸的区域,实际没有执行裁剪操作,仅完成了缩放和格式转换。若原图尺寸大于目标裁剪尺寸,应先裁剪再处理格式。
- 资源释放不严谨:依赖
GC.Collect()强制回收资源来删除文件,这种方式不可靠,容易引发文件占用异常。 - 分辨率设置不合理:
SetResolution(1,1)将图片分辨率设为1dpi,会导致后续使用图片时出现显示或兼容性问题。
修正后的代码
private void Converter(Image image, int count) { string outputPath = Path.Combine("imgTemp", $"img{count}.bmp"); // 确保输出目录存在,避免路径错误 Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); using (Bitmap originalBitmap = new Bitmap(image)) { // 检查原图尺寸,避免因原图过小导致裁剪异常 int cropWidth = Math.Min(866, originalBitmap.Width); int cropHeight = Math.Min(520, originalBitmap.Height); // 从原图裁剪(0,0)起始的目标区域 using (Bitmap croppedBitmap = originalBitmap.Clone(new Rectangle(0, 0, cropWidth, cropHeight), originalBitmap.PixelFormat)) { // 转换为单色1bppIndexed格式 using (Bitmap targetBitmap = ConvertTo1bppIndexed(croppedBitmap)) { // 保留原图分辨率 targetBitmap.SetResolution(image.HorizontalResolution, image.VerticalResolution); // 安全删除已存在的文件 if (File.Exists(outputPath)) { File.Delete(outputPath); } targetBitmap.Save(outputPath, ImageFormat.Bmp); } } } lbFicheiros.Items.Add(outputPath); } // 单独实现1bppIndexed格式转换,提升兼容性 private Bitmap ConvertTo1bppIndexed(Bitmap sourceBitmap) { Bitmap targetBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height, PixelFormat.Format1bppIndexed); targetBitmap.SetResolution(sourceBitmap.HorizontalResolution, sourceBitmap.VerticalResolution); using (Graphics g = Graphics.FromImage(targetBitmap)) { g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.DrawImage(sourceBitmap, new Rectangle(0, 0, targetBitmap.Width, targetBitmap.Height)); } return targetBitmap; }
核心改进点
- 调整逻辑顺序:先裁剪原图指定区域,再进行格式转换,确保裁剪效果符合预期
- 使用
using语句自动释放图像资源,彻底避免资源泄漏和文件占用问题 - 增加尺寸检查,防止原图小于裁剪尺寸时出现异常
- 单独实现格式转换方法,解决
Clone方法转换1bppIndexed格式的兼容性问题 - 保留原图分辨率,避免不必要的异常
内容的提问来源于stack exchange,提问作者Tomás Moreira
相关产品推荐
相关产品推荐

