修剪位图导致底部文本被切割

Trimming Bitmap Causes Cutting of Text at Bottom

我正在使用以下代码删除图像周围的空白。

  static Bitmap TrimBitmap(Bitmap source)
        {
            Rectangle srcRect = default(Rectangle);
            BitmapData data = null;
            try
            {
                data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
                byte[] buffer = new byte[data.Height * data.Stride];
                Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);

                int xMin = int.MaxValue,
                    xMax = int.MinValue,
                    yMin = int.MaxValue,
                    yMax = int.MinValue;

                bool foundPixel = false;

                // Find xMin
                for (int x = 0; x < data.Width; x++)
                {
                    bool stop = false;
                    for (int y = 0; y < data.Height; y++)
                    {
                        byte alpha = buffer[y * data.Stride + 4 * x + 3];
                        if (alpha != 0)
                        {
                            xMin = x;
                            stop = true;
                            foundPixel = true;
                            break;
                        }
                    }
                    if (stop)
                        break;
                }

                // Image is empty...
                if (!foundPixel)
                    return null;

                // Find yMin
                for (int y = 0; y < data.Height; y++)
                {
                    bool stop = false;
                    for (int x = xMin; x < data.Width; x++)
                    {
                        byte alpha = buffer[y * data.Stride + 4 * x + 3];
                        if (alpha != 0)
                        {
                            yMin = y;
                            stop = true;
                            break;
                        }
                    }
                    if (stop)
                        break;
                }

                // Find xMax
                for (int x = data.Width - 1; x >= xMin; x--)
                {
                    bool stop = false;
                    for (int y = yMin; y < data.Height; y++)
                    {
                        byte alpha = buffer[y * data.Stride + 4 * x + 3];
                        if (alpha != 0)
                        {
                            xMax = x;
                            stop = true;
                            break;
                        }
                    }
                    if (stop)
                        break;
                }

                // Find yMax
                for (int y = data.Height - 1; y >= yMin; y--)
                {
                    bool stop = false;
                    for (int x = xMin; x <= xMax; x++)
                    {
                        byte alpha = buffer[y * data.Stride + 4 * x + 3];
                        if (alpha != 0)
                        {
                            yMax = y;
                            stop = true;
                            break;
                        }
                    }
                    if (stop)
                        break;
                }
                srcRect = Rectangle.FromLTRB(xMin, yMin, xMax , yMax);
            }
            finally
            {
                if (data != null)
                    source.UnlockBits(data);
            }

            Bitmap dest = new Bitmap(srcRect.Width, srcRect.Height);
            Rectangle destRect = new Rectangle(0, 0, srcRect.Width, srcRect.Height);
            using (Graphics graphics = Graphics.FromImage(dest))
            {
                graphics.DrawImage(source, destRect, srcRect, GraphicsUnit.Pixel);
            }
            return dest;
        }

我正在尝试 trim 在 it.The 上绘制文本的位图 trimming

后正确的图像应该看起来像这样

但是在 trimming 之后我得到了以下结果..底部被剪掉了

我做错了什么?请指教..

这其实是Rectangle.FromLTRB的问题!

仔细观察图像,您会发现实际上只丢失了 行像素。 (强大的放大倍数把我骗了一阵子。。)

确定矩形高(和宽)的算法基本正确,但差了一个

如果你使用这个

srcRect = Rectangle.FromLTRB(xMin, yMin, xMax + 1 , yMax + 1);

或者这个:

srcRect = new Rectangle(xMin, yMin, xMax - xMin + 1 , yMax - yMin + 1);

应该可以。

您可以用笔和纸进行测试:假设:颜色为 4 的第一个像素行,从底部开始在一个 10 像素的正方形上:8,这使得 5 而不是 4 净数据:4,5,6,7 ,8.

请注意,此问题 FromLTRB 中是固有的:

Rectangle myRectangle = Rectangle.FromLTRB(0, 0, 10, 10);

..结果是 RectangleHeight=10,即使 0..10 应该覆盖 11 像素行!所以 Right-Bottom 坐标实际上从结果中 排除 !!

我认为矩形相差一个的整个问题源于 legacy ways to use a Pen with its alignment。当使用相同的矩形填充 Brush 时,一切都按预期工作。