You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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);
}

问题分析与修正方案

原代码存在的问题

  1. 逻辑顺序错误:先将原图缩放到866×520,再裁剪相同尺寸的区域,实际没有执行裁剪操作,仅完成了缩放和格式转换。若原图尺寸大于目标裁剪尺寸,应先裁剪再处理格式。
  2. 资源释放不严谨:依赖GC.Collect()强制回收资源来删除文件,这种方式不可靠,容易引发文件占用异常。
  3. 分辨率设置不合理: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 20:15:40