在 C# 中从图像中裁剪空白 [重复]

Posted

技术标签:

【中文标题】在 C# 中从图像中裁剪空白 [重复]【英文标题】:Cropping whitespace from image in C# [duplicate] 【发布时间】:2011-11-08 21:35:41 【问题描述】:

可能重复:Remove surrounding whitespace from an image

我正在寻求帮助以裁剪图像顶部、底部、左侧和右侧的空白。

我找到了following question/answer on SO,但是带有答案的链接是第三方网站,该网站似乎不再可用。

【问题讨论】:

您是在寻找第三方库还是本机代码。遍历边缘检查空白区域然后调整图像大小非常容易,但并不是真正的最佳选择。有第三方库会以更优化的方式为您包含此类功能。 我对第三方库没有意见 - 因为这是一个内部项目,所以最好没有成本。 查看this answer。它假定透明空白,但您可以根据需要轻松调整逻辑 【参考方案1】:

找到解决方案here,但修改了返回代码部分以允许输入空图像,在这种情况下将返回原始图像。

class ImageCrop

    public static byte[][] GetRGB(Bitmap bmp)
    
        BitmapData bmp_data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
        IntPtr ptr = bmp_data.Scan0;
        int num_pixels = bmp.Width * bmp.Height, num_bytes = bmp_data.Stride * bmp.Height, padding = bmp_data.Stride - bmp.Width * 3, i = 0, ct = 1;
        byte[] r = new byte[num_pixels], g = new byte[num_pixels], b = new byte[num_pixels], rgb = new byte[num_bytes];
        System.Runtime.InteropServices.Marshal.Copy(ptr, rgb, 0, num_bytes);

        for (int x = 0; x < num_bytes - 3; x += 3)
        
            if (x == (bmp_data.Stride * ct - padding))  x += padding; ct++; ;
            r[i] = rgb[x]; g[i] = rgb[x + 1]; b[i] = rgb[x + 2]; i++;
        
        bmp.UnlockBits(bmp_data);
        return new byte[3][]  r, g, b ;
    
    public static Image AutoCrop(Bitmap bmp)
    
        //Get an array containing the R,G,B components of each pixel
        var pixels = GetRGB(bmp);

        int h = bmp.Height - 1, w = bmp.Width, top = 0, bottom = h, left = bmp.Width, right = 0, white = 0;
        int tolerance = 95; // 95%

        bool prev_color = false;
        for (int i = 0; i < pixels[0].Length; i++)
        
            int x = (i % (w)), y = (int)(Math.Floor((decimal)(i / w))), tol = 255 * tolerance / 100;
            if (pixels[0][i] >= tol && pixels[1][i] >= tol && pixels[2][i] >= tol)  white++; right = (x > right && white == 1) ? x : right; 
            else  left = (x < left && white >= 1) ? x : left; right = (x == w - 1 && white == 0) ? w - 1 : right; white = 0; 
            if (white == w)  top = (y - top < 3) ? y : top; bottom = (prev_color && x == w - 1 && y > top + 1) ? y : bottom; 
            left = (x == 0 && white == 0) ? 0 : left; bottom = (y == h && x == w - 1 && white != w && prev_color) ? h + 1 : bottom;
            if (x == w - 1)  prev_color = (white < w) ? true : false; white = 0; 
        
        right = (right == 0) ? w : right; left = (left == w) ? 0 : left;

        //Crop the image
        if (bottom - top > 0)
        
            Bitmap bmpCrop = bmp.Clone(new Rectangle(left, top, right - left + 1, bottom - top), bmp.PixelFormat);

            return (Bitmap)(bmpCrop);
        
        else
        
            return bmp;
        
    



【讨论】:

伟大的工作,应该有更多的赞成票。 我遇到了与传递到 .Clone() 调用的无效维度相关的“内存不足”异常的问题。您可以在***.com/questions/199468/… 找到更多信息。当整个图像应该被裁剪时,“右 - 左 + 1”中的 +1 似乎是一个错误。最后,我写了我自己的这个方法版本,它更清晰一点,使用更少的内存,但牺牲了简洁性。您可以在链接的副本中找到它。 效果不佳。我用了这个***.com/questions/4820212/…,效果很好!!也超级快!

以上是关于在 C# 中从图像中裁剪空白 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

C#,当我在 Windows 窗体应用程序中发送电子邮件时,图像显示为空白 [重复]

裁剪后python pdf空白[重复]

在 C# 中从项目的资源区域加载图像

在 C# 中使用 TextureBrush 重复采样图像

在 C# 中从 XML 中获取某个元素 [重复]

C#如何在不使用大量内存的情况下裁剪图像? [复制]