关于c#:将位图转换为特殊的灰度字节数组

Converting bitmap to special gray scale byte array

我需要在内存中创建一个图像(可以是巨大的图像!)从中提取宽度x高度的字节数组。每个字节的值必须为0-255(256个灰度值:白色为0,黑色为255)。创建图像的部分很容易,下面是我的代码的一个简单示例:

1
2
3
4
img = new Bitmap(width, height);
drawing = Graphics.FromImage(img);
drawing.Clear(Color.Black);// paint the background
drawing.DrawString(text, font, Brushes.White, 0, 0);

问题是将它转换为"我的"特殊灰度字节数组。当我使用除Format8bpindexed之外的任何像素格式时,我从位图中得到的字节数组的大小与我需要的大小(宽度*长度)不符,因此我需要一个花费太多时间的转换。当我使用format8bpindexed时,我得到的字节数组非常快并且大小正确,但是每个字节/像素都是0-15。

更改位图调色板没有影响:

1
2
3
4
5
var pal = img.Palette;
for (int i = 1; i < 256; i++){
   pal.Entries[i] = Color.FromArgb(255, 255, 255);
}
img.Palette = pal;

知道怎么做吗?

编辑:完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// assume font can be Times New Roman, size 7500!
static private Bitmap DrawText(String text, Font font)
{
    //first, create a dummy bitmap just to get a graphics object
    var img = new Bitmap(1, 1);
    var drawing = Graphics.FromImage(img);

    //measure the string to see how big the image needs to be
    var textSize = drawing.MeasureString(text, font);

    //free up the dummy image and old graphics object
    img.Dispose();
    drawing.Dispose();

    //create a new image of the right size (must be multiple of 4)
    int width = (int) (textSize.Width/4) * 4;
    int height = (int)(textSize.Height / 4) * 4;
    img = new Bitmap(width, height);

    drawing = Graphics.FromImage(img);

    // paint the background
    drawing.Clear(Color.Black);

    drawing.DrawString(text, font, Brushes.White, 0, 0);

    var bmpData = img.LockBits(new Rectangle(0, 0, img.Width, img.Height),    ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);

    var newBitmap = new Bitmap(width, height, bmpData.Stride, PixelFormat.Format8bppIndexed, bmpData.Scan0);

    drawing.Dispose();

    return newBitmap;
}

private static byte[] GetGrayscleBytesFastest(Bitmap bitmap)
{
    BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
    int numbytes = bmpdata.Stride * bitmap.Height;
    byte[] bytedata = new byte[numbytes];
    IntPtr ptr = bmpdata.Scan0;

    Marshal.Copy(ptr, bytedata, 0, numbytes);

    bitmap.UnlockBits(bmpdata);

    return bytedata;
}


你可能想分两步来完成。首先,创建原始图像的16bpp灰度副本,如"将图像转换为灰度"中所述。

然后,使用适当的颜色表创建8bpp图像,并将16bpp灰度图像绘制到该图像上。这将为您进行转换,将16位灰度值转换为256种不同的颜色。

然后你应该有一个8bpp的图像,有256种不同的灰度。然后可以调用锁位来访问位图位,该位图位将是0到255范围内的索引值。