18

コードからだけで、C でビットマップを作成しようとしています。現在、高さ 1px、幅 4 ピクセル、すべて白いピクセルの非常に簡単な .bmp 画像を作成しようとしています。フォーマットの説明を読み、それを適用しようとしました。これにより、次のコードが生成されました。

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);
}

この画像を開こうとすると、画像が破損していると表示されます。ここで何か不足していますか?

また、.bmp 整数のエンコーディングがリトル エンディアンであることにも気付きました。これは、バイトの順序を逆にする必要があることを意味すると思いました。たとえば、4 バイトの 256 は 00000000 00000000 00000001 00000000 であり、リトルエンディアンでは次のようになると思います: 00000000 00000001 00000000 00000000

ここで手を貸してくれる人はいますか?正しいアプローチを使用していますか? どんな助けでも大歓迎です!

前もって感謝します!

4

3 に答える 3

10

ピクセルオフセット(バイト10..13)はゼロですが、ピクセルデータは実際にはファイルの先頭から始まるのではなく、バイト54から始まります。

また:

  • バイト34に関するあなたのコメントは「ビット」と言っていますが、「バイト」を意味しますが、もちろんそれは問題ではありません。

  • 水平解像度と垂直解像度のバイト順序が間違っていますが、それが重要かどうかは非常に疑わしいです。

これを行う場合は、ヘッダーデータの構造体を定義し(実際、Windowsを使用している場合は、Microsoftがすでにこれを行っています)、マクロなどを使用して、バイトを移植可能に正しい順序に並べます。

「バイトの順序を逆にする必要がある」かどうかは、使用しているプロセッサのエンディアンによって異なります。あなたがしているように、別々のバイトを別々に書くことは、これについて心配する必要を避けるための効果的な方法です。

于 2012-06-12T21:16:09.097 に答える
7

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);
}
于 2014-04-25T22:06:50.167 に答える
3

16 進エディタでファイルを開いて、実際に何があるかを確認します。これは、コードが予期しないことを行っているかどうかを判断するのに役立ちます。

于 2012-06-12T21:17:29.620 に答える