gpt4 book ai didi

c++ - 从 RGB 值数组生成 BMP 文件

转载 作者:太空宇宙 更新时间:2023-11-03 10:42:59 24 4
gpt4 key购买 nike

我想从我已经存储的 RGB 值生成一个 BMP 文件。

我在 OS X 上编程,所以我不能使用预定义的 BMP header 。

我已尝试执行以下操作,但预览显示文件已损坏。

void bitmap(Image * image) {

typedef struct /**** BMP file header structure ****/
{
unsigned short bfType; /* Magic number for file */
unsigned int bfSize; /* Size of file */
unsigned short bfReserved1; /* Reserved */
unsigned short bfReserved2; /* ... */
unsigned int bfOffBits; /* Offset to bitmap data */
} BITMAPFILEHEADER;

typedef struct /**** BMP file info structure ****/
{
unsigned int biSize; /* Size of info header */
int biWidth; /* Width of image */
int biHeight; /* Height of image */
unsigned short biPlanes; /* Number of color planes */
unsigned short biBitCount; /* Number of bits per pixel */
unsigned int biCompression; /* Type of compression to use */
unsigned int biSizeImage; /* Size of image data */
int biXPelsPerMeter; /* X pixels per meter */
int biYPelsPerMeter; /* Y pixels per meter */
unsigned int biClrUsed; /* Number of colors used */
unsigned int biClrImportant; /* Number of important colors */
} BITMAPINFOHEADER;

BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;

bfh.bfType = 0x4d42;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bfh.bfOffBits = 0x36;

bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = image->getWidth();
bih.biHeight = image->getHeight();
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biCompression = 0;
bih.biSizeImage = 0;
bih.biXPelsPerMeter = 0x0ec4;
bih.biYPelsPerMeter = 0x0ec4;
bih.biClrUsed = 0;
bih.biClrImportant = 0;

FILE *file = fopen("a.bmp", "wb");
if (!file) {
cout << "File not found";
return;
}

fwrite(&bfh, 1, sizeof(bfh), file);
fwrite(&bih, 1, sizeof(bfh), file);

for (int x = 0; x < image->getWidth(); x++) {
for (int y = 0; y < image->getHeight(); y++) {
float r = image->getPixel(x, y).r;
float g = image->getPixel(x, y).g;
float b = image->getPixel(x, y).b;
fwrite(&r, 1, 1, file);
fwrite(&g, 1, 1, file);
fwrite(&b, 1, 1, file);
}
}
}

我不确定我是否正确理解了结构。我试过阅读它,但我一定遗漏了一些东西。

这是文件的十六进制输出

42 4D 00 02 38 00 00 00 00 00 00 00 36 00 00 00 28 00 00 00 80 02 00 00 E0 01 0000 01 00 18 00 00 00 00 00 00 00 00 00 C4 0E 00 00 C4 0E 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000

最佳答案

这个问题很好,因为它启发了一些陷阱。这是您的代码中的所有问题。通过修复它们,一切都按预期工作:

  • 您的 bfSize 字段不包括位图的大小

  • 一般:BITMAPFILEHEADER 变得很大,因为它以 2 字节值开头,后跟 4 字节值。填充规则表示此结构的第一个字段将为 4 个字节而不是 2 个字节。解决方案:通过将魔数(Magic Number)从 BITMAPFILEHEADER 中排除来单独写入魔数(Magic Number):

    unsigned short magic=0x4d42; //This field is _not_ included in `BITMAPFILEHEADER`
    fwrite(&magic,1,sizeof(magic),file);

    // Write the remaining part of the header (if you did not get an I/O error...)

    这个修改也意味着 BITMAPFILEHEADER::bfSize2+sizeof(BITMAPFILEHADER) + sizeof(BITMAPINFOHEADER)+ biWidth*biHeight*3

    <
  • 您还通过了展位 bfhbihsizeof(bfh),因此完整的 BITMAPINFOHEADER从未写过

  • BMP 文件格式要求每个扫描线都是 DWORD 对齐的,因此根据宽度,您可能需要在每个扫描线后写入零字节

  • 如果您认为第一条扫描线是向上的,那么您的图像是颠倒的,因为您的高度是正数。

  • 位图文件按存储,因此您应该在最内层循环中遍历 x 坐标

  • 您还输入了错误的像素值。你应该写 unsigned char 而不是 float。您写入了正确的大小(1 个字节),但它不会是正确的值:

    unsigned char r = image->getPixel(x, y).r/255; //If 1.0f is white.

    此外,位图是 BGR(A) 而不是 RGB(A)。

假设你有一个很好的宽度,一个有效的例子是

void bitmap()
{
typedef struct /**** BMP file header structure ****/
{
unsigned int bfSize; /* Size of file */
unsigned short bfReserved1; /* Reserved */
unsigned short bfReserved2; /* ... */
unsigned int bfOffBits; /* Offset to bitmap data */
} BITMAPFILEHEADER;

typedef struct /**** BMP file info structure ****/
{
unsigned int biSize; /* Size of info header */
int biWidth; /* Width of image */
int biHeight; /* Height of image */
unsigned short biPlanes; /* Number of color planes */
unsigned short biBitCount; /* Number of bits per pixel */
unsigned int biCompression; /* Type of compression to use */
unsigned int biSizeImage; /* Size of image data */
int biXPelsPerMeter; /* X pixels per meter */
int biYPelsPerMeter; /* Y pixels per meter */
unsigned int biClrUsed; /* Number of colors used */
unsigned int biClrImportant; /* Number of important colors */
} BITMAPINFOHEADER;

BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;

/* Magic number for file. It does not fit in the header structure due to alignment requirements, so put it outside */
unsigned short bfType=0x4d42;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfSize = 2+sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+640*480*3;
bfh.bfOffBits = 0x36;

bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = 640;
bih.biHeight = 480;
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biCompression = 0;
bih.biSizeImage = 0;
bih.biXPelsPerMeter = 5000;
bih.biYPelsPerMeter = 5000;
bih.biClrUsed = 0;
bih.biClrImportant = 0;

FILE *file = fopen("a.bmp", "wb");
if (!file)
{
printf("Could not write file\n");
return;
}

/*Write headers*/
fwrite(&bfType,1,sizeof(bfType),file);
fwrite(&bfh, 1, sizeof(bfh), file);
fwrite(&bih, 1, sizeof(bih), file);

/*Write bitmap*/
for (int y = bih.biHeight-1; y>=0; y--) /*Scanline loop backwards*/
{
for (int x = 0; x < bih.biWidth; x++) /*Column loop forwards*/
{
/*compute some pixel values*/
unsigned char r = 255*((float)x/bih.biWidth);
unsigned char g = 255*((float)y/bih.biHeight);
unsigned char b = 0;
fwrite(&b, 1, 1, file);
fwrite(&g, 1, 1, file);
fwrite(&r, 1, 1, file);
}
}
fclose(file);
}

This is the output

关于c++ - 从 RGB 值数组生成 BMP 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30423590/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com