CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4
  1. #1
    Join Date
    May 1999
    Posts
    11

    Printing 2^8 (256 Color) Bitmaps - REWARD!:)

    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).

    Please help! - thanks in advance!


  2. #2
    Join Date
    May 1999
    Posts
    5

    Re: Printing 2^8 (256 Color) Bitmaps - REWARD!:)

    Here is the code, and it works

    Have fun

    Lars Dirks [email protected]


    BOOL GPrint::Bitmap(int iID, double dXPos, double dYPos, double dXSize, double dYSize, double xScale)
    {
    BITMAP bm;
    CBitmap bitmap;
    CBitmap* pOldBitmap = NULL;
    CRect rcDest, rc_source;
    CDC sourceDC;

    if (!bitmap.LoadBitmap(iID))
    return FALSE;

    bitmap.GetObject(sizeof(BITMAP), &bm);

    rc_source.bottom = bm.bmHeight;
    rc_source.top = 0;
    rc_source.left = 0;
    rc_source.right = bm.bmWidth;

    if (!sourceDC.CreateCompatibleDC(m_pDC))
    return FALSE; // not enough memory

    pOldBitmap = sourceDC.SelectObject(&bitmap);

    bitmap.GetObject(sizeof(bm), &bm);

    sourceDC.SelectObject(&bitmap);

    rcDest = CRect(m_iPixLeftMargin + (int)(dXPos / 25.4 * m_iLogPixelsX),
    m_iPixTopMargin + (int)(dYPos / 25.4 * m_iLogPixelsY),
    m_iPixLeftMargin + (int)((dXPos + dXSize) / 25.4 * m_iLogPixelsX),
    m_iPixTopMargin + (int)((dYPos + dYSize) / 25.4 * m_iLogPixelsY));

    if (m_pDC->IsPrinting())
    {
    PaintDIB(m_pDC->GetSafeHdc(),&rcDest,BitmapToDIB(bitmap, NULL), &rc_source, NULL);
    }
    else
    m_pDC->StretchBlt(m_iPixLeftMargin + (int)(dXPos / 25.4 * m_iLogPixelsX),
    m_iPixTopMargin + (int)(dYPos / 25.4 * m_iLogPixelsY),
    rcDest.Width(),
    rcDest.Height(),
    &sourceDC,
    0,
    0,
    bm.bmWidth,
    bm.bmHeight,
    SRCCOPY);

    sourceDC.SelectObject(pOldBitmap);

    return TRUE;
    }

    HANDLE GPrint::BitmapToDIB(HBITMAP hBitmap, HPALETTE hPal)
    {
    BITMAP bm; // bitmap structure
    BITMAPINFOHEADER bi; // bitmap header
    BITMAPINFOHEADER FAR *lpbi; // pointer to BITMAPINFOHEADER
    DWORD dwLen; // size of memory block
    HANDLE hDIB, h; // handle to DIB, temp handle
    HDC hDC; // handle to DC
    WORD biBits; // bits per pixel

    /* check if bitmap handle is valid */

    if (!hBitmap)
    return NULL;

    /* fill in BITMAP structure, return NULL if it didn't work */
    if (!GetObject(hBitmap, sizeof(bm), (LPSTR)&bm))
    return NULL;

    /* if no palette is specified, use default palette */
    if (hPal == NULL)
    hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);

    /* calculate bits per pixel */
    biBits = bm.bmPlanes * bm.bmBitsPixel;

    /* 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;

    /* initialize BITMAPINFOHEADER */
    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = bm.bmWidth;
    bi.biHeight = bm.bmHeight;
    bi.biPlanes = 1;
    bi.biBitCount = biBits;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;

    /* calculate size of memory block required to store BITMAPINFO */
    dwLen = bi.biSize + PaletteSize((LPSTR)&bi);

    /* get a DC */
    hDC = GetDC(NULL);

    /* select and realize our palette */
    hPal = SelectPalette(hDC, hPal, FALSE);
    RealizePalette(hDC);

    /* 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;

    /* clean up */
    GlobalUnlock(hDIB);
    SelectPalette(hDC, hPal, TRUE);
    RealizePalette(hDC);
    ReleaseDC(NULL, hDC);

    /* return handle to the DIB */
    return hDIB;
    }

    WORD GPrint:IBNumColors(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

    switch (wBitCount)
    {
    case 1:
    return 2;

    case 4:
    return 16;

    case 8:
    return 256;

    default:
    return 0;
    }
    }

    BOOL WINAPI GPrint::PaintDIB(HDC hDC,
    LPRECT lpDCRect,
    HANDLE hDIB,
    LPRECT lpDIBRect,
    CPalette* pPal)
    {
    LPSTR lpDIBHdr; // Pointer to BITMAPINFOHEADER
    LPSTR lpDIBBits; // Pointer to DIB bits
    BOOL bSuccess=FALSE; // Success/fail flag
    HPALETTE hPal=NULL; // Our DIB's palette
    HPALETTE hOldPal=NULL; // Previous palette

    /* 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);

    /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
    if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&
    (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
    bSuccess = ::SetDIBitsToDevice(hDC, // hDC
    lpDCRect->left, // DestX
    lpDCRect->top, // DestY
    RECTWIDTH(lpDCRect), // nDestWidth
    RECTHEIGHT(lpDCRect), // nDestHeight
    lpDIBRect->left, // SrcX
    (int)DIBHeight(lpDIBHdr) -
    lpDIBRect->top -
    RECTHEIGHT(lpDIBRect), // SrcY
    0, // nStartScan
    (WORD)DIBHeight(lpDIBHdr), // nNumScans
    lpDIBBits, // lpBits
    (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo
    DIB_RGB_COLORS); // wUsage
    else
    bSuccess = ::StretchDIBits(hDC, // hDC
    lpDCRect->left, // DestX
    lpDCRect->top, // DestY
    RECTWIDTH(lpDCRect), // nDestWidth
    RECTHEIGHT(lpDCRect), // nDestHeight
    lpDIBRect->left, // SrcX
    lpDIBRect->top, // SrcY
    RECTWIDTH(lpDIBRect), // wSrcWidth
    RECTHEIGHT(lpDIBRect), // wSrcHeight
    lpDIBBits, // lpBits
    (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo
    DIB_RGB_COLORS, // wUsage
    SRCCOPY); // dwROP

    ::GlobalUnlock((HGLOBAL) hDIB);

    /* Reselect old palette */
    if (hOldPal != NULL)
    {
    ::SelectPalette(hDC, hOldPal, TRUE);
    }

    return bSuccess;
    }

    LPSTR WINAPI GPrint::FindDIBBits(LPSTR lpbi)
    {
    return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi));
    }

    DWORD WINAPI GPrint:IBHeight(LPSTR lpDIB)
    {
    LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
    LPBITMAPCOREHEADER lpbmc; // pointer to an other-style DIB

    /* point to the header (whether old or Win 3.0 */

    lpbmi = (LPBITMAPINFOHEADER)lpDIB;
    lpbmc = (LPBITMAPCOREHEADER)lpDIB;

    /* 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));
    }



  3. #3
    Join Date
    Apr 1999
    Posts
    53

    Re: Printing 2^8 (256 Color) Bitmaps - REWARD!:)

    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


  4. #4
    Join Date
    May 1999
    Posts
    11

    Re: Printing 2^8 (256 Color) Bitmaps - REWARD!:)

    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;

    //START THE PRINTING/SCALING
    CBitmap* tbits = (CBitmap*)bitmap->Memdc->SelectObject(bitmap->cbits);
    CDC *memDC = new CDC;
    CBitmap wholething;
    wholething.CreateBitmap( outwidth, outheight, bpp, bpc, NULL);
    memDC->CreateCompatibleDC(bitmap->Memdc);
    CBitmap *oldfoo = memDC->SelectObject(&wholething);

    memDC->BitBlt(0,0, outwidth, outheight, NULL, 0,0,WHITENESS);
    memDC->BitBlt(PageAlignInfo->shift_x.Num,PageAlignInfo->shift_y.Num, outwidth, outheight, bitmap->Memdc, 0,0,SRCCOPY);

    bitmap->Memdc->SelectObject(tbits);
    delete bitmap;

    //wholething is now our image that should be sclaed to the paper size


    BITMAPINFO BitmapInfo;
    BitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
    BitmapInfo.bmiHeader.biWidth = outwidth;
    BitmapInfo.bmiHeader.biHeight = outheight;
    BitmapInfo.bmiHeader.biPlanes = 1;
    BitmapInfo.bmiHeader.biBitCount = bpc;
    BitmapInfo.bmiHeader.biCompression = BI_RGB;
    BitmapInfo.bmiHeader.biSizeImage = 0;
    BitmapInfo.bmiHeader.biXPelsPerMeter = 0;
    BitmapInfo.bmiHeader.biYPelsPerMeter = 0;
    BitmapInfo.bmiHeader.biClrUsed = (1<<bpc);
    BitmapInfo.bmiHeader.biClrImportant = 0;
    /*
    //MEMSET THE PALETTE
    for (int i=0; i< (1 << biBits); i++) {
    RGBQUAD *foo = (RGBQUAD *)(lpbi + lpbi->biSize + i*sizeof(RGBQUAD));
    foo->rgbBlue = i;
    foo->rgbGreen = i;
    foo->rgbRed = i;
    foo->rgbReserved = i;
    }

    lpbi->biClrUsed=(1 << biBits);
    */

    long ImageSize = ( ( ( ( outwidth * bpc ) + 31 ) & ~31 ) >> 3 )
    * outheight;

    BitmapInfo.bmiHeader.biSizeImage = ImageSize;

    // This would calc the palette size
    //ImageSize += BitmapInfo.bmiHeader.biSize + (1<<bpc)*sizeof(RGBQUAD);

    BYTE* pBitmapBits = new BYTE[ ImageSize ];

    // Select a palette for the PDC
    CPalette pal;
    UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * (1 << bpc));
    LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];

    pLP->palVersion = 0x300;
    pLP->palNumEntries = (1 << bpc);

    for( int i=0; i < pLP->palNumEntries; i++)
    {
    pLP->palPalEntry[i].peRed = i;
    pLP->palPalEntry[i].peGreen = i;
    pLP->palPalEntry[i].peBlue = i;
    pLP->palPalEntry[i].peFlags = 0;
    }

    pal.CreatePalette( pLP );

    delete[] pLP;

    HPALETTE hPal = SelectPalette(pDC->GetSafeHdc(), (HPALETTE)pal, FALSE);
    RealizePalette(pDC->GetSafeHdc());

    // Get the bitmap bits
    int xf0 = wholething.GetBitmapBits(ImageSize, pBitmapBits);
    memDC->SelectObject(oldfoo);
    delete memDC;
    wholething.DeleteObject();

    //StretchDIBits
    int boogy = StretchDIBits(
    pDC->GetSafeHdc(),
    0,
    0,
    nwidth-1,
    nheight-1,
    0,
    0,
    outwidth,
    outheight,
    (LPVOID) pBitmapBits,
    &BitmapInfo,
    DIB_RGB_COLORS //DIB_RGB_COLORS DIB_PAL_COLORS
    ,SRCCOPY
    );

    delete pBitmapBits;
    SelectPalette(pDC->GetSafeHdc(), hPal, FALSE);
    RealizePalette(pDC->GetSafeHdc());

    } // end else scan file opened
    } // end if front page
    iCurPage++;
    }



Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured