Создание BMP-файла (растрового изображения) в C

Я пытаюсь сделать bitmap на C, только из кода. В настоящее время я пытаюсь сделать очень легкое изображение .bmp с высотой 1 пиксель и шириной 4 пикселя со всеми белыми пикселями. Я прочитал описание формата и попытался применить его. Это привело к следующему коду:

char bitmap[1000]; void BMPmake() { // -- FILE HEADER -- // // bitmap signature bitmap[0] = 'B'; bitmap[1] = 'M'; // file size bitmap[2] = 66; // 40 + 14 + 12 bitmap[3] = 0; bitmap[4] = 0; bitmap[5] = 0; // reserved field (in hex. 00 00 00 00) for(int i = 6; i < 10; i++) bitmap[i] = 0; // offset of pixel data inside the image for(int i = 10; i < 14; i++) bitmap[i] = 0; // -- BITMAP HEADER -- // // header size bitmap[14] = 40; for(int i = 15; i < 18; i++) bitmap[i] = 0; // width of the image bitmap[18] = 4; for(int i = 19; i < 22; i++) bitmap[i] = 0; // height of the image bitmap[22] = 1; for(int i = 23; i < 26; i++) bitmap[i] = 0; // reserved field bitmap[26] = 1; bitmap[27] = 0; // number of bits per pixel bitmap[28] = 24; // 3 byte bitmap[29] = 0; // compression method (no compression here) for(int i = 30; i  4 pixels bitmap[35] = 0; bitmap[36] = 0; bitmap[37] = 0; // horizontal resolution of the image - pixels per meter (2835) bitmap[38] = 0; bitmap[39] = 0; bitmap[40] = 0b00110000; bitmap[41] = 0b10110001; // vertical resolution of the image - pixels per meter (2835) bitmap[42] = 0; bitmap[43] = 0; bitmap[44] = 0b00110000; bitmap[45] = 0b10110001; // color pallette information for(int i = 46; i < 50; i++) bitmap[i] = 0; // number of important colors for(int i = 50; i < 54; i++) bitmap[i] = 0; // -- PIXEL DATA -- // for(int i = 54; i < 66; i++) bitmap[i] = 0; } void BMPwrite() { FILE *file; file = fopen("bitmap.bmp", "w+"); for(int i = 0; i < 66; i++) { fputc(bitmap[i], file); } fclose(file); } 

Когда я пытаюсь открыть это изображение, он говорит, что изображение повреждено. Я что-то упустил?

Я также заметил, что кодирование целых чисел .bmp мало ориентировано. Я думал, что это означает, что я должен изменить порядок байтов. Например, 256 байтов в четырех байтах: 00000000 00000000 00000001 00000000, и я думаю, что это мало, это будет: 00000000 00000001 00000000 00000000

Может ли кто-нибудь дать мне руку здесь? Я использую правильный подход? Любая помощь будет оценена!

Заранее спасибо!

Ваше смещение пикселей (байт 10..13) равно нулю, но данные пикселя фактически не начинаются в начале файла, они начинаются с байта 54.

Также:

  • Ваш комментарий к бабу 34 говорит «бит», но означает «байты», но, конечно, это не имеет значения.

  • У ваших горизонтальных и вертикальных разрешений есть неправильный порядок байтов, но я очень сомневаюсь, что это имеет значение.

Если бы я делал это, я бы определил структуры для данных заголовка (действительно, если вы в Windows, Microsoft уже это сделала) и используйте макрос или что-то для правильного расположения байтов в правильном порядке.

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

Вот код, протестированный на linux.

 #include  #include  #include  #include  #define _height 600 #define _width 800 #define _bitsperpixel 24 #define _planes 1 #define _compression 0 #define _pixelbytesize _height*_width*_bitsperpixel/8 #define _filesize _pixelbytesize+sizeof(bitmap) #define _xpixelpermeter 0x130B //2835 , 72 DPI #define _ypixelpermeter 0x130B //2835 , 72 DPI #define pixel 0xFF #pragma pack(push,1) typedef struct{ uint8_t signature[2]; uint32_t filesize; uint32_t reserved; uint32_t fileoffset_to_pixelarray; } fileheader; typedef struct{ uint32_t dibheadersize; uint32_t width; uint32_t height; uint16_t planes; uint16_t bitsperpixel; uint32_t compression; uint32_t imagesize; uint32_t ypixelpermeter; uint32_t xpixelpermeter; uint32_t numcolorspallette; uint32_t mostimpcolor; } bitmapinfoheader; typedef struct { fileheader fileheader; bitmapinfoheader bitmapinfoheader; } bitmap; #pragma pack(pop) int main (int argc , char *argv[]) { FILE *fp = fopen("test.bmp","wb"); bitmap *pbitmap = (bitmap*)calloc(1,sizeof(bitmap)); uint8_t *pixelbuffer = (uint8_t*)malloc(_pixelbytesize); strcpy(pbitmap->fileheader.signature,"BM"); pbitmap->fileheader.filesize = _filesize; pbitmap->fileheader.fileoffset_to_pixelarray = sizeof(bitmap); pbitmap->bitmapinfoheader.dibheadersize =sizeof(bitmapinfoheader); pbitmap->bitmapinfoheader.width = _width; pbitmap->bitmapinfoheader.height = _height; pbitmap->bitmapinfoheader.planes = _planes; pbitmap->bitmapinfoheader.bitsperpixel = _bitsperpixel; pbitmap->bitmapinfoheader.compression = _compression; pbitmap->bitmapinfoheader.imagesize = _pixelbytesize; pbitmap->bitmapinfoheader.ypixelpermeter = _ypixelpermeter ; pbitmap->bitmapinfoheader.xpixelpermeter = _xpixelpermeter ; pbitmap->bitmapinfoheader.numcolorspallette = 0; fwrite (pbitmap, 1, sizeof(bitmap),fp); memset(pixelbuffer,pixel,_pixelbytesize); fwrite(pixelbuffer,1,_pixelbytesize,fp); fclose(fp); free(pbitmap); free(pixelbuffer); } 

Откройте файл с шестнадцатеричным редактором, чтобы увидеть, что на самом деле существует. Это поможет вам определить, делает ли ваш код что-то неожиданное.