【发布时间】:2018-02-11 20:19:52
【问题描述】:
我正在 GDI+ WinForms 中制作一个绘图应用程序,我有一个功能我想添加并尝试添加,但我在网上没有找到任何相关信息。
我想拍摄一张图片(或位图,并不重要)并将其裁剪到其中所有内容所在的位置。
我举个例子:
我在这里有一张图片 它周围有很多白色(将图像保存到您的计算机以查看它周围是否有白色。)我想将图像裁剪到火柴人所在的区域,我希望它看起来像这样:
(保存到你的电脑,你可以比较两者)
如果你看一下我想要制作的第二个,它会将图像缩减为只有火柴人!
但是,当然,我自己已经做到了。
我在网上找了很多解决方法,但找不到,所以我决定自己尝试一下,但没有奏效。
这是我尝试过的:
我有一个带有图片框和按钮的简单表单 - 单击按钮后,它应该裁剪图像。我将图片框的 BackColor 设置为黑色,并将图像居中,使图像中不再存在的区域变为黑色。
图像存储在名为ImageToChange 的位图中。
点击按钮后,它应该裁剪图像 - 所以我创建了一个函数来执行我将从按钮调用的操作
这个函数依赖于我在网上找到的另一个函数来裁剪图像:
public Bitmap CropImage(Image source, int x, int y, int width, int height)
{
Rectangle crop = new Rectangle(x, y, width, height);
var bmp = new Bitmap(crop.Width, crop.Height);
using (var gr = Graphics.FromImage(bmp))
{
gr.DrawImage(source, new Rectangle(0, 0, bmp.Width, bmp.Height), crop, GraphicsUnit.Pixel);
}
return bmp;
}
上面的函数应该只是裁剪和图像到给它的 x、y、宽度和高度 - 我没有编写代码,但我可以看到它的作用。
我的CropToContent 函数最后取决于那个。
所以,这是我创建的用于裁剪图像的函数:
public Bitmap CropToContent(Bitmap oldBmp)
{
Rectangle currentRect = new Rectangle();
// Get a base color
for (int y = 0; y < oldBmp.Height; y++)
{
for (int x = 0; x < oldBmp.Width; x++)
{
if (oldBmp.GetPixel(x, y) != Color.White)
{
// We need to interpret this!
if (!currentRect.Contains(new Point(x, y)))
{
// This will run if this is out of the current rectangle
if (x > (currentRect.X + currentRect.Width)) currentRect.Width += ((currentRect.X + currentRect.Width) + x);
if (x < (currentRect.X))
{
// Move the rectangle over there and extend it's width to make the right the same!
int oldRectLeft = currentRect.Left;
currentRect.X = x;
currentRect.Width += oldRectLeft - x;
}
if (y > (currentRect.Y + currentRect.Height)) currentRect.Height += ((currentRect.Y + currentRect.Height) + y);
if (y < (currentRect.Y + currentRect.Height))
{
int oldRectTop = currentRect.Top;
currentRect.Y = y;
currentRect.Height += oldRectTop - y;
}
}
}
}
}
return CropImage(oldBmp, currentRect.X, currentRect.Y, currentRect.Width, currentRect.Height);
}
如你所见,它使用了我前面提到的CropImage函数!
这个函数有一个矩形,图像将被裁剪到 - 随着函数的进行,这个矩形会被修改。
该函数循环遍历位图中的所有像素,如果它不是白色的,它会忽略它 - 如果是其他任何东西,它会根据矩形周围的位置执行某些操作,
如果它在矩形的左侧,它将移动矩形的 X 并更改宽度,因此矩形的右侧仍然是相同的
如果它在矩形的顶部,它将向上移动矩形的 Y 并更改高度...
如果它在矩形的右侧,它将更改宽度以匹配。
如果它位于矩形的底部,它将更改高度以匹配。
如果它在矩形内,它根本不会在意。
我不明白为什么这个功能不起作用。
在Load 的表单上运行此代码:
ImageToChange = Properties.Resources.stickman;
pictureBox1.Image = ImageToChange;
我将未动过的火柴人放入Properties.Resources.stickman。
然后单击它运行的按钮:
ImageToChange = CropToContent(ImageToChange);
pictureBox1.Image = ImageToChange;
我不明白为什么这行不通,如果您阅读全文,非常感谢您。
【问题讨论】:
-
调试代码时总是从小处着手,这张图片的像素太多了,你很容易失去耐心。从 1x1 位图开始,可以很好地检查边界条件。接下来是 3x3,中心有一个像素。然后一个在边缘。然后两个。到那时,您将消除 99% 的错误。
-
好的,那我试试小一点的图片。
标签: c# winforms bitmap gdi+ crop