123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515 |
- // dibapi.cpp
- //
- // Source file for Device-Independent Bitmap (DIB) API. Provides
- // the following functions:
- //
- // PaintDIB() - Painting routine for a DIB
- // CreateDIBPalette() - Creates a palette from a DIB
- // FindDIBBits() - Returns a pointer to the DIB bits
- // DIBWidth() - Gets the width of the DIB
- // DIBHeight() - Gets the height of the DIB
- // PaletteSize() - Gets the size required to store the DIB's palette
- // DIBNumColors() - Calculates the number of colors
- // in the DIB's color table
- // CopyHandle() - Makes a copy of the given global memory block
- //
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1995 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- //PCH
- #include "stdafx.h"
- #include "dibapi.h"
- // System
- #include <io.h>
- #include <errno.h>
- /*************************************************************************
- *
- * PaintDIB()
- *
- * Parameters:
- *
- * HDC hDC - DC to do output to
- *
- * LPRECT lpDCRect - rectangle on DC to do output to
- *
- * HDIB hDIB - handle to global memory with a DIB spec
- * in it followed by the DIB bits
- *
- * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
- *
- * CPalette* pPal - pointer to CPalette containing DIB's palette
- *
- * Return Value:
- *
- * BOOL - TRUE if DIB was drawn, FALSE otherwise
- *
- * Description:
- * Painting routine for a DIB. Calls StretchDIBits() or
- * SetDIBitsToDevice() to paint the DIB. The DIB is
- * output to the specified DC, at the coordinates given
- * in lpDCRect. The area of the DIB to be output is
- * given by lpDIBRect.
- *
- ************************************************************************/
- BOOL WINAPI PaintDIB(HDC hDC,
- LPRECT lpDCRect,
- HDIB hDIB,
- LPRECT lpDIBRect,
- CPalette* pPal)
- {
- LPBITMAPINFOHEADER lpDIBHdr; // Pointer to BITMAPINFOHEADER
- BYTE* 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
- */
- // Note: Many of these functions are using LPSTR where they should really be
- // LPBITMAPINFOHEADERs or BYTE*s etc. I've only changed the ones I'm using.
-
- lpDIBHdr = (LPBITMAPINFOHEADER) ::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, FALSE) ; // 1998-12-07
- // 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
- */// the above does not work with -biHeight 1997-09-30
- //#ifdef _DEBUG
- // {
- // LPBITMAPINFO pBI = (LPBITMAPINFO)lpDIBHdr;
- // BITMAPINFOHEADER bih = pBI->bmiHeader;
- // CString sBH;
- // sBH.Format("\r\nPaintDIB::>( %lu, %ld, %ld, %u, %u, %lu, %lu, %ld, %ld, %lu, %lu )\r\n",
- // /*DWORD*/bih.biSize,
- // /*LONG*/bih.biWidth,
- // /*LONG*/bih.biHeight,
- // /*WORD*/bih.biPlanes,
- // /*WORD*/bih.biBitCount,
- // /*DWORD*/bih.biCompression,
- // /*DWORD*/bih.biSizeImage,
- // /*LONG*/bih.biXPelsPerMeter,
- // /*LONG*/bih.biYPelsPerMeter,
- // /*DWORD*/bih.biClrUsed,
- // /*DWORD*/bih.biClrImportant);
- // TRACE0(sBH);
- // }
- //#endif
- 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;
- }
- /*************************************************************************
- *
- * CreateDIBPalette()
- *
- * Parameter:
- *
- * HDIB hDIB - specifies the DIB
- *
- * Return Value:
- *
- * HPALETTE - specifies the palette
- *
- * Description:
- *
- * This function creates a palette from a DIB by allocating memory for the
- * logical palette, reading and storing the colors from the DIB's color table
- * into the logical palette, creating a palette from this logical palette,
- * and then returning the palette's handle. This allows the DIB to be
- * displayed using the best possible colors (important for DIBs with 256 or
- * more colors).
- *
- ************************************************************************/
- BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal)
- {
- LPLOGPALETTE lpPal; // pointer to a logical palette
- HANDLE hLogPal; // handle to a logical palette
- // HPALETTE hPal = NULL; // handle to a palette
- int i; // loop index
- WORD wNumColors; // number of colors in color table
- LPBITMAPINFOHEADER lpbi; // pointer to packed-DIB
- LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0)
- LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (old)
- BOOL bWinStyleDIB; // flag which signifies whether this is a Win3.0 DIB
- BOOL bResult = FALSE;
- /* if handle to DIB is invalid, return FALSE */
- if (hDIB == NULL)
- return FALSE;
- lpbi = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDIB);
- /* get pointer to BITMAPINFO (Win 3.0) */
- lpbmi = (LPBITMAPINFO)lpbi;
- /* get pointer to BITMAPCOREINFO (old 1.x) */
- lpbmc = (LPBITMAPCOREINFO)lpbi;
- /* get the number of colors in the DIB */
- wNumColors = ::DIBNumColors(lpbi);
- if (wNumColors != 0)
- {
- /* allocate memory block for logical palette */
- hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
- + sizeof(PALETTEENTRY)
- * wNumColors);
- /* if not enough memory, clean up and return NULL */
- if (hLogPal == 0)
- {
- ::GlobalUnlock((HGLOBAL) hDIB);
- return FALSE;
- }
- lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
- /* set version and number of palette entries */
- lpPal->palVersion = PALVERSION;
- lpPal->palNumEntries = (WORD)wNumColors;
- /* is this a Win 3.0 DIB? */
- bWinStyleDIB = IS_WIN30_DIB(lpbi);
- for (i = 0; i < (int)wNumColors; i++)
- {
- if (bWinStyleDIB)
- {
- lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
- lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
- lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
- lpPal->palPalEntry[i].peFlags = 0;
- }
- else
- {
- lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
- lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
- lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
- lpPal->palPalEntry[i].peFlags = 0;
- }
- }
- /* create the palette and get handle to it */
- bResult = pPal->CreatePalette(lpPal);
- ::GlobalUnlock((HGLOBAL) hLogPal);
- ::GlobalFree((HGLOBAL) hLogPal);
- }
- ::GlobalUnlock((HGLOBAL) hDIB);
- return bResult;
- }
- /*************************************************************************
- *
- * FindDIBBits()
- *
- * Parameter:
- *
- * LPBITMAPINFOHEADER lpbi - pointer to packed-DIB memory block
- *
- * Return Value:
- *
- * BYTE* - pointer to the DIB bits
- *
- * Description:
- *
- * This function calculates the address of the DIB's bits and returns a
- * pointer to the DIB bits.
- *
- ************************************************************************/
- BYTE* WINAPI FindDIBBits(LPBITMAPINFOHEADER lpbi)
- {
- return (BYTE*)lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi);
- }
- /*************************************************************************
- *
- * DIBWidth()
- *
- * Parameter:
- *
- * LPSTR lpbi - pointer to packed-DIB memory block
- *
- * Return Value:
- *
- * DWORD - width of the DIB
- *
- * Description:
- *
- * This function gets the width of the DIB from the BITMAPINFOHEADER
- * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
- * width field if it is an other-style DIB.
- *
- ************************************************************************/
- DWORD WINAPI DIBWidth(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 Win 3.0 and old) */
- lpbmi = (LPBITMAPINFOHEADER)lpDIB;
- lpbmc = (LPBITMAPCOREHEADER)lpDIB;
- /* return the DIB width if it is a Win 3.0 DIB */
- if (IS_WIN30_DIB(lpDIB))
- return lpbmi->biWidth;
- else /* it is an other-style DIB, so return its width */
- return (DWORD)lpbmc->bcWidth;
- }
- /*************************************************************************
- *
- * DIBHeight()
- *
- * Parameter:
- *
- * LPSTR lpbi - pointer to packed-DIB memory block
- *
- * Return Value:
- *
- * DWORD - height of the DIB
- *
- * Description:
- *
- * This function gets the height of the DIB from the BITMAPINFOHEADER
- * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
- * height field if it is an other-style DIB.
- *
- ************************************************************************/
- DWORD WINAPI DIBHeight(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;
- }
- /*************************************************************************
- *
- * PaletteSize()
- *
- * Parameter:
- *
- * LPSTR lpbi - pointer to packed-DIB memory block
- *
- * Return Value:
- *
- * WORD - size of the color palette of the DIB
- *
- * Description:
- *
- * This function gets the size required to store the DIB's palette by
- * multiplying the number of colors by the size of an RGBQUAD (for a
- * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an other-
- * style DIB).
- *
- ************************************************************************/
- WORD WINAPI PaletteSize(LPBITMAPINFOHEADER lpbi)
- {
- /* calculate the size required by the palette */
- if (IS_WIN30_DIB (lpbi))
- return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
- else
- return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
- }
- /*************************************************************************
- *
- * DIBNumColors()
- *
- * Parameter:
- *
- * LPSTR lpbi - pointer to packed-DIB memory block
- *
- * Return Value:
- *
- * WORD - number of colors in the color table
- *
- * Description:
- *
- * This function calculates the number of colors in the DIB's color table
- * by finding the bits per pixel for the DIB (whether Win3.0 or other-style
- * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
- * if 24, no colors in color table.
- *
- ************************************************************************/
- WORD WINAPI DIBNumColors(LPBITMAPINFOHEADER lpbi)
- {
- 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(lpbi))
- {
- DWORD dwClrUsed;
- dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
- if (dwClrUsed != 0)
- return (WORD)dwClrUsed;
- }
- /* Calculate the number of colors in the color table based on
- * the number of bits per pixel for the DIB.
- */
- if (IS_WIN30_DIB(lpbi))
- wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
- else
- wBitCount = ((LPBITMAPCOREHEADER)lpbi)->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;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- //// Clipboard support
- //---------------------------------------------------------------------
- //
- // Function: CopyHandle (from SDK DibView sample clipbrd.c)
- //
- // Purpose: Makes a copy of the given global memory block. Returns
- // a handle to the new memory block (NULL on error).
- //
- // Routine stolen verbatim out of ShowDIB.
- //
- // Parms: h == Handle to global memory to duplicate.
- //
- // Returns: Handle to new global memory block.
- //
- //---------------------------------------------------------------------
- HGLOBAL WINAPI CopyHandle (HGLOBAL h)
- {
- if (h == NULL)
- return NULL;
- SIZE_T dwLen = ::GlobalSize((HGLOBAL) h);
- HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen);
- if (hCopy != NULL)
- {
- void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
- void* lp = ::GlobalLock((HGLOBAL) h);
- memcpy(lpCopy, lp, dwLen);
- ::GlobalUnlock(hCopy);
- ::GlobalUnlock(h);
- }
- return hCopy;
- }
|