If someone can send me some code that will print
a 256 Color CBitmap to a monochrome device (like
a laser printer) and I can get it to work in my
project, I'll send you $20.
I've been stuck on this for way too long and can't figure out what's going on. I have a CBitmap
object that is 16 bit aligned than I need to print to a laser printer. I can print 1 bit images and 24 bit images just fine, but I can't print 8 bit images. I've tried building palletes, converting to DIBs, and other fun things, but I don't have a firm grasp on this.
So basically I have a 256 greyscale image (2^8) that I want to send to my printer in an optimal way. It's a 8.5 inchesX11inchesX400DPI greyscale image so printing it in a 24 bit method is not viable (would take way too many MB of ram).
/* make sure bits per pixel is valid */
if (biBits <= 1)
biBits = 1;
else if (biBits <= 4)
biBits = 4;
else if (biBits <= 8)
biBits = 8;
else /* if greater than 8-bit, force to 24-bit */
biBits = 24;
/* alloc memory block to store our bitmap */
hDIB = GlobalAlloc(GHND, dwLen);
/* if we couldn't get memory block */
if (!hDIB)
{
/* clean up and return NULL */
SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
return NULL;
}
/* lock memory and get pointer to it */
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
/* use our bitmap info. to fill BITMAPINFOHEADER */
*lpbi = bi;
/* call GetDIBits with a NULL lpBits param, so it will calculate the
* biSizeImage field for us
*/
GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, NULL, (LPBITMAPINFO)lpbi,
DIB_RGB_COLORS);
/* get the info. returned by GetDIBits and unlock memory block */
bi = *lpbi;
GlobalUnlock(hDIB);
/* if the driver did not fill in the biSizeImage field, make one up */
if (bi.biSizeImage == 0)
bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
/* realloc the buffer big enough to hold all the bits */
dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage;
if (h = GlobalReAlloc(hDIB, dwLen, 0))
hDIB = h;
else
{
/* clean up and return NULL */
GlobalFree(hDIB);
hDIB = NULL;
SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
return NULL;
}
/* lock memory block and get pointer to it */
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
/* call GetDIBits with a NON-NULL lpBits param, and actualy get the
* bits this time
*/
if (GetDIBits(hDC, hBitmap, 0, (WORD)bi.biHeight, (LPSTR)lpbi + (WORD)lpbi
->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,
DIB_RGB_COLORS) == 0)
{
/* clean up and return NULL */
GlobalUnlock(hDIB);
hDIB = NULL;
SelectPalette(hDC, hPal, TRUE);
RealizePalette(hDC);
ReleaseDC(NULL, hDC);
return NULL;
}
bi = *lpbi;
WORD GPrint::DIBNumColors(LPSTR lpDIB)
{
WORD wBitCount; // DIB bit count
// If this is a Windows-style DIB, the number of colors in the
// color table can be less than the number of bits per pixel
// allows for (i.e. lpbi->biClrUsed can be set to some value).
// If this is the case, return the appropriate value.
if (IS_WIN30_DIB(lpDIB))
{
DWORD dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed;
if (dwClrUsed)
return (WORD)dwClrUsed;
}
if (IS_WIN30_DIB(lpDIB))
wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
else
wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
// return number of colors based on bits per pixel
/* Check for valid DIB handle */
if (hDIB == NULL)
return FALSE;
/* Lock down the DIB, and get a pointer to the beginning of the bit
* buffer
*/
lpDIBHdr = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
lpDIBBits = FindDIBBits(lpDIBHdr);
// Get the DIB's palette, then select it into DC
if (pPal != NULL)
{
hPal = (HPALETTE) pPal->m_hObject;
// Select as background since we have
// already realized in forground if needed
hOldPal = ::SelectPalette(hDC, hPal, TRUE);
}
/* Make sure to use the stretching mode best for color pictures */
::SetStretchBltMode(hDC, COLORONCOLOR);
/* return the DIB height if it is a Win 3.0 DIB */
if (IS_WIN30_DIB(lpDIB))
return lpbmi->biHeight;
else /* it is an other-style DIB, so return its height */
return (DWORD)lpbmc->bcHeight;
}
WORD GPrint::PaletteSize(LPSTR lpDIB)
{
/* calculate the size required by the palette */
if (IS_WIN30_DIB (lpDIB))
return (DIBNumColors(lpDIB) * sizeof(RGBQUAD));
else
return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
}
Wes Rogers
May 17th, 1999, 02:46 PM
Dear Fooo,
You could also look at the article I submitted
under "Bitmaps and graphics" at this site,
entitled "Print transparent bitmap via regions".
It works for me for any type of bitmap, and
prints transparently on HP printers.
It is too slow for actual video display, but
works fine for printing.
Yours,
Wes Rogers
Fooo
May 17th, 1999, 05:35 PM
Unfortunately, neither solution has worked yet for printing a 256 Color CBitmap.
It has something to do with the palettes I think. All I get is a big black page still.
I have narrowed my printing code down a little. Here's what I have so far:
(I can basically printing monochrome, although I'm still working on the kinks. I used to have
tons of commented out code of all the different things I've tried).
int nheight = pDC->GetDeviceCaps(VERTRES);
int nwidth = pDC->GetDeviceCaps(HORZRES);
int clip = pDC->GetDeviceCaps(CLIPCAPS);
int pResX = pDC->GetDeviceCaps(LOGPIXELSX);
int pResY = pDC->GetDeviceCaps(LOGPIXELSY);
int outwidth = ((float)nwidth/pResX)*resolution;
int outheight = ((float)nheight/pResY)*resolution;
int ox = bitmap->ReturnBmapInfo()->bmiHeader.biWidth;
int oy = bitmap->ReturnBmapInfo()->bmiHeader.biHeight;
int nsx = (PageAlignInfo->shift_x.Num *pResX)/resolution;
int nsy = (PageAlignInfo->shift_y.Num*pResY)/resolution;
int bpp = bitmap->ReturnBmapInfo()->bmiHeader.biPlanes;
int bpc = bitmap->ReturnBmapInfo()->bmiHeader.biBitCount;
long SIZEIMAGE = bitmap->ReturnBmapInfo()->bmiHeader.biSize;
// Get the bitmap bits
int xf0 = wholething.GetBitmapBits(ImageSize, pBitmapBits);
memDC->SelectObject(oldfoo);
delete memDC;
wholething.DeleteObject();