Reputation: 193
I am trying to count number of pixels in BMP image and thus the no of bytes per pixel, by using the information I gathered from struct BITMAPINFOHEADER . But whenever I run my code I get number of bytes per pixel = 0
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;
}
I am trying to work on a bitmap image called index.bmp
Dimension : 275x184
Width : 275 pixels
Height : 184 pixels
Bit Depth : 24
Name : index.bmp
Item Type : BMP file
Size : 148 KB
But whenever I run the above code I get the following output. I am not sure where I am going wrong. Please help me.
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
Upvotes: 3
Views: 2456
Reputation: 106096
As well the packing issue legends2k mentions:
you're not considering endianness (Google it, then use ntohs
et al in your code),
you should create a local BITMAPFILEHEADER bmpheader;
object then brgfile.read((char*)&bmpheader, sizeof bmpheader);
- that way you know the embedded multi-byte integers will be properly aligned for access - otherwise you may get SIGBUS or similar on some systems; do something similar for BITMAPINFOHEADER
don't just print bfType
either - as an array, it decays to a const char*
for <<
, and it's not NUL terminated so you get garbage extra characters.
Upvotes: 2
Reputation: 32904
The BMP file will have no padding bits within the header data, while you're struct
s have been defined with no tight packing macros; this will lead to your file data members and struct
data members to be not aligned correctly. Fix this and you'll be able to see the fields rightly
#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
It can be verified that there're no padding bits now
std::cout << sizeof BITMAPFILEHEADER << '\n';
would print 14
now; try it by disabling the macros and you would see something more than 14. On this live example it shows 16
.
Upvotes: 1