2

生のバイトの配列があり、それらのバイトから bmp ファイルを作成したいと考えています。つまり、ビットマップ ヘッダー構造体などを埋めてから、バイトを書き留めて、適切な形式の bmp ファイルを作成する必要があります。

これは簡単なチェックにのみ必要なので、これを行うための移植可能な方法があるかどうか疑問に思います-生のバイトを取得して、それらをbmpファイルとして保存します。Unixで書いているので、どのWindowsバージョンでも機能しません。

または、これらのバイトを他の画像形式として保存することもできます。必要なのは、結果の画像をざっと見るだけです。

4

6 に答える 6

5

これは私が.bmpグレースケール画像に使用するコードです

カラービットマップとして保存するには、パレットを使用しないように注意してください(24ビットの場合)

void SaveBitmapToFile( BYTE* pBitmapBits, LONG lWidth, LONG lHeight,WORD wBitsPerPixel, LPCTSTR lpszFileName )
{
    RGBQUAD palette[256];
    for(int i = 0; i < 256; ++i)
    {
        palette[i].rgbBlue = (byte)i;
        palette[i].rgbGreen = (byte)i;
        palette[i].rgbRed = (byte)i;
    }

    BITMAPINFOHEADER bmpInfoHeader = {0};
    // Set the size
    bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
    // Bit count
    bmpInfoHeader.biBitCount = wBitsPerPixel;
    // Use all colors
    bmpInfoHeader.biClrImportant = 0;
    // Use as many colors according to bits per pixel
    bmpInfoHeader.biClrUsed = 0;
    // Store as un Compressed
    bmpInfoHeader.biCompression = BI_RGB;
    // Set the height in pixels
    bmpInfoHeader.biHeight = lHeight;
    // Width of the Image in pixels
    bmpInfoHeader.biWidth = lWidth;
    // Default number of planes
    bmpInfoHeader.biPlanes = 1;
    // Calculate the image size in bytes
    bmpInfoHeader.biSizeImage = lWidth* lHeight * (wBitsPerPixel/8);

    BITMAPFILEHEADER bfh = {0};
    // This value should be values of BM letters i.e 0x4D42
    // 0x4D = M 0×42 = B storing in reverse order to match with endian

    bfh.bfType = 'B'+('M' << 8);
    // <<8 used to shift ‘M’ to end

    // Offset to the RGBQUAD
    bfh.bfOffBits = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) + sizeof(RGBQUAD) * 256;
    // Total size of image including size of headers
    bfh.bfSize = bfh.bfOffBits + bmpInfoHeader.biSizeImage;
    // Create the file in disk to write
    HANDLE hFile = CreateFile( lpszFileName,GENERIC_WRITE, 0,NULL,
        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);

    if( !hFile ) // return if error opening file
    {
        return;
    }

    DWORD dwWritten = 0;
    // Write the File header
    WriteFile( hFile, &bfh, sizeof(bfh), &dwWritten , NULL );
    // Write the bitmap info header
    WriteFile( hFile, &bmpInfoHeader, sizeof(bmpInfoHeader), &dwWritten, NULL );
    // Write the palette
    WriteFile( hFile, &palette[0], sizeof(RGBQUAD) * 256, &dwWritten, NULL );
    // Write the RGB Data
    if(lWidth%4 == 0)
    {
        WriteFile( hFile, pBitmapBits, bmpInfoHeader.biSizeImage, &dwWritten, NULL );
    }
    else
    {
        char* empty = new char[ 4 - lWidth % 4];
        for(int i = 0; i < lHeight; ++i)
        {
            WriteFile( hFile, &pBitmapBits[i * lWidth], lWidth, &dwWritten, NULL );
            WriteFile( hFile, empty,  4 - lWidth % 4, &dwWritten, NULL );
        }
    }
    // Close the file handle
    CloseHandle( hFile );
}
于 2012-12-06T14:21:59.737 に答える
2

以下は、バイト配列からの.ppm画像を提供します。"P6"、ピクセルあたり3バイトのバイナリ形式を指定しますが、プレーンテキストもサポートされており、さまざまな形式のグレースケールがサポートされています。これを使用する理由は、可能な限り簡単であり、ほとんどの*nixシステムには多数のppmto*ツールがあります:ppmtobmp、ppmtojpeg、...、ppmtopng...名前を付けます。

typedef struct {
    int width;
    int height;
    uint8_t *data;
    size_t size;
} ppm_image;

size_t ppm_save(ppm_image *img, FILE *outfile) {
    size_t n = 0;
    n += fprintf(outfile, "P6\n# THIS IS A COMMENT\n%d %d\n%d\n", 
                 img->width, img->height, 0xFF);
    n += fwrite(img->data, 1, img->width * img->height * 3, outfile);
    return n;
}

ppmtocadもあります...誰が推測したでしょうか?

于 2012-12-06T14:19:43.687 に答える
2

EasyBMPを試してみてください。これはオープンソースのクロスプラットフォーム C++ ライブラリであり、BMP ファイルを作成するのは楽しいものです。

BMP AnImage;
// Set size to 640 × 480
AnImage.SetSize(640,480);
// Set its color depth to 32-bits
AnImage.SetBitDepth(32);

// Set one of the pixels
AnImage(14,18)->Red = 255;
AnImage(14,18)->Green = 255;
AnImage(14,18)->Blue = 255;
AnImage(14,18)->Alpha = 0;

AnImage.WriteToFile("Output.bmp");
于 2013-10-17T12:36:49.043 に答える
2

SOILを使用できます。これは軽量で移植性があり、OpenGL を対象としていますが、画像をロード (および画像を保存) して生データを返すことができます。

使用例を次に示します(SOILサイトから)

   /* load an image as a heightmap, forcing greyscale (so channels should be 1) */
   int width, height, channels;
   unsigned char *ht_map = SOIL_load_image
   (
    "terrain.tga",
    &width, &height, &channels,
    SOIL_LOAD_L
   );

SOIL が提供する読み取り可能な形式は次のとおりです。

Readable Image Formats:
BMP - non-1bpp, non-RLE (from stb_image documentation)
PNG - non-interlaced (from stb_image documentation)
JPG - JPEG baseline (from stb_image documentation)
TGA - greyscale or RGB or RGBA or indexed, uncompressed or RLE
DDS - DXT1/2/3/4/5, uncompressed, cubemaps (can't read 3D DDS files yet)
PSD - (from stb_image documentation)
HDR - converted to LDR, unless loaded with *HDR* functions (RGBE or RGBdivA or RGBdivA2)

編集:必要に応じて、 stb_image (クロスプラットフォームで移植可能) を使用することもできます。これには、すべてのドキュメントなどが単一のファイルに含まれています。

于 2012-12-06T14:06:34.407 に答える
1

Boost GILは、JPG、TIFF、および PNG の読み取り/書き込みをサポートします。

テンプレートを多用しているため、画像フォーマットをライブラリに適合させることができます。それはあなたにとってやり過ぎかもしれません。

于 2012-12-06T14:15:03.343 に答える
-2

WinGDIの typedef を見てくださいBITMAPFILEHEADER。フィールドは簡単です。BITMAPINFOHEADERWORD には 16 ビットの int、DWORD には 32 ビットの int があることを確認してください。RGBRGBRGB を実行している場合...ヘッダーに入力してデータを書き出すのは非常に簡単です...

于 2012-12-06T16:20:33.233 に答える