Join 136,834 C++ Programmers for FREE! Get instant access to thousands of C++ experts, tutorials, code snippets, and more! There are 1,763 people online right now. Registration is fast and FREE... Join Now!
I have a pointer to an array that stores a GrayScale 16 bits per pixel image and I'm trying to save it as a BMP. I'm able to create the BITMAP, but when I open the BMP file it shows up in color (instead of GrayScale). My code is:
CODE
void SaveBitmapToFile( uns16* pBitmapBits, LONG lWidth, LONG lHeight,WORD wBitsPerPixel, LPCTSTR lpszFileName ) { BITMAPINFOHEADER bmpInfoHeader = {0}; // Set the size bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER); // Bit count bmpInfoHeader.biBitCount = wBitsPerPixel; // Use all colors bmpInfoHeader.biClrImportant = 0; // Use as many colors according to bits per pixel bmpInfoHeader.biClrUsed = 0; // Store as un Compressed bmpInfoHeader.biCompression = BI_RGB; // Set the height in pixels bmpInfoHeader.biHeight = lHeight; // Width of the Image in pixels bmpInfoHeader.biWidth = lWidth; // Default number of planes bmpInfoHeader.biPlanes = 1; // Calculate the image size in bytes bmpInfoHeader.biSizeImage = lWidth* lHeight * (wBitsPerPixel/8);
BITMAPFILEHEADER bfh = {0}; // This value should be values of BM letters i.e 0×4D42 // 0×4D = M 0×42 = B storing in reverse order to match with endian bfh.bfType=0x4D42; /* or bfh.bfType = ‘B’+(’M’ << 8); // <<8 used to shift ‘M’ to end */ // Offset to the RGBQUAD bfh.bfOffBits = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER); // Total size of image including size of headers bfh.bfSize = bfh.bfOffBits + bmpInfoHeader.biSizeImage; // Create the file in disk to write HANDLE hFile = CreateFile( lpszFileName,GENERIC_WRITE, 0,NULL,
I tried a different approach to the BMP code shown below. The results are still pretty much the same, unable to save the file effectively as a Grayscale 16bpp... I also attached the kind of results I'm getting, compressed as a jpg file. The result.jpg shows the result from the code from the first post on the left side of the image. The result from the code from this current post is on the right side of the image. Anyone help? thx
CODE
void SaveBitmapToFile( uns16* lpBits, LONG lWidth, LONG lHeight, WORD wBitsPerPixel, LPCTSTR pszFile, HWND hwnd ) {
PBITMAPINFO pbmi; WORD cClrBits; int biPlanesSetBU = 1;
// Convert the color format to a count of bits. cClrBits = (WORD)(biPlanesSetBU * wBitsPerPixel); //cClrBits = 16 in our case
// Allocate memory for the BITMAPINFO structure. (This structure // contains a BITMAPINFOHEADER structure and an array of RGBQUAD // data structures.)
// Initialize the fields in the BITMAPINFO structure.
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // biSize = 40 pbmi->bmiHeader.biWidth = lWidth; //lwidth = 1024 pbmi->bmiHeader.biHeight = -1*lHeight; // -1024 so that image is displayed rightside up pbmi->bmiHeader.biPlanes = biPlanesSetBU; // biPlaneSetBU = 1 pbmi->bmiHeader.biBitCount = wBitsPerPixel; // wBitsPerPixel = 16
if (cClrBits < 24) pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
// If the bitmap is not compressed, set the BI_RGB flag. pbmi->bmiHeader.biCompression = BI_RGB;
// Compute the number of bytes in the array of color // indices and store the result in biSizeImage. // For Windows NT, the width must be DWORD aligned unless // the bitmap is RLE compressed. This example shows this. // For Windows 95/98/Me, the width must be WORD aligned unless the // bitmap is RLE compressed. pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 //biSizeImage = 2097152 * -1 * pbmi->bmiHeader.biHeight; // Set biClrImportant to 0, indicating that all of the // device colors are important. pbmi->bmiHeader.biClrImportant = 0;
// Retrieve the color table (RGBQUAD array) and the bits // (array of palette indices) from the DIB. /*if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, DIB_RGB_COLORS)) { MessageBox(hwnd, "Error Get DI Bits", "Error", MB_OK);
// Compute the offset to the array of color indices. hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof (RGBQUAD);
// Copy the BITMAPFILEHEADER into the .BMP file. if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL)) MessageBox(hwnd, "Error writing file1", "Error", MB_OK);
// Copy the BITMAPINFOHEADER and RGBQUAD array into the file. if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof (RGBQUAD), (LPDWORD) &dwTmp, ( NULL))) MessageBox(hwnd, "Error writing file2", "Error", MB_OK);
// Copy the array of color indices into the .BMP file. dwTotal = cb = pbih->biSizeImage; //4292870144
Do I need to post any more info? I haven't seen any suggestions.
I'm going to try and compress the array from a 16bpp to a 8bpp and see if I can make a color pallete that will keep the image in GrayScale. Wish me luck.
Consider this issue closed. The code below can be directly coppied into Microsoft Visual Studio. It gives a basic idea of how to manipulate a grayscale image image with a Color Table. Hopefully this will shed some light on future programmers trying to manipulate BMPs.
void SaveBitmapToFile( LONG lWidth, LONG lHeight);
LPCTSTR StrBmpFileNameBMP = "Image.bmp";
int main(void) {
int width = 1024; int height = 1024; SaveBitmapToFile(width, height); return 0; }
void SaveBitmapToFile( LONG lWidth, LONG lHeight) { BITMAPINFOHEADER bmpInfoHeader = {0}; // Set the size bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER); // Bit count bmpInfoHeader.biBitCount = 8; //image already processed to be 8bpp // Use all colors bmpInfoHeader.biClrImportant = 0; // Use as many colors according to bits per pixel bmpInfoHeader.biClrUsed = 0; // Store as un Compressed bmpInfoHeader.biCompression = BI_RGB; //0 //mgiht want to use BI_BITFIELDS and set up the bmiColors like u did below with the color table // Set the height in pixels bmpInfoHeader.biHeight = -1*lHeight; // Width of the Image in pixels bmpInfoHeader.biWidth = lWidth; // Default number of planes bmpInfoHeader.biPlanes = 1; // Calculate the image size in bytes bmpInfoHeader.biSizeImage = 0; //lWidth* lHeight * (wBitsPerPixel/8); // or try sizeof(RGBTRIPLE)*lWidth*lHeight // possible to set to zero (if not compression)
procframe = procframe - 1048576; //important must move the pointer back to the starting position!!!
RGBQUAD ColorTable[256]; //used for color table purposes for (int i = 0; i < 256; i++) { ColorTable[i].rgbBlue = i; ColorTable[i].rgbGreen = i; ColorTable[i].rgbRed = i; ColorTable[i].rgbReserved = 0; }
BITMAPFILEHEADER bfh = {0}; // This value should be values of BM letters i.e 0×4D42 // 0×4D = M 0×42 = B storing in reverse order to match with endian bfh.bfType=0x4D42;/* 19778 'BM' or bfh.bfType = ‘B’+(’M’ << 8); // <<8 used to shift ‘M’ to end*/ // Offset to the RGBQUAD bfh.bfOffBits = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) + sizeof(ColorTable); //specifies the offset from the beginning of the file to the bitmap data. //prob should add + sizeof(ColorTable) // Total size of image including size of headers bfh.bfSize = bfh.bfOffBits + 1048576 * sizeof(BYTE); // or try sizeof(BITMAPINFOHEADER) // Create the file in disk to write