从RGB BMP创建灰度BMP

时间:2013-12-09 21:03:10

标签: c++ c bitmap

我有24位图像,我读取位图并将其转换为灰度并保存为8位。

RGBTRIPLE temp;
unsigned char t;
...
t = (temp.rgbtBlue * 0.114 + temp.rgbtGreen * 0.587 + temp.rgbtRed * 0.299);
fwrite(&t, sizeof(UCHAR), 1, newFile);

在图片没有打开之后,我明白我必须改变标题。 我尝试在标题中更改文件的大小和位图的大小,但它没有工作。

BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
...
bfh.bfSize = sizeof(UCHAR) * img.Width * img.Height + bfh.bfOffBits;
bih.biSizeImage = sizeof(UCHAR) * img.Width * img.Height;
bih.biCompression = BI_BITFIELDS;
bih.biBitCount = 8;

我需要更改保存图像,例如8位BMP吗?

2 个答案:

答案 0 :(得分:2)

实际上,最简单的方法是不更改标题中的任何内容。您读取3个值(RGB),使用标准PAL / NTSC公式将它们转换为灰色,然后您可以将计算出的灰度值输出3次。这样,你再次得到1个像素,但值改变了。

您只是简单地更改标题不起作用,因为对于8位颜色索引图像,您还需要提供颜色索引图 - 调色板。此外,根据原始图片尺寸,您可能需要更改每行的 stride (这就是所谓的 - Google也是您的朋友!)。

正如Mark Setchell所说,BI_BITFIELDS不是你需要的(Wikipedia on BMP)。将BI_RGB用于真彩色或彩色索引图像;其他值非常专门 - 我从来没有见过它们“在野外”。

答案 1 :(得分:1)

如果使用Gdiplus类Bitmap的成员函数ConvertFormat,它将更加容易

void GrayScale(Bitmap* bmp)
{
    void* p = malloc(sizeof(Gdiplus::ColorPalette) + 255 * sizeof(ARGB));
    Gdiplus::ColorPalette *cpal = (Gdiplus::ColorPalette*)p;
    for (int i = 0; i < 256; i++) cpal->Entries[i] = Color::MakeARGB(0, i, i, i);
    cpal->Flags = PaletteFlagsGrayScale;
    cpal->Count = 256;
    bmp->ConvertFormat(PixelFormat8bppIndexed, DitherTypeSolid, PaletteTypeCustom, cpal, 0);
    free(p);
}