修剪位图导致底部文本被切割
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);
..结果是 Rectangle
和 Height=10
,即使 0..10
应该覆盖 11
像素行!所以 Right-Bottom
坐标实际上从结果中 排除 !!
我认为矩形相差一个的整个问题源于 legacy ways to use a Pen with its alignment。当使用相同的矩形填充 Brush
时,一切都按预期工作。
我正在使用以下代码删除图像周围的空白。
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);
..结果是 Rectangle
和 Height=10
,即使 0..10
应该覆盖 11
像素行!所以 Right-Bottom
坐标实际上从结果中 排除 !!
我认为矩形相差一个的整个问题源于 legacy ways to use a Pen with its alignment。当使用相同的矩形填充 Brush
时,一切都按预期工作。