c# winforms gdi+ - 将图像裁剪为其内容

标签 c# winforms bitmap gdi+ crop

我正在 GDI+ WinForms 中制作一个绘画应用程序,我有一个想要添加的功能,并且已经尝试添加,但我在网上没有找到任何有关它的信息。

我想拍摄一张图像(或位图,并不重要)并将其裁剪到其中所有内容所在的位置。

举个例子:

我这里有一张图片 (Picture of Stickman white a lot of white around it) 它周围有相当多的白色(将图像保存到您的计算机上,看看它周围有白色。)我想将图像裁剪到火柴人所在的区域,我希望它看起来像像这样:

(Cropped stickman)

(将其保存到您的计算机中,您可以比较两者)

如果你看第二个,这就是我想要制作的,它已将图像缩减为只有火柴人!

但是,当然,我自己也这么做过。

我在网上查找了很多解决方案,但找不到,所以我决定尝试自己做,但没有成功。

这是我尝试过的:

我有一个带有图片框和按钮的简单表单 - 单击按钮后,它应该向下裁剪图像。我将图片框的背景颜色设置为黑色,并将其置于图像中心,以便图像中不再存在的区域为黑色。

图像存储在名为 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 并更改高度...

如果它位于矩形的右侧,它将更改宽度以匹配。

如果它位于矩形的底部,它将更改高度以匹配。

如果它在矩形内部,它根本不会关心。

我不明白为什么这个功能不起作用。

加载表单时,它运行以下代码:

ImageToChange = Properties.Resources.stickman;

        pictureBox1.Image = ImageToChange;

我将未受影响的火柴人放入 Properties.Resources.stickman 中。

然后单击它运行的按钮:

ImageToChange = CropToContent(ImageToChange);

        pictureBox1.Image = ImageToChange;

我不明白为什么这行不通,如果您阅读了整篇文章,我将非常感谢。

最佳答案

我对你所说的“不起作用”的意思有点了解,但我想我发现了问题。

错误在于您的逻辑中,例如修改矩形右侧的代码行:

if (x > (currentRect.X + currentRect.Width)) currentRect.Width += ((currentRect.X + currentRect.Width) + x);

这通过添加 x、矩形.X 和矩形.Width 来修改检测到的矩形的宽度,这是错误的。你想要的可能是这样的:

if (x > (currentRect.X + currentRect.Width)) currentRect.Width = x - currentRect.X;

您将需要对其余逻辑进行类似的更改。

关于c# winforms gdi+ - 将图像裁剪为其内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46022742/

相关文章:

c# - LINQ 从一个集合中获取不属于另一个集合的元素

c# - Linq 查询列表包含具有相同顺序的列表

c# - 通过代理服务器连接MySQL

c# - 使用 Winforms 在 C# 中将对象字符串转换为对象(类)

c# - 使用 picturebox 或类似控件制作 2d 平铺编辑器

c# - 具有常量的 Fluent NHibernate 引用

.net - WebBrowser 控件报告什么 UserAgent?

winforms - Windows 窗体应用程序中的.设置文件,最佳实践

c# - 来自 Stream : Bug? 的位图

c# - 根据亮度设置黑白像素