2012-11-13 3 views
2

bmp 파일에서 데이터를 추출하는 간단한 프로그램을 작성했습니다. 나는 지금 막 시작했고 나는 그 WTF 순간 중 하나에있다. 나는이 프로그램을 실행하고이 이미지를 제공 할 때c BMP에서 데이터 가져 오기

는 : 실제 이미지 크기는 786,486 바이트입니다

type: 19778 
size: 12 
res1: 0 
res2: 54 
offset: 2621440 

: http://www.hack4fun.org/h4f/sites/default/files/bindump/lena.bmp

을 나는 출력을 얻을. 내 코드가 12 바이트를보고하는 이유는 무엇입니까?

http://en.wikipedia.org/wiki/BMP_file_format에 지정된 헤더 형식이 내 BMP_FILE_HEADER 구조와 일치합니다. 그렇다면 잘못된 정보로 왜 채워지고 있습니까?

이미지 파일이 손상되지 않은 것 같고 다른 이미지도 똑같이 잘못된 출력을 제공합니다. 내가 뭘 놓치고 있니? 여기

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

typedef struct { 
    unsigned short type; 
    unsigned int size; 
    unsigned short res1; 
    unsigned short res2; 
    unsigned int offset; 
} BMP_FILE_HEADER; 

int main (int args, char ** argv) { 
    char *file_name = argv[1]; 

    FILE *fp = fopen(file_name, "rb"); 

    BMP_FILE_HEADER file_header; 

    fread(&file_header, sizeof(BMP_FILE_HEADER), 1, fp); 

    if (file_header.type != 'MB') { 
     printf("ERROR: not a .bmp"); 
     return 1; 
    } 

    printf("type: %i\nsize: %i\nres1: %i\nres2: %i\noffset: %i\n", file_header.type, file_header.size, file_header.res1, file_header.res2, file_header.offset); 
    fclose(fp); 

    return 0; 
} 
+0

'BMP_FILE_HEADER'이 (가) packof되어 있는지 확인하십시오. sizeof (BMP_FILE_HEADER) == 14 – Musa

+0

@ Musa 16입니다. 고마워요, 지금 제가 할 일이 있습니다. –

답변

1

코드에서 두 가지 실수가 있습니다.

첫 번째 실수 : 구조체를 1로 패킹해야하므로 모든 유형 크기가 의도 한 크기와 정확히 같아야하므로 컴파일러는 예를 들어 4 바이트 정렬로 정렬하지 않습니다. 따라서 코드에서 short은 2 바이트 대신 4 바이트입니다. 이에 대한 트릭은, 가장 가까운 구조체를 포장하기위한 컴파일러 지시문을 사용하고 있습니다 :

#pragma pack(1) 

typedef struct { 
    unsigned short type; 
    unsigned int size; 
    unsigned short res1; 
    unsigned short res2; 
    unsigned int offset; 
} BMP_FILE_HEADER; 

지금 제대로 정렬되어야합니다.

다른 실수는 여기에 있습니다 : 당신은 char 유형, 2 바이트 인 short 유형을 확인하려고

if (file_header.type != 'MB') 

1 바이트 인 ('' 사용). 아마 컴파일러가 그것에 대해 경고를 제공하고 있습니다. 작은 따옴표에는 1 바이트 크기의 문자가 1 개만 포함될 수 있습니다.

이 문제를 해결하려면이 2 바이트를 2 바이트로 나눌 수 있습니다 (MB).이를 word에 넣을 수 있습니다.예를 들어 :이 식을 참조하면

if (file_header.type != (('M' << 8) | 'B')) 

,이 상황이 발생합니다

'M' 왼쪽으로 8 비트 이동 (ASCII에서 0x4D 인), 0x4D00가 발생합니다, 지금 방금 추가 할 수 또는 또는 오른쪽 0의 다음 문자 : 0x4D00 | 0x42 = 0x4D42 (여기에서 0x42은 ASCII의 경우 'B' 임). 이렇게 생각하면 다음과 같이 쓸 수 있습니다.

if (file_header.type != 0x4D42) 

그러면 코드가 작동합니다.

2

헥스 헤더 :

0000000 42 4d 36 00 0c 00 00 00 00 00 36 00 00 00 28 00 
0000020 00 00 00 02 00 00 00 02 00 00 01 00 18 00 00 00 

길이 필드 인텔 순서에 바이트 36 00 0C 00`이고; 32 비트 값으로 처리되면 0x000c0036 또는 십진수 786,486 (저장된 파일 크기와 일치 함)입니다.

아마 C 컴파일러가 각 필드를 32 비트 경계에 맞추고있을 것입니다. 팩 구조 옵션, pragma 또는 지시문을 활성화합니다.

+0

감사합니다. 매력처럼 작동하여 구조체 앞에'#pragma pack() '을 추가했습니다. –