1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
void Bitmap::load(const string& filename) {
//Create a binary input stream
ifstream inputStream(filename.c_str(),ios::binary);
//Advance to last position to get file size
inputStream.seekg(0,ios::end);
unsigned fileSize = inputStream.tellg();
//Rewind to beginning
inputStream.seekg(0,ios::beg);
//Create file header
BITMAPFILEHEADER bmfh;
//Read the file header fields from file
inputStream.read((char*)&bmfh.bfType,sizeof(bmfh.bfType));
inputStream.read((char*)&bmfh.bfSize,sizeof(bmfh.bfSize));
inputStream.read((char*)&bmfh.bfReserved1,sizeof(bmfh.bfReserved1));
inputStream.read((char*)&bmfh.bfReserved2,sizeof(bmfh.bfReserved2));
inputStream.read((char*)&bmfh.bfOffBits,sizeof(bmfh.bfOffBits));
//Create info header
BITMAPINFOHEADER bmih;
//Read the info header fields from file
inputStream.read((char*)&bmih.biSize,sizeof(bmih.biSize));
inputStream.read((char*)&bmih.biWidth,sizeof(bmih.biWidth));
inputStream.read((char*)&bmih.biHeight,sizeof(bmih.biHeight));
inputStream.read((char*)&bmih.biPlanes,sizeof(bmih.biPlanes));
inputStream.read((char*)&bmih.biBitCount,sizeof(bmih.biBitCount));
inputStream.read((char*)&bmih.biCompression,sizeof(bmih.biCompression));
inputStream.read((char*)&bmih.biSizeImage,sizeof(bmih.biSizeImage));
inputStream.read((char*)&bmih.biXPelsPerMeter,sizeof(bmih.biXPelsPerMeter));
inputStream.read((char*)&bmih.biYPelsPerMeter,sizeof(bmih.biYPelsPerMeter));
inputStream.read((char*)&bmih.biClrUsed,sizeof(bmih.biClrUsed));
inputStream.read((char*)&bmih.biClrImportant,sizeof(bmih.biClrImportant));
//Declare necessary variables
unsigned nColorBytes; //Number of entries in color index array, or length of BGR/BGRA array
unsigned nTableEntries; //Number of entries in the color table
vector<BYTE> colorBytes; //Color table index array, or literal BGR/BGRA byte array
vector<RGBQUAD> colorTable; //Array of color values
//Size the arrays according to bit depth
switch (bmih.biBitCount) {
case 24:
{
//Calculate end-of-line byte padding
unsigned padding = 0;
while ((bmih.biWidth * 3 + padding) % 4 != 0) {
++padding;
}
//Set sizes
nColorBytes = bmih.biHeight * (bmih.biWidth * 3 + padding);
nTableEntries = 0;
break;
}
case 8:
{
//Calculate end-of-line byte padding
unsigned padding = 0;
while ((bmih.biWidth + padding) % 4 != 0) {
++padding;
}
//Set sizes
nColorBytes = bmih.biHeight * (bmih.biWidth + padding);
nTableEntries = (bmih.biClrUsed == 0)? 256 : bmih.biClrUsed;
break;
}
default:
::MessageBox(NULL,"Unsupported bit depth!","",0);
inputStream.close();
return;
}
//Allocate memory
colorBytes.resize(nColorBytes);
colorTable.resize(nTableEntries);
//Read the color table entries one-by-one
for (unsigned i=0; i<nTableEntries; i++) {
inputStream.read((char*)&colorTable[i],sizeof(RGBQUAD));
}
//Read the array color indices (or literal BGR components)
inputStream.read((char*)&colorBytes[0],nColorBytes);
//Close the input file
inputStream.close();
//Get DC for SetDIBits to use
HDC hdcScreen = ::GetDC(NULL);
//Create and initialize the BITMAPINFO structure for SetDIBits to use
BITMAPINFO bmi;
bmi.bmiHeader = bmih; //Use the header information from the input file
//Create the new bitmap
HBITMAP hNewBitmap = ::CreateCompatibleBitmap(hdcScreen,bmih.biWidth,bmih.biHeight);
//Transfer the color byte array into the bitmap
::SetDIBits(hdcScreen,hNewBitmap,0,bmih.biHeight,&colorBytes[0],&bmi,DIB_RGB_COLORS);
//Set the color table, if one exists
if (nTableEntries > 0) {
//Create compatible DC to select image into for SetDIBColorTable
HDC hdcTemp = ::CreateCompatibleDC(hdcScreen);
//Select the new bitmap into the color table DC, and save pointer to original
HBITMAP hbmOldTemp = (HBITMAP)::SelectObject(hdcTemp,hNewBitmap);
//Set the color table, starting with the first entry
::SetDIBColorTable(hdcTemp,0,nTableEntries,&colorTable[0]); //FAILS
//Restore temp DC's original bitmap, and free memory
::SelectObject(hdcTemp,hbmOldTemp);
::DeleteDC(hdcTemp);
}
//Restore the screen DC
::ReleaseDC(NULL,hdcScreen);
//Free any existing member bitmap
if (m_hBitmap != NULL) {
::DeleteObject(m_hBitmap);
}
//Replace member bitmap with new one
m_hBitmap = hNewBitmap;
}
|