2

.bmpファイルから各ピクセルのRGB値を読み取りたいのでbmp、GBA(GameBoy Advance)に適した形式に変換できます。

各ピクセルのRGBだけを取得してから、この情報をファイルに書き込む必要があります。

私は<windows.h>構造を使おうとしています:

typedef struct
{
    char signature[2];
    unsigned int fileSize;
    unsigned int reserved;
    unsigned int offset;
}BmpHeader;

typedef struct
{
    unsigned int headerSize;
    unsigned int width;
    unsigned int height;
    unsigned short planeCount;
    unsigned short bitDepth;
    unsigned int compression;
    unsigned int compressedImageSize;
    unsigned int horizontalResolution;
    unsigned int verticalResolution;
    unsigned int numColors;
    unsigned int importantColors;

}BmpImageInfo;

typedef struct
{
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    unsigned char reserved;
}Rgb;

typedef struct
{
    BmpHeader header;
    BmpImageInfo info;
    Rgb colors[256];
    unsigned short image[1];
}BmpFile;

しかし、必要なのはRGB構造体だけです。それで、私が「in.bmp」を読んだとしましょう:

FILE *inFile, *outFile;
inFile = fopen("C://in.bmp", "rb");

Rgb Palette[256];
for(i=0;i<256;i++)
{
   fread(&Palette[i],sizeof(Rgb),1,inFile);
}

fclose(inFile);

これは正しいです?RGB情報のみをファイルに書き込むにはどうすればよいですか?

4

8 に答える 8

4

Windowsを使用している場合は、win32のLoadBitmap関数を使用できます。

次に、ハンドルを指定して、それをDIBビットマップに変換し、その方法でピクセルに到達します

于 2009-10-07T12:19:42.220 に答える
4

私は少しテストを行い、Patriceのプログラムを少し拡張しました。私は優れたCプログラマーではないので、すべての功績は彼にあり、私の部分は彼ほどエレガントではありません-申し訳ありません。

警告:巨大なソースコードが先にあります。

#include <stdio.h>
#pragma pack(2)


typedef struct
{
    char signature[2];
    unsigned int fileSize;
    unsigned int reserved;
    unsigned int offset;
} BmpHeader;

typedef struct
{
    unsigned int headerSize;
    unsigned int width;
    unsigned int height;
    unsigned short planeCount;
    unsigned short bitDepth;
    unsigned int compression;
    unsigned int compressedImageSize;
    unsigned int horizontalResolution;
    unsigned int verticalResolution;
    unsigned int numColors;
    unsigned int importantColors;

} BmpImageInfo;

typedef struct
{
    unsigned char blue;
    unsigned char green;
    unsigned char red;
    //unsigned char reserved; Removed for convenience in fread; info.bitDepth/8 doesn't seem to work for some reason
} Rgb;


int main( int argc, char **argv ) {

    FILE *inFile;
    BmpHeader header;
    BmpImageInfo info;
    Rgb *palette;
    int i = 0;

    printf( "Opening file %s for reading.\n", argv[1] );

    inFile = fopen( argv[1], "rb" );
    if( !inFile ) {
        printf( "Error opening file %s.\n", argv[1] );
        return -1;
    }

    if( fread(&header, 1, sizeof(BmpHeader), inFile) != sizeof(BmpHeader) ) {
        printf( "Error reading bmp header.\n" );
        return -1;
    }

    if( fread(&info, 1, sizeof(BmpImageInfo), inFile) != sizeof(BmpImageInfo) ) {
        printf( "Error reading image info.\n" );
        return -1;
    }

    if( info.numColors > 0 ) {
        printf( "Reading palette.\n" );
        palette = (Rgb*)malloc(sizeof(Rgb) * info.numColors);
        if( fread(palette, sizeof(Rgb), info.numColors, inFile) != (info.numColors * sizeof(Rgb)) ) {
            printf( "Error reading palette.\n" );
            return -1; // error
        }
    }

    printf( "Opening file %s for writing.\n", argv[2] );
    FILE *outFile = fopen( argv[2], "wb" );
    if( !outFile ) {
        printf( "Error opening outputfile.\n" );
        return -1;
    }
    Rgb *pixel = (Rgb*) malloc( sizeof(Rgb) );
    int read, j;
    for( j=0; j<info.height; j++ ) {
        printf( "------ Row %d\n", j+1 );
        read = 0;
        for( i=0; i<info.width; i++ ) {
            if( fread(pixel, 1, sizeof(Rgb), inFile) != sizeof(Rgb) ) {
                printf( "Error reading pixel!\n" );
                return -1;
            }
            read += sizeof(Rgb);
            printf( "Pixel %d: %3d %3d %3d\n", i+1, pixel->red, pixel->green, pixel->blue );
        }
        if( read % 4 != 0 ) {
            read = 4 - (read%4);
            printf( "Padding: %d bytes\n", read );
            fread( pixel, read, 1, inFile );
        }
    }

    printf( "Done.\n" );
    fclose(inFile);
    fclose(outFile);

    printf( "\nBMP-Info:\n" );
    printf( "Width x Height: %i x %i\n", info.width, info.height );
    printf( "Depth: %i\n", (int)info.bitDepth );

    return 0;

}

このプログラムは、ファイルに保存されているピクセル情報を読み取ります。パディングが考慮されますが、ピクセルあたり24ビットの色深度のbmpでのみ機能します(他の深度が必要な場合は、RGB構造体をカスタマイズする必要があります)。これがお役に立てば幸いですが、私が言ったように、これはPatriceのコードの単なる拡張です。

これが私のテストファイルからの出力例です:

$ ./a.out test.bmp out.txt
Opening file test.bmp for reading.
Opening file out.txt for writing.
------ Row 1
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3:   0   0   0
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 2
Pixel 1:   0   0   0
Pixel 2: 232  33  33
Pixel 3:   0   0   0
Pixel 4: 232  33  33
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 3
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3: 232  33  33
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 4
Pixel 1:   0   0   0
Pixel 2: 232  33  33
Pixel 3:   0   0   0
Pixel 4: 232  33  33
Pixel 5:   0   0   0
Padding: 1 bytes
------ Row 5
Pixel 1:   0   0   0
Pixel 2:   0   0   0
Pixel 3:   0   0   0
Pixel 4:   0   0   0
Pixel 5:   0   0   0
Padding: 1 bytes
Done.

BMP-Info:
Width x Height: 5 x 5
Depth: 24

編集:はい、私の画像は赤十字を表示しています。画像は上下逆に保存されるため、ファイルの行1は実際には画像の行5であることに注意してください。D'ohはコードを開くために何かを書くのを忘れましたが、これはあなたに練習問題として残されています;)。

于 2009-10-07T15:32:17.603 に答える
3

まず、埋め込みパレットで使用可能な色の数を取得する必要があります。これは、DIBヘッダーで利用できます。

次に、パレットを含むすべてのカラーコンポーネントを読み取ることができます。

どこを探すべきかを知るために、オフセットなどのすべてのヘッダー情報を見ることができます:http: //en.wikipedia.org/wiki/BMP_file_format

これは機能するはずです:(編集:ファイルに書き込むコードを追加します)

FILE *inFile, *outFile;
BMPHeader header;
BMPImageInfo info;
RGB *palette, *p;
int i = 0;

inFile = fopen("C://in.bmp", "rb");
if( !inFile )
   return;

if( fread(&header, sizeof(BMPHeader), 1, inFile) != 1 )
   return; // Manage error and close file

if( fread&info, sizeof(BMPImageInfo), 1, inFile) != 1 )
   return; // Manage error and close file

if( info.numColors > 0 )
{
   palette = (RGB*)malloc(sizeof(RGB) * info.numColors);
   if( fread(palette, sizeof(RGB), info.numColors, inFile) != info.numColors )
      return; // manage error and close file
}

fclose(inFile)

// Binary method => if read later by another computer
outFile = fopen("path", "wb");
if( !outFile )
   return;

if( fwrite(&info.numColors, sizeof(unsigned int), 1, outFile) != 1 )
   return; // Manage Error and close file

if( fwrite(&palette, sizeof(RGB), info.numColors, outFile) != info.numColors )
   return; // Manage error and close file

fclose(outFile);

// Text method => if read later by human
outFile = fopen("path", "w");
if( !outFile )
   return;

for( i=0; i<info.numColors; ++i )
{
   p = &palette[i];
   if( fprintf(outFile, "R:%d, G:%d, B:%d\n", p->red, p->green, p->blue) < 0 )
      return; // Manage error and close file
}

fclose(outFile);
于 2009-10-07T12:29:16.083 に答える
2

圧縮されていない24bppビットマップであり、その幅が4で割り切れることが保証されている場合は、比較的簡単です。

  1. BmpHeaderファイルの先頭にあるを読んでください。
  2. 求めずに、を読んでくださいBmpImageInfo
  3. ファイルの先頭BmpHeaderから'soffsetバイトを探します。24ビットビットマップにはパレットがないことに注意してください(少なくとも、私たちが気にするパレットはありません)。
  4. BGRトリプレットを読み取ります(この順序で、reserved未使用のメンバーはここにありません)。(BmpImageInfoのメンバー)width * abs(height)トリプレットがあります。覚えているように、heightが正の場合(標準の場合)、最初に読み取る色の行は、画像の一番下の行になり、そこから上に向かっていきます。ただし、が負の場合height、ファイルの最初の色の行は画像の上部で、そこから下に向かっていきます。

これらの保証を行うことができない場合、事態はかなり複雑になります。

免責事項:私はここで自分のホーンを不幸にも使いすぎています。 数年前、私はあなたが話していることを正確に実行するための小さな(1つのソースファイル)ユーティリティをポータブル(100%ANSI C)の方法で作成しました。glbmp libbmpread。そのソースはあなたの問題にいくらかの光を当てるかもしれません-それはどんなビット深度の圧縮されていない(RLEなしの)ビットマップを処理し、GBAでうまく動くはずです。

于 2009-10-07T16:51:32.060 に答える
1

.bmpファイル形式のウィキペディアページを参照してください。このページには、ファイルの構造に関する多くの情報が記載されており、ファイルの解析に役立ちます。

http://en.wikipedia.org/wiki/BMP_file_format

コードでは、最初にデータの開始アドレス(ファイルヘッダーで指定)と画像の高さを読み取る必要があります。次に、この位置を探します。その後、ピクセルごとに1行ずつ読み取り(ヘッダーはピクセルあたりのビット数を指定します)、最後の32ビットのパディングを処理する必要があります。24ビット画像(RGB)では、情報はBGR順に保存されることに注意してください。また、高さの値が負でない場合、画像は上下逆に保存されます。

于 2009-10-07T12:25:51.397 に答える
1

私が何年も前に書いたBMPファイルの読み取りと書き込み用のCコードを見ると、次の場所にあると便利です。

http://david.tribble.com/src/bmp/bmp.html

さまざまなピクセルビットサイズ(1/2/4/8/24)とRLE圧縮を処理できると思います。

于 2009-10-07T20:42:16.823 に答える
0

私はBMPファイル形式に精通していませんが、最初にヘッダー情報を読み取る必要はありませんか?何かのようなもの:

BmpHeader header;
fread(&header,sizeof(BmpHeader),1,inFile);

必要な詳細な画像情報を読みます。

BmpImageInfo info;
fread(&info,sizeof(BmpImageInfo),1,inFile);

パレット情報も読み込みます。

それができたら、ファイルサイズとデータオフセットがわかります。十分なスペースを事前に割り当てて、一度にすべてを読み込むことができます。これが最も簡単な場合があります。または、チャンクで読み込んで、進行中に解析することもできます(十分なメモリがない可能性は低くなりますが、解析はより複雑になります)。

情報セクションから、圧縮が有効になっているかどうか、画像のサイズなどもわかります。

一度にすべてを読み込んでいる場合は、データのオフセットにジャンプして、次のようにします。

Rgb* rgb = offset;
blueVal = rgb->blue;
greenVal = rgb->green;
redVal = rgb->red;
rgb += sizeof( Rgb );

等々。明らかに、そのコードはエラーやバッファの終わりなどをチェックしていないので、それを行う必要があります。画像データを理解するには、おそらくパレット情報も読み込む必要があります。

または、他の誰かが言ったように、ウィキペディアのフォーマット仕様を見てください

于 2009-10-07T12:34:15.967 に答える
0

BMPファイルにパレットがある場合は、次のコードが機能するはずです。

  FILE *inFile, *outFile;
  inFile = fopen("C:/in.bmp", "rb");
  Rgb Palette[256];
  if ( inFile ) {
    // Bypass headers
    fseek(inFile, sizeof(BmpHeader) + sizeof(BmpImageInfo), SEEK_SET);
    // Load the whole palette
    fread(Palette, sizeof(Palette), 1, inFile);
    fclose(inFile);
  }
于 2009-10-07T12:39:20.743 に答える