2010-11-01 2 views
0

Я хочу загрузить файл BMP в память в C. Я нашел много разных типов структур BmpFileHeader и BmpInfoHeader. Последнее, что я взял с msdn.microsoft.com, но он по-прежнему не читается правильно из двоичного файла. С тестовым файлом lena Размер изображения: -1076791624 Невозможно выделитьПроблемы с структурами BMP {FileHeader, InfoHeader}

Какой у меня недостаток? Благодарю.

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

typedef struct tagBITMAPFILEHEADER { 
    unsigned short bfType; 
    unsigned int bfSize; 
    short bfReserved1; 
    short bfReserved2; 
    unsigned int bfOffBits; 
} BITMAPFILEHEADER; 

typedef struct tagBITMAPINFOHEADER { 
    unsigned int biSize; 
    int biWidth; 
    int biHeight; 
    short biPlanes; 
    short biBitCount; 
    unsigned int biCompression; 
    unsigned int biSizeImage; 
    int biXPelsPerMeter; 
    int biYPelsPerMeter; 
    unsigned int biClrUsed; 
    unsigned int biClrImportant; 
} BITMAPINFOHEADER; 

int main(int argc, char *argv[]) 
{ 
    if(argc != 2) 
    { 
    printf("Usage: %s input.bmp\n", argv[0]); 
    exit(-1); 
    } 

    FILE *filePtr; 
    BITMAPFILEHEADER bitmapFileHeader; 
    BITMAPINFOHEADER bitmapInfoHeader; 
    unsigned char *bitmapImage; 
    int imageIdx=0; 
    unsigned char tempRGB; 

    filePtr = fopen(argv[1],"rb"); 
    if (filePtr == NULL) 
    { 
    printf("File could not opened\n"); 
    exit(-1); 
    } 

    //read the bitmap file header 
    fread(&bitmapFileHeader, sizeof(bitmapFileHeader), 1, filePtr); 

    if (bitmapFileHeader.bfType !=0x4D42) 
    { 
    fclose(filePtr); 
    printf("Not a bmp file\n"); 
    exit(-1); 
    } 

    fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET); 
    bitmapImage = (unsigned char*)malloc(sizeof(unsigned char)*bitmapInfoHeader.biSizeImage); 
    printf("Image Size: %d\n", bitmapInfoHeader.biSizeImage); 

    if (!bitmapImage) 
    { 
    free(bitmapImage); 
    fclose(filePtr); 
    printf("Memory could not be allocated\n"); 
    exit(-1); 
    } 

    //swap the r and b values to get RGB (bitmap is BGR) 
    for (imageIdx = 0; imageIdx < bitmapInfoHeader.biSizeImage; imageIdx+=3) 
    { 
    tempRGB = bitmapImage[imageIdx]; 
    bitmapImage[imageIdx] = bitmapImage[imageIdx + 2]; 
    bitmapImage[imageIdx + 2] = tempRGB; 
    } 

    int i; 

    for(i = 0; i < bitmapInfoHeader.biSizeImage; i+=3){ 
    printf("R: %c G: %c B: %c\n", bitmapImage[i], bitmapImage[i + 1], bitmapImage[i + 2]); 
    } 

    fclose(filePtr); 

    return 0; 

} 
+0

Формат printf для размера изображения должен быть% u вместо% d, потому что bitmapInfoHeader.biSizeImage - это неподписанный int. Это предотвратит отображение ошибочного негативного изображения. Используйте отладчик, чтобы посмотреть содержимое структур после их чтения с диска, чтобы узнать, правильно ли они заполнены. Возможно, компилятор добавляет дополнительные байты заполнения, чтобы сделать выравнивание слов приятным (см. BfReserved1/bfReserved2 и biPlanes/biBitCount). – jholl

ответ

0

Первое, что я хотел бы сделать, это найти авторитетное утверждение в byte layout этих заголовков, а затем, предположив, что вы хотите продолжать использовать структурированные вами структуры, добавить некоторые утверждения в смещения поля, для пример:

assert(offsetof(BITMAPFILEHEADER, bfType) == 0);  // or whatever 
assert(offsetof(BITMAPFILEHEADER, bfSize) == 2);  // or whatever 
assert(offsetof(BITMAPFILEHEADER, bfOffBits) == 10); // or whatever 
etc. 

Скорее всего, что использование знака Int, короткие, и т.д., плюс ваши варианты компилятора (особенно структура упаковки) может означать, что ваши поля Struct не совпадают с фактическими данными файла BMP (в зачёт, и, возможно, в длину).

0

Ваш bitmapInfoHeader является неинициализированным!

То есть вы читаете bitmapFileHeader, а затем устанавливаете указатель на файл, где должны быть фактические данные растрового изображения. Но вы не читали bitmapInfoHeader, в котором содержится вся информация о растровом изображении (размеры, bpp и т. Д.)

P.S. В следующий раз попробуйте сделать отладку вашего кода befure, разместив вопрос.

+0

Да, вы правы. Я добавил строку; fread (& bitmapInfoHeader, sizeof (bitmapInfoHeader), 1, filePtr); Однако выход есть; Размер изображения: 4 R: 0 G: 0 B: 0 R: 0 G: 0 B: 0 Файл изображения - 257,1 kb..Что-то еще не так – anarhikos

0

Существует несколько версий формата файла BMP, и большинство из них отличаются размером заголовков. Если вы хотите иметь возможность читать все действующие BMP-файлы, вам нужно будет их поддерживать. Изображение lena, похоже, является версией Windows V3.

Существует хорошее описание различных версий в Wikipedia.

Кроме того, я не вижу в коде кода никаких указаний. Если вы машина не маленькая, это не сработает.

И, наконец, выравнивание элементов структуры является проблемой. Ваш компилятор, скорее всего, выровнят элемент bfSize со смещением 4, но он должен быть со смещением 2. (0).

Смежные вопросы