Реализация файла BMP C - PullRequest
       14

Реализация файла BMP C

0 голосов
/ 30 апреля 2018

Я пытаюсь создать файл изображения на языке 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; }

Hex Output (после добавления атрибута ((упакованный)) к структурам): enter image description here

Ответы [ 3 ]

0 голосов
/ 30 апреля 2018

Я очистил код. И похоже, что это работает:

#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                                 |.$.$.$|
0 голосов
/ 30 апреля 2018

С MSVC вы можете заключить структуру с

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

чтобы сделать его упакованным. Я обнаружил, что это необходимо только для BITMAPFILEHEADER в 32-разрядной компиляции.

0 голосов
/ 30 апреля 2018

Вам необходимо упаковать структуру заголовка файла, чтобы компилятор не дополнял записи. Вы можете использовать __attribute__((packed)) с gcc при определении структур, чтобы выполнить это.

...