我想知道是否有办法去除每个扫描线的24位位图生成的填充。
我的意思是这样的:
Original [Pure Cyan 24 Bit BMP]:
FF FF 00 FF FF 00 FF FF **00 00** FF FF 00 FF FF 00 FF FF 00
所需输出[已移除填充]:
FF FF 00 FF FF 00 FF FF **00** FF FF 00 FF FF 00 FF FF 00
以下是获取像素数据的代码。
Bitmap tmp_bitmap = BitmapFromFile;
Rectangle rect = new Rectangle(0, 0, tmp_bitmap.Width, tmp_bitmap.Height);
System.Drawing.Imaging.BitmapData bmpData =
tmp_bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
int length = bmpData.Stride * bmpData.Height;
byte[] bytes = new byte[length];
// Copy bitmap to byte[]
Marshal.Copy(bmpData.Scan0, bytes, 0, length);
tmp_bitmap.UnlockBits(bmpData);
提前谢谢。
答案 0 :(得分:4)
不,你必须自己删除它。添加填充以确保位图中扫描线的起点以4的倍数开始。因此,当像素格式为24bpp时,很可能获得填充,bmp_bitmap.Width * 3只能被4整除。
你需要一个循环来复制每一行。像这样:
byte[] bytes = new byte[bmpData.Width * bmpData.Height * 3];
for (int y = 0; y < bmpData.Height; ++y) {
IntPtr mem = (IntPtr)((long)bmpData.Scan0 + y * bmpData.Stride);
Marshal.Copy(mem, bytes, y * bmpData.Width * 3, bmpData.Width * 3);
}
答案 1 :(得分:0)
您应该逐行复制位图,但跳过填充字节。对此的扩展方法是:
static class BitmapExtensions
{
public static void RemovePadding(this Bitmap bitmap)
{
int bytesPerPixel = Image.GetPixelFormatSize(bitmap.PixelFormat) / 8;
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
var pixels = new byte[bitmapData.Width * bitmapData.Height * bytesPerPixel];
for (int row = 0; row < bitmapData.Height; row++)
{
var dataBeginPointer = IntPtr.Add(bitmapData.Scan0, row * bitmapData.Stride);
Marshal.Copy(dataBeginPointer, pixels, row * bitmapData.Width * bytesPerPixel, bitmapData.Width * bytesPerPixel);
}
Marshal.Copy(pixels, 0, bitmapData.Scan0, pixels.Length);
bitmap.UnlockBits(bitmapData);
}
}
答案 2 :(得分:0)
我为AutoCrop图像创建了扩展方法,并在Left,Top,Right和Bottom中寻找第一个归档像素。然后计算一个矩形。使用Graphics.DrawImage可以通过源和新Rectangle指定裁剪区域。
public static Bitmap AutoCrop(this Bitmap bitmap)
{
int leftSHift = 0;
int topShift = 0;
int rightShift = 0;
int bottomShift = 0;
// left Shift
for (int widthX = 0; widthX < bitmap.Width; widthX++)
{
for (int heightY = 0; heightY < bitmap.Height; heightY++)
{
Color c = bitmap.GetPixel(widthX, heightY);
if (!c.Name.Equals("0"))
{
leftSHift = widthX;
break;
}
}
if (!leftSHift.Equals(0))
break;
}
// Top Shift
for (int widthX = 0; widthX < bitmap.Height; widthX++)
{
for (int heightY = 0; heightY < bitmap.Width - 1; heightY++)
{
Color c = bitmap.GetPixel(heightY, widthX);
if (!c.Name.Equals("0"))
{
topShift = widthX;
break;
}
}
if (!topShift.Equals(0))
break;
}
// Right Shift
for (int heightX = bitmap.Width - 1; heightX >= 0; heightX--)
{
for (int widthY = 0; widthY < bitmap.Height; widthY++)
{
Color c = bitmap.GetPixel(heightX, widthY);
if (!c.Name.Equals("0"))
{
rightShift = heightX;
break;
}
}
if (!rightShift.Equals(0))
break;
}
//Bottom Shift.
for (int heightX = bitmap.Height - 1; heightX >= 0; heightX--)
{
for (int widthY = 0; widthY < bitmap.Width - 1; widthY++)
{
Color c = bitmap.GetPixel(widthY, heightX);
if (!c.Name.Equals("0"))
{
bottomShift = heightX;
break;
}
}
if (!bottomShift.Equals(0))
break;
}
Rectangle cropRect = new Rectangle
(
leftSHift + 1,
topShift,
bitmap.Width - (leftSHift + (bitmap.Width - rightShift)),
bitmap.Height - (topShift + (bitmap.Height - bottomShift))
);
Bitmap src = bitmap;
Bitmap target = new Bitmap(cropRect.Width, cropRect.Height);
using (Graphics g = Graphics.FromImage(target))
{
g.DrawImage(src, new Rectangle(0, 0, target.Width, target.Height), cropRect, GraphicsUnit.Pixel);
}
return target;
}