我正在尝试在图像的顶部和底部添加黑色横幅。我可以添加横幅,但是结果位图的像素格式更改为32位。有没有办法得到一个8位的位图。 如here所述,如果我在构造函数中设置8位pixelFormat,则创建图形将引发异常。 我读到如果将32转换为8,则像素值可能会与原始像素值不同。不知道我是否可以创建具有所需高度的新位图并使用for循环添加黑色横幅的像素。任何人都有更好更好的方法吗?
我的代码如下:
Bitmap img = image as Bitmap;
using (Bitmap bitmap = new Bitmap(img.Width, img.Height + 200*2)) // create blank bitmap of desired size
using (Graphics graphics = Graphics.FromImage(bitmap))
{
SolidBrush brush = new SolidBrush(Color.White);
graphics.FillRectangle(brush, 0, 0, img.Width,200);
// draw existing image onto new blank bitmap
graphics.DrawImage(img, 0, 200, img.Width, img.Height);
// draw your rectangle below the original image
graphics.FillRectangle(brush, 0, 200 + img.Height, img.Width, 200);
// bitmap.Save(@"c:\Test1.bmp");
}
答案 0 :(得分:0)
这是在FillRectangle
位图上执行bmp8bpp
的例程。
您传入一个索引,如果为正,它将用于将颜色放入调色板。如果传递负索引,它将尝试查找颜色;如果找不到负索引,则它将颜色放置在索引的末尾。这将覆盖以前的颜色!
void FillIndexedRectangle(Bitmap bmp8bpp, Rectangle rect, Color col, int index)
{
var pal = bmp8bpp.Palette;
int idx = -1;
if (index >= 0) idx = index;
else
{
if (pal.Entries.Where(x => x.ToArgb() == col.ToArgb()).Any())
idx = pal.Entries.ToList().FindIndex(x => x.ToArgb() == col.ToArgb());
if (idx < 0) idx = pal.Entries.Length - 1;
}
pal.Entries[idx] = col;
bmp8bpp.Palette = pal;
var bitmapData =
bmp8bpp.LockBits(new Rectangle(Point.Empty, bmp8bpp.Size),
ImageLockMode.ReadWrite, bmp8bpp.PixelFormat);
byte[] buffer=new byte[bmp8bpp.Width*bmp8bpp.Height];
Marshal.Copy(bitmapData.Scan0, buffer,0, buffer.Length);
for (int y = rect.Y; y < rect.Bottom; y++)
for (int x = rect.X; x < rect.Right; x++)
{
buffer[x + y * bmp8bpp.Width] = (byte)idx;
}
Marshal.Copy(buffer, 0, bitmapData.Scan0,buffer.Length);
bmp8bpp.UnlockBits(bitmapData);
}
示例调用:
Bitmap img = new Bitmap(200, 200, PixelFormat.Format8bppIndexed);
FillIndexedRectangle(img, new Rectangle(0,0,200, 200), Color.Silver, 21);
FillIndexedRectangle(img, new Rectangle(23, 23, 55, 99), Color.Red, 22);
FillIndexedRectangle(img, new Rectangle(123, 123, 55, 33), Color.Black, 23);
FillIndexedRectangle(img, new Rectangle(1, 1, 123, 22), Color.Orange, 34);
FillIndexedRectangle(img, new Rectangle(27, 27, 16, 12), Color.Black, -1);
img.Save("D:\\__bmp8bpp.png");
结果:
还有改进的空间:
index
,以便下一次调用可以引用它。.对于矩形以外的其他形状,可以使用复制例程,该例程首先将其绘制到“正常”的32bpp位图上,然后将像素传输到缓冲区。
更新:以下几行可添加(**)或更改(*)以允许绘制未填充矩形; stroke 0
填充矩形。.:
void FillIndexedRectangle(Bitmap bmp8bpp, Rectangle rect,
Color col, int index, int stroke) // *
...
...
Marshal.Copy(bitmapData.Scan0, buffer,0, buffer.Length);
Rectangle ri = rect; //**
if (stroke > 0) ri.Inflate(-stroke, -stroke); //**
for (int y = rect.Y; y < rect.Bottom; y++)
for (int x = rect.X; x < rect.Right; x++)
{
if (ri == rect || !ri.Contains(x,y)) //**
buffer[x + y * bmp8bpp.Width] = (byte)idx;
}
Marshal.Copy(buffer, 0, bitmapData.Scan0,buffer.Length);