我正在尝试从图像中删除所有白色或透明像素,留下实际图像(裁剪)。我尝试了一些解决方案,但似乎没有一个有效。有什么建议还是我要花一夜写图像裁剪代码?
6 回答
所以,你想要做的是找到顶部,最左边的非白色/透明像素和底部,最右边的非白色/透明像素。这两个坐标将为您提供一个矩形,然后您可以提取该矩形。
// Load the bitmap
Bitmap originalBitmap = Bitmap.FromFile("d:\\temp\\test.bmp") as Bitmap;
// Find the min/max non-white/transparent pixels
Point min = new Point(int.MaxValue, int.MaxValue);
Point max = new Point(int.MinValue, int.MinValue);
for (int x = 0; x < originalBitmap.Width; ++x)
{
for (int y = 0; y < originalBitmap.Height; ++y)
{
Color pixelColor = originalBitmap.GetPixel(x, y);
if (!(pixelColor.R == 255 && pixelColor.G == 255 && pixelColor.B == 255)
|| pixelColor.A < 255)
{
if (x < min.X) min.X = x;
if (y < min.Y) min.Y = y;
if (x > max.X) max.X = x;
if (y > max.Y) max.Y = y;
}
}
}
// Create a new bitmap from the crop rectangle
Rectangle cropRectangle = new Rectangle(min.X, min.Y, max.X - min.X, max.Y - min.Y);
Bitmap newBitmap = new Bitmap(cropRectangle.Width, cropRectangle.Height);
using (Graphics g = Graphics.FromImage(newBitmap))
{
g.DrawImage(originalBitmap, 0, 0, cropRectangle, GraphicsUnit.Pixel);
}
public Bitmap CropBitmap(Bitmap original)
{
// determine new left
int newLeft = -1;
for (int x = 0; x < original.Width; x++)
{
for (int y = 0; y < original.Height; y++)
{
Color color = original.GetPixel(x, y);
if ((color.R != 255) || (color.G != 255) || (color.B != 255) ||
(color.A != 0))
{
// this pixel is either not white or not fully transparent
newLeft = x;
break;
}
}
if (newLeft != -1)
{
break;
}
// repeat logic for new right, top and bottom
}
Bitmap ret = new Bitmap(newRight - newLeft, newTop - newBottom);
using (Graphics g = Graphics.FromImage(ret)
{
// copy from the original onto the new, using the new coordinates as
// source coordinates for the original
g.DrawImage(...);
}
return ret
}
请注意,此功能会像污垢一样缓慢。 GetPixel()
慢得令人难以置信,并且访问循环内部 的Width
andHeight
属性也很慢。将是这样做的正确方法 - StackOverflow 上有大量示例。Bitmap
LockBits
在 WPF 中,我们有一个 WriteableBitmap 类。这是你要找的吗?如果是这种情况,请查看http://blogs.msdn.com/b/jgalasyn/archive/2008/04/17/using-writeablebitmap-to-display-a-procedural-texture.aspx
每像素检查应该可以解决问题。扫描每一行以从顶部和底部查找空行,扫描每一行以查找左右约束(这可以通过行或列一次完成)。找到约束后 - 将图像的一部分复制到另一个缓冲区。
除此之外,如果您在 WPF 中并且图像周围有多余的空间,请检查图像的属性并确保您的Stretch属性设置为填充。这消除了图像周围的空间。
我找到了一种在大约 10 分钟内批量修剪几千个 .jpg 文件的方法,但我没有在代码中执行此操作。我使用了 Snag-It Editor 的转换功能。我不知道这是否适合您,如果您需要进行一次修剪或者您的需求仍在持续,但对于软件的价格,这不是很多,我认为这是一个不错的解决方法。(我不为 Techsmith 工作或代表 Techsmith。)
乔伊