2016-06-12 6 views
0

비트 맵 (.bmp) 이미지 헤더를 struct으로 읽으려고합니다. c.구조체에 fread가 데이터를 잘못 읽습니다.

typedef unsigned short WORD; 
typedef unsigned long DWORD; 

typedef struct _BITMAPFILEHEADER { 
    WORD Type; 
    DWORD Size; 
    WORD Reserved1; 
    WORD Reserved2; 
    DWORD OffBits; 
} BITMAPFILEHEADER; 

비트 맵 파일을 읽을 수있는 내 코드

FILE *fp; 
BITMAPFILEHEADER header; 

fp = fopen(file,"rb"); 
if (fp == NULL) { 
    printf("cannot open file!\n"); 
    return 1; 
} 

fread(&header, sizeof(BITMAPFILEHEADER), 1, fp); 

printf("Type: %02x\n", header.Type); 
printf("Size: %04x\n", header.Size); 
printf("Reserved: %02x\n", header.Reserved1); 
printf("Reserved: %02x\n", header.Reserved2); 
printf("Offset: %04x\n", header.OffBits); 

은 무엇 모두 같아야합니다 :
유형 : 0x424d
크기 : 0x00060436
한 Reserved1 : 0x00
Reserved2을 : 0x00
오프셋 : 실제로 (printf와 출력) happning 무엇 0x00000436

:
유형 : 0x424d
크기 : 0x0006
가 예약 : 0x002
가 예약 : 0x436
오프셋 : 0x280000

(내 os는 도움이된다면 32 비트 우분투)

+1

고정 너비 정수가 필요한 경우 표준에서 제공하는 정수를 사용하십시오. 자작 나무 종류를 사용하지 마십시오. 또한 abolut'struct' 레이아웃과 옥텟 스트림을 적절하게 직렬화/마샬링하는 방법을 읽으십시오. – Olaf

+5

http://c-faq.com/struct/io.html, http://c-faq.com/struct/padding.html – melpomene

+2

데이터는 어떻게 파일에 기록 되었습니까? 데이터를 읽을 때 작성된 방식을 모방해야합니다.구조체에 패딩이있는 경우 (거의 확실하게) 데이터가 단편적으로 작성되었지만 (패딩이없는 경우처럼) 데이터를 읽은 것처럼 읽을 수 없습니다. 별도의'fread()'연산을 통해 각 원소를 차례대로 읽어 들여야하고'fread()'가 성공했다고 확신하는지 확인한 후에 반환 할 것이라고 생각하는 것을 사용해야한다. –

답변

0

이런 종류의 파일을 읽을 때 좋은 방법은 먼저 바이트 스트림 (unsigned char)으로 읽은 다음 필요한 경우 적절한 데이터 형식에 따라 파일 내용의 일부를 해석하는 것입니다.

귀하의 경우에는

, 예를 들어,이 같은 BITMAPFILEHEADER 구조체를 정의 할 :

typedef struct _BITMAPFILEHEADER { 
    unsigned char Type[ 2 ]; 
    unsigned int Size;   // Size of the BMP file in bytes 
    unsigned char Reserved1[ 2 ]; 
    unsigned char Reserved2[ 2 ]; 
    unsigned int OffBits;  // Starting address of the pixel array 
} BITMAPFILEHEADER; 

그때 나는 마지막에, 나는에 갈 것이라고, 14 바이트의 블록으로 헤더 내용을 읽고 것이다 BITMAPFILEHEADER 구조체를 올바르게 채 웁니다.

아래에서 BMP 파일의 헤더를 읽고이를 화면에 인쇄하는 간단한 프로그램을 찾을 수 있습니다.

int main 
    (
    ) 
    { 
    // Defines a few variables 
    FILE*   fp = 0; 
    unsigned char h[ 14 ]; 

    // Opens the BMP file 
    fp = fopen("img.bmp", "rb"); 

    if (fp == NULL) 
     { 
     printf("Cannot open file\n"); 
     return -1; 
     } 

    // Reads the BMP header (14 bytes) 
    fread(h, 14, 1, fp); 

    // Prints the header contents 
    printf("Type:  %02x%02x\n", h[ 0 ], h[ 1 ]); 
    printf("Size:  %02x%02x%02x%02x\n", h[ 2 ], h[ 3 ], h[ 4 ], h[ 5 ]); 
    printf("Reserved: %02x%02x\n", h[ 6 ], h[ 7 ]); 
    printf("Reserved: %02x%02x\n", h[ 8 ], h[ 9 ]); 
    printf("Offset: %02x%02x%02x%02x\n", h[ 10 ], h[ 11 ], h[ 12 ], h[ 13 ]); 

    return 0; 
    } 

주 1 - 패딩 : BMP 파일 형식 사양에서, 우리는 헤더가 printf("%d", sizeof(BITMAPFILEHEADER))가 (때문에 패딩에 다른 (! 이상) 수를 표시하는 의견을 볼 때 14 바이트 길이의 것을 알고 귀하의 질문).

주 2 - 엔디안 : 2 바이트 또는 4 바이트를 각각 짧게 또는 길게 쓸 때는 엔디안을 고려해야합니다. 즉, 파일에 값을 쓰는 방법 (비트 맵 헤더는 리틀 엔디안 표기법으로 나타냄)과 시스템에서 처리하는 방법 (아마 리틀 엔디안 표기법)을 알아야합니다.

+1

'unsigned char [2] Type;'은 구문 오류입니다. –

+1

'unsigned char Type [2];'를 사용한다고 가정하면 구조체 정의는'Size' 전에 패딩이 남아 있기 때문에 실제로 도움이되지 않습니다. 샘플 프로그램에서와 같이 예상 크기의 부호없는 char 버퍼를 읽는 것이 좋습니다. 그러나 프로그램에는 엔디안 문제가 있습니다. –

+1

BMP 파일은 항상 리틀 엔디안 afaik에 있습니다. – rici

관련 문제