Création d'un fichier BMP (bitmap) en C

voix
14

Je suis en train de faire un bitmap en C, juste à partir du code. J'essaie actuellement de faire une image .bmp très facile, avec une hauteur de 1px et une largeur de 4 pixels, avec tous les pixels blancs. J'ai lu la description du format et essayé de l'appliquer. Il en est résulté le code suivant:

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 < 34; i++) bitmap[i] = 0;

    // size of pixel data
    bitmap[34] = 12; // 12 bits => 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);
}

Lorsque je tente d'ouvrir cette image, il est dit que l'image est endommagée. Est-ce que j'ai râté quelque chose?

J'ai aussi remarqué que le codage des entiers .bmp est peu endian. Je pensais que cela veut dire que je dois inverser l'ordre des octets. Par exemple, 256 en quatre octets est: 00000000 00000000 00000001 00000000, et je pense que dans peu endian ce serait: 00000000 00000001 00000000 00000000

Quelqu'un peut-il me donner un coup de main? Suis-je utiliser une bonne approche? Toute aide serait appréciée!

Merci d'avance!

Créé 12/06/2012 à 22:05
source utilisateur
Dans d'autres langues...                            


3 réponses

voix
8

Votre décalage pixel (octets 10..13) est égal à zéro, mais les données de pixels ne commencent pas vraiment au début du fichier, ils commencent à l'octet 54.

Aussi:

  • Votre commentaire sur l'octet 34 dit « bits » mais signifie « octets », mais bien sûr cela n'a pas d'importance.

  • Vos résolutions horizontales et verticales ont le mauvais ordre des octets, mais je doute fort que ce qui compte.

Si je faisais cela, je voudrais définir struct pour les données d'en-tête (en effet, si vous êtes sous Windows, Microsoft a déjà fait) et utiliser une macro ou quelque chose pour mettre les octets dans le bon ordre portably.

Que vous « devez inverser l'ordre des octets » dépend du endianity du processeur que vous utilisez. L'écriture d'octets séparés séparément, comme vous faites, est un moyen efficace pour éviter d'avoir à se soucier de cela.

Créé 12/06/2012 à 22:16
source utilisateur

voix
4

Voici le code testé sur Linux.

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <malloc.h>
#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);
}
Créé 25/04/2014 à 23:06
source utilisateur

voix
3

Ouvrez votre fichier avec un éditeur hexadécimal pour voir ce qui est réellement là. Cela vous aidera à déterminer si votre code est en train de faire quelque chose d'inattendu.

Créé 12/06/2012 à 22:17
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more