2015-02-02 1 views
3

Я пытаюсь подсчитать количество пикселей в BMP-изображении и, следовательно, нет байтов на пиксель, используя информацию, полученную из структуры BITMAPINFOHEADER. Но всякий раз, когда я запускаю мой код я получаю число байт на пиксель = 0Как правильно вычислить количество байтов на пиксель в BMP-изображении с использованием C++?

struct BITMAPFILEHEADER    // File header 
{ 
char bfType[2];     // File type: should be BM (0x42 0x4D) 
int bfSize;      // File size in bytes 
short bfReserved1;    // Reserved - for what i have no idea :P 
short bfReserved2;    // -||- 
int bfOffBits;     // Offset, adress of the beginning of the information about image (pixels) 
}; 

struct BITMAPINFOHEADER    // Bitmap header 
{ 
unsigned int biSize;    // Size of this header 
unsigned int biWidth;    // Width of image (in pixels) 
unsigned int biHeight;   // Height of this image (in pixels) 
unsigned short biPlanes;   // Numer of color planes, always 1 
unsigned short biBitCount;  // Number of bytes for pixel. Possibility values :1,4,8,16, 24 and 32 
unsigned int biCompression;  // Used compression (0 -none) 
unsigned int biSizeImage;   // Size of image 
signed int biXPelsPerMeter;  // Horizontal resolution of the image (pixel per meter) 
signed int biYPelsPerMeter;  // Vertical resolution of the image (pixel per meter) 
unsigned int biClrUsed;   // Number of colors in the color palette, or 0 to default to 2^n (0- no palette) 
unsigned int biClrImportant;  // Number of important colors used 
}; 

struct Pixel{ 
unsigned int blue; // or double? 
unsigned int green; 
unsigned int red; 
//unsigned char reserved; 
}; 


void Image::conversiontoBRG(const char* filename) 
{ 
ifstream brgfile; 
brgfile.open(filename, ios::in | ios::binary); 


char *bmpheadinfo = new char[sizeof(BITMAPFILEHEADER)]; 
brgfile.read(bmpheadinfo, sizeof(BITMAPFILEHEADER)); 
BITMAPFILEHEADER* bmpheader = (BITMAPFILEHEADER*)bmpheadinfo; 

cout << "File type : " << bmpheader->bfType << endl; 
cout << "File size : " << bmpheader->bfSize << endl; 
cout << "File Offset for the beginning of image info : " << bmpheader->bfOffBits << endl << endl; 


bmpheadinfo = new char[sizeof(BITMAPINFOHEADER)]; 
brgfile.read(bmpheadinfo, sizeof(BITMAPINFOHEADER)); 
BITMAPINFOHEADER* bmpinfo = (BITMAPINFOHEADER*)bmpheadinfo; 

cout << "File Header Size : " << bmpinfo->biSize << endl; 
cout << "Width : " << bmpinfo->biWidth << endl; 
cout << "Height : " << bmpinfo->biHeight << endl; 
cout << "No of bytes per pixel : " << bmpinfo->biBitCount << endl; 
cout << "Used compression: " << bmpinfo->biCompression << endl; 
cout << "Image size: " << bmpinfo->biSizeImage << endl; 
cout << "Horizontal resolution: " << bmpinfo->biXPelsPerMeter << endl; 
cout << "Vertical resolution: " << bmpinfo->biYPelsPerMeter << endl; 
cout << "Number of colors in the color palette: " << bmpinfo->biClrUsed << endl; 
cout << "Number of important colors used: " << bmpinfo->biClrImportant << endl; 
} 

Я пытаюсь работать на растровом изображении называется index.bmp

Размер: 275x184
Ширина: 275 пикс
Высота: 184 пикселей
Битовая глубина: 24
Название: index.bmp Тип
Item: BMP файл
Размер: 148 KB

Но всякий раз, когда я запускаю приведенный выше код, я получаю следующий вывод. Я не уверен, где я ошибаюсь. Пожалуйста, помогите мне.

File type : BMVS 
File size : 2 
File Offset for the beginning of image info : 2621440 

File Header Size : 18022400 
Width : 12058624 
Height : 65536 
No of bytes per pixel : 0 
Used compression: 1394606080 
Image size: 2 
Horizontal resolution: 0 
Vertical resolution: 0 
Number of colors in the color palette: 0 
Number of important colors used: 973078528 
+1

12058624 - 0xB80000. 0xB8 - 184. 18022400 - 0x1130000. 0x113 - 275. Вы не в синхронизации. – molbdnilo

+0

'BMVS' - 0x424d5653 в гексагоне большого эндиана. Строка 'VS' появляется, потому что' bfType' - это не строка с нулевым завершением, как TonyD, и это 2 MSB 'bfSize'. Поскольку вы не указали дополнение, из-за выравнивания 'bfSize' начинается с следующей границы 4 байта и читает 2 или 0x02000000 в большом конце. Поэтому это фактическое значение: '0x00025356 = 152,406 bytes = 148.834KB' –

+0

Просто используйте макрос' #pragma pack (push, 1) 'и' #pragma pack (pop) '. Вы получите результат, которого вы ожидали. –

ответ

1

файл BMP не будет иметь дополняющие биты в данных заголовка, в то время как вы struct S были определены, без жесткой упаковки макросов; это приведет к тому, что члены ваших файлов данных и члены данных struct будут правильно выровнены. Исправьте это, и вы будете иметь возможность увидеть поля справедливо

#pragma pack(push, 1)  // macro to avoid padding bytes within a struct 

struct BITMAPFILEHEADER    // File header 
{ 
    char bfType[2];     // File type: should be BM (0x42 0x4D) 
    int bfSize;      // File size in bytes 
    short bfReserved1;    // Reserved - for what i have no idea :P 
    short bfReserved2;    // -||- 
    int bfOffBits;     // Offset, adress of the beginning of the information about image (pixels) 
}; 

struct BITMAPINFOHEADER    // Bitmap header 
{ 
    unsigned int biSize;    // Size of this header 
    unsigned int biWidth;    // Width of image (in pixels) 
    unsigned int biHeight;   // Height of this image (in pixels) 
    unsigned short biPlanes;   // Numer of color planes, always 1 
    unsigned short biBitCount;  // Number of bytes for pixel. Possibility values :1,4,8,16, 24 and 32 
    unsigned int biCompression;  // Used compression (0 -none) 
    unsigned int biSizeImage;   // Size of image 
    signed int biXPelsPerMeter;  // Horizontal resolution of the image (pixel per meter) 
    signed int biYPelsPerMeter;  // Vertical resolution of the image (pixel per meter) 
    unsigned int biClrUsed;   // Number of colors in the color palette, or 0 to default to 2^n (0- no palette) 
    unsigned int biClrImportant;  // Number of important colors used 
}; 

#pragma pack(pop)   // stop doing the tight packing 

Это можно проверить, что там не вы не биты заполнения Теперь

std::cout << sizeof BITMAPFILEHEADER << '\n'; 

напечатает 14 в настоящее время; попробуйте, отключив макросы, и вы увидите что-то большее, чем 14. На this live example отображается 16.

2

Как проблема упаковки legends2k упоминается:

  • Вы не считая порядка байтов (Google это, а затем использовать ntohs и др в коде),

  • следует создать локальный BITMAPFILEHEADER bmpheader; object then brgfile.read((char*)&bmpheader, sizeof bmpheader); - таким образом вы знаете, что встроенные многобайтовые целые числа будут правильно выровнены для доступа - в противном случае вы можете получить SIGBUS или подобное на некоторых системах; сделать что-то подобное для BITMAPINFOHEADER

  • не только печатать bfType либо - как массив, он распадается на const char* для <<, и это не завершенную нулем, так что вы получите мусор дополнительных символов.

+0

Активировано для metioning SIGBUS из-за несвязанного доступа, который будет вызываться при игнорировании байтов заполнения. – legends2k

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