c#GDI边缘空白检测算法

我正在寻找一种从c#托管的GDI +库中检测 c#位图的边缘空白的解决方案。

图像可以是透明的白色的 ,400x图像中的大多数是8000x8000px,边缘周围有大约2000px的空白。

找出边缘, x,y,高度和宽度坐标的最有效方法是什么? 我尝试逐像素,但发现它很慢。

更新到解决方案 –添加左/右/上/下边界

图像细节中心图像的问题现在裁剪任何透明(0%)或白色(#FFFFFF)像素。

var top = bitmap.Height; var left = bitmap.Width; var right = 0; var bottom = 0; 

 var pData = pData0 + (y * data.Stride) + (x * 4); var xyAlpha = pData[3]; var xyBlue = pData[0]; var xyGreen = pData[1]; var xyRed = pData[2]; if ((xyAlpha > 0) || (xyRed != 255 && xyGreen != 255 && xyBlue != 255)) { if (y  bottom) bottom = y; if (x  right) right = x; } 

 var cropWidth = right - left; var cropHeight = bottom - top; var cropX = top; var cropY = left; var cacheBitmap = new Bitmap(cropWidth, cropHeight, PixelFormat.Format32bppArgb); using (var cacheGraphics = Graphics.FromImage(cacheBitmap)) { cacheGraphics.DrawImage(context.Image, new Rectangle(0, 0, cropWidth, cropHeight), cropX, cropY, cropWidth, cropHeight, GraphicsUnit.Pixel); } 

一个伟大的GDI +资源是Bob Powells GDI + FAQ !

您没有说明如何访问图像中的像素,因此我假设您使用了慢速GetPixel方法。 您可以使用指针和LockBits以更快的方式访问像素: 请参阅Bob Powells对LockBits的解释 – 这将需要一个不安全的代码块 – 如果您不想要这个或者您没有FullTrust,您可以使用此处说明的技巧: J. Dunlap在.NET中的无指点图像处理

下面的代码使用LockBits方法(对于PixelFormat.Format32bppArgb),并将使用发现图像中第一个和最后一个像素的值填充起点和终点,这些像素没有参数颜色中描述的颜色。 该方法还忽略了完全透明的像素,如果您想要检测可见“内容”开始的图像区域,这将非常有用。

  Point start = Point.Empty; Point end = Point.Empty; int bitmapWidth = bmp.Width; int bitmapHeight = bmp.Height; #region find start and end point BitmapData data = bmp.LockBits(new Rectangle(0, 0, bitmapWidth, bitmapHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); try { unsafe { byte* pData0 = (byte*)data.Scan0; for (int y = 0; y < bitmapHeight; y++) { for (int x = 0; x < bitmapWidth; x++) { byte* pData = pData0 + (y * data.Stride) + (x * 4); byte xyBlue = pData[0]; byte xyGreen = pData[1]; byte xyRed = pData[2]; byte xyAlpha = pData[3]; if (color.A != xyAlpha || color.B != xyBlue || color.R != xyRed || color.G != xyGreen) { //ignore transparent pixels if (xyAlpha == 0) continue; if (start.IsEmpty) { start = new Point(x, y); } else if (start.Y > y) { start.Y = y; } if (end.IsEmpty) { end = new Point(x, y); } else if (end.X < x) { end.X = x; } else if (end.Y < y) { end.Y = y; } } } } } } finally { bmp.UnlockBits(data); } #endregion 

我首先要确保使用Patrick描述的LockBits方法。 其次,我检查中间线上的像素,以快速确定边缘。 中间线我的意思是,如果你说例如2000×1000图像,你首先看水平线500(1000个)找到左右限制,然后沿着垂直线1000(2000年)找到顶部和底部限制。 这种方式应该非常快。