2017-09-21 9 views
-2

イメージの各ピクセルのRGBカラー値のバイトをbmp(ビットマップ)形式で表示する必要があるコードに問題があります。ビットマップからカラーバイト(RGB)を読み取る

私はWindows APIをより現実的な方法でビットマップで動作させる方法を知っていますが、最終的なコードをオペレーティングシステムの観点から移植したいので、構造体を作成しました。

#include <stdio.h> 
#include <stdlib.h> 

unsigned char *readBMP(char *filename, int *size) { 
    int width, height; 
    unsigned char *data; 
    unsigned char info[54]; 

    FILE *file = fopen(filename, "rb"); 
    if (file == NULL) 
     return 0; 

    fread(info, sizeof(unsigned char), 54, file); // read the 54-byte header 

    // extract image height and width from header 
    width = *(int *) &info[18]; 
    height = *(int *) &info[22]; 

    *size = 3 * width * height; 
    data = (unsigned char *) malloc(*size * sizeof(unsigned char)); // allocate 3 bytes per pixel 
    fread(data, sizeof(unsigned char), (size_t) *size, file); // read the rest of the data at once 

    for (int i = 0; i < *size; i += 3) { 
     unsigned char tmp = data[i]; 
     data[i] = data[i + 2]; 
     data[i + 2] = tmp; 
    } 

    fclose(file); 
    return data; 
} 

int main() { 
    int size = 0; 
    char filename[] = "output.bmp"; 
    unsigned char *data = readBMP(filename, &size); 

    for (int i = 0; i < size; i++) { 
     printf("%d. %d\n", i + 1, (int) data[i]); 
     if ((i + 1) % 3 == 0) 
      printf("\n"); 
    } 

    free(data); 
    return 0; 
} 

ピクセルのRGBコード:

(0, 0, 0), (0, 0, 255), 
(0, 255, 0), (0, 255, 255), 
(255, 0, 0), (255, 0, 255); 

私は "読み" しようとしている画像は、2×3ピクセルのビットマップである:C.

ここではコードです

そして、私が持っている出力は次のようになります。

1. 255 
2. 0 
3. 0 

4. 255 
5. 0 
6. 255 

7. 0 
8. 0 
9. 0 

10. 255 
11. 0 
12. 255 

13. 0 
14. 0 
15. 255 

16. 0 
17. 0 
18. 0 

最初の測定値であっても、ビットマップの下部にあるピクセルと一致するが、他は、少なくともではないために、他の画素と一致していない彼らが配置されている。

誰かが間違っているのを見ることはできますか?

+3

必要な詰め物を考慮していないようです。各行は4バイトの倍数でなければなりません。 –

+0

ビットマップは、高さが負でない限り、ボトムアップで保存されます。 https://en.wikipedia.org/wiki/BMP_file_format –

+0

2x3イメージを考えると、各行を読み、最後の2バイトを無視する必要があります。これは、その行に4の倍数のバイト数があることを確認するだけでしょうか? –

答えて

1

ビットマップのサイズがwidth * height * 3ではありません。なお、この場合bitcount

size = ((width * bitcount + 31)/32) * 4 * height; 

を用いて計算することがなければならない24ビットのビットマップで24

行がパディングされなければならないれます。また、24ビットのビットマップを読み込んでいることを確認する必要があります。 32ビットのビットマップとパレットのビットマップには異なるアルゴリズムが必要です。

行は下から上に読み込まれます。

以下は24ビットの例です。

このコードでは、他の問題が引き続き発生することがあります。これらの関数にライブラリを使用する方が良いでしょう。 Windowsの機能を使用したくない場合は、別のオペレーティングシステムで使用できるサードパーティのライブラリを使用してください。そこには多くのそのようなライブラリがあります。

int main() 
{ 
    int width, height, padding, bitcount, size; 
    unsigned char *data = 0; 
    unsigned char info[54] = { 0 }; 
    FILE *file = fopen("output.bmp", "rb"); 
    if(!file) 
     return 0; 

    fread(info, 1, 54, file); 
    width = *(int*)(info + 18); 
    height = *(int*)(info + 22); 
    bitcount = *(int*)(info + 28); 
    size = ((width * bitcount + 31)/32) * 4 * height; 
    padding = width % 4; 
    if(bitcount != 24) //this code works for 24-bit bitmap only 
     goto error; 

    data = malloc(size); 
    fread(data, 1, size, file); 
    for(int row = height - 1; row >= 0; row--) 
    { 
     for(int col = 0; col < width; col++) 
     { 
      int p = (row * width + col) * 3 + row * padding; 
      printf("%02X%02X%02X ", data[p + 0], data[p + 1], data[p + 2]); 
     } 
     printf("\n"); 
    } 

error: 
    if(file) fclose(file); 
    if(data) free(data); 
    return 0; 
} 
関連する問題