BMP 文件 C 实现

BMP File C implementation

我正在尝试用C实现创建图像文件。我想要的图像格式是RGB565。我已经关注了这两个网站 1 2 以尝试获取可查看的图像,但我似乎无法正常工作。 "fwrite" 函数中的问题是因为小字节序的问题吗?

出于测试目的,我想要一张 16*4 大且所有像素颜色相同的图像。 (代码很乱,因为它只是为了在更大的项目中实现之前进行测试。

    #include <stdio.h>
    #include <stdint.h>
    #include <stdlib.h>

int main() {
    uint16_t myData[64];
    for(int i = 0; i<64; i++)
    {
        myData[i] = 0x241B; //Random Color
    }

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

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

BITMAPFILEHEADER myFileHeader = {0x4D42, 198, 0, 0, 70};

BITMAPINFOHEADER myInfoHeader = {40, 16, 4, 1, 16, 0, 0, 1000, 1000, 0, 0};

uint32_t RGB565ColorTable[] = {0x7E00000, 0xF8000000, 0x001F0000, 0}; 



   FILE *fptr;    fptr = fopen("testImage.bmp","w+");

   if(fptr == NULL)    {
      printf("Error!");   
      exit(1);                 }

    fwrite(&myFileHeader, sizeof(BITMAPFILEHEADER), 1, fptr); 
    fwrite(&myInfoHeader, sizeof(BITMAPINFOHEADER), 1, fptr); 
    fwrite(&RGB565ColorTable, sizeof(RGB565ColorTable), 1, fptr); 
    fwrite(&myData, sizeof(myData), 1, fptr); 
    fclose(fptr);

    return 0; }

十六进制输出(在将 attribute((packed)) 添加到结构之后):

您需要打包文件头结构,以便编译器不会填充条目。在定义结构来完成此操作时,您可以将 __attribute__((packed)) 与 gcc 一起使用。

我确实清理了代码。看起来它正在运行:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct        /**** BMP file header structure ****/
{
    uint16_t bfType;           /* Magic number for file */
    uint32_t bfSize;           /* Size of file */
    uint16_t bfReserved1;      /* Reserved */
    uint16_t bfReserved2;      /* ... */
    uint32_t bfOffBits;        /* Offset to bitmap data */
} __attribute__((packed)) BITMAPFILEHEADER;

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

int main()
{
    FILE *fptr;

    BITMAPFILEHEADER myFileHeader = {
        .bfType = 0x4D42,
        .bfSize = 198,
        .bfOffBits = 70
    };

    BITMAPINFOHEADER myInfoHeader = {
        .biSize = 40,
        .biWidth = 16,
        .biHeight = 4,
        .biPlanes = 1,
        .biBitCount = 16,
        .biCompression = 0,
        .biSizeImage = 0,
        .biXPelsPerMeter = 1000,
        .biYPelsPerMeter = 1000,
        .biClrUsed = 0,
        .biClrImportant = 0
    };

    uint32_t RGB565ColorTable[] = {
        0x7E00000, 0xF8000000, 0x001F0000, 0
    };

    uint16_t myData[64];

    for(int i = 0; i<64; i++)
    {
        myData[i] = 0x241B; //Random Color
    }

    fptr = fopen("testImage.bmp","w+");

    if(fptr == NULL) {
        printf("Error!");
        exit(1);
    }

    fwrite(&myFileHeader, sizeof(myFileHeader), 1, fptr);
    fwrite(&myInfoHeader, sizeof(myInfoHeader), 1, fptr);
    fwrite(&RGB565ColorTable, sizeof(RGB565ColorTable), 1, fptr);
    fwrite(&myData, sizeof(myData), 1, fptr);
    fclose(fptr);

    return 0;
}

我确实有以下输出:

hexdump -C testImage.bmp
00000000  42 4d c6 00 00 00 00 00  00 00 46 00 00 00 28 00  |BM........F...(.|
00000010  00 00 10 00 00 00 04 00  00 00 01 00 10 00 00 00  |................|
00000020  00 00 00 00 00 00 e8 03  00 00 e8 03 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  e0 07 00 00 00 f8 00 00  |................|
00000040  1f 00 00 00 00 00 1b 24  1b 24 1b 24 1b 24 1b 24  |.......$.$.$.$.$|
00000050  1b 24 1b 24 1b 24 1b 24  1b 24 1b 24 1b 24 1b 24  |.$.$.$.$.$.$.$.$|
*
000000c0  1b 24 1b 24 1b 24                                 |.$.$.$|

使用 MSVC,您可以将结构包含在

#pragma pack(push, 1)
// struct
#pragma pack(pop)

让它打包。我发现只有 BITMAPFILEHEADER 在 32 位编译中才需要它。