// dibapi.cpp // // stolen from diblook MFC sample, and modified to kill off the Alloc/Lock style // code. // // 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 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Microsoft Foundation Classes Reference and Microsoft // QuickHelp and/or WinHelp documentation provided with the library. // See these sources for detailed information regarding the // Microsoft Foundation Classes product. #include "stdafx.h" #include "dibapi.h" /************************************************************************* * * PaintDIB() * * Parameters: * * HDC hDC - DC to do output to * * LPRECT lpDCRect - rectangle on DC to do output to * * LPSTR lpDIBHdr - pointer to packed-DIB memory block * * 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, LPSTR lpDIBHdr, LPRECT lpDIBRect, CPalette* pPal, DWORD dwRop) { 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 */ if (lpDIBHdr == NULL) return FALSE; 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); RealizePalette (hDC); } /* 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 dwRop); // dwROP /* Reselect old palette */ if (hOldPal != NULL) { ::SelectPalette(hDC, hOldPal, TRUE); } return bSuccess; } //--------------------------------------------------------------------- // // Function: PaintDDB // // stolen from DIBLook sample. // // Purpose: Painting routine for a DDB. Calls BitBlt() or // StretchBlt() to paint the DDB. The DDB is // output to the specified DC, at the coordinates given // in lpDCRect. The area of the DDB to be output is // given by lpDDBRect. The specified palette is used. // // IMPORTANT assumption: The palette has been realized // elsewhere... We won't bother figuring out whether it // should be realized as a foreground or background palette // here. // // Parms: hDC == DC to do output to. // lpDCRect == Rectangle on DC to do output to. // hDDB == Handle to the device dependent bitmap (DDB). // lpDDBRect == Rect of DDB to output into lpDCRect. // hPal == Palette to be used. // // History: Date Reason // 6/01/91 Created // //--------------------------------------------------------------------- BOOL WINAPI PaintDDB (HDC hDC, LPRECT lpDCRect, HBITMAP hDDB, LPRECT lpDDBRect, CPalette *pPal, DWORD dwRop) { HDC hMemDC; HBITMAP hOldBitmap; HPALETTE hOldPal1 = NULL; HPALETTE hOldPal2 = NULL; HPALETTE hPal = (HPALETTE)pPal->GetSafeHandle(); hMemDC = CreateCompatibleDC (hDC); if (!hMemDC) return FALSE; if (hPal) { hOldPal1 = SelectPalette (hMemDC, hPal, FALSE); hOldPal2 = SelectPalette (hDC, hPal, FALSE); // Assume the palette's already been realized (no need to // call RealizePalette(). It should have been realized in // our WM_QUERYNEWPALETTE or WM_PALETTECHANGED messages... } hOldBitmap = (HBITMAP)SelectObject (hMemDC, hDDB); SetStretchBltMode (hDC, COLORONCOLOR); if ((RECTWIDTH (lpDCRect) == RECTWIDTH (lpDDBRect)) && (RECTHEIGHT (lpDCRect) == RECTHEIGHT (lpDDBRect))) { BitBlt (hDC, lpDCRect->left, lpDCRect->top, lpDCRect->right - lpDCRect->left, lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left, lpDDBRect->top, dwRop); } else StretchBlt (hDC, lpDCRect->left, lpDCRect->top, lpDCRect->right - lpDCRect->left, lpDCRect->bottom - lpDCRect->top, hMemDC, lpDDBRect->left, lpDDBRect->top, lpDDBRect->right - lpDDBRect->left, lpDDBRect->bottom - lpDDBRect->top, dwRop); SelectObject (hMemDC, hOldBitmap); if (hOldPal1) SelectPalette (hMemDC, hOldPal1, FALSE); if (hOldPal2) SelectPalette (hDC, hOldPal2, FALSE); DeleteDC (hMemDC); return TRUE; } //--------------------------------------------------------------------- // // Function: DIBToBitmap // // stolen from DIBLook sample. // // Purpose: Given a handle to global memory with a DIB spec in it, // and a palette, returns a device dependent bitmap. The // The DDB will be rendered with the specified palette. // // Parms: hDIB == HANDLE to global memory containing a DIB spec // (either BITMAPINFOHEADER or BITMAPCOREHEADER) // hPal == Palette to render the DDB with. If it's NULL, // use the default palette. // // History: Date Reason // 6/01/91 Created // //--------------------------------------------------------------------- HBITMAP WINAPI DIBToBitmap (LPSTR lpDIBHdr, CPalette *pPal) { LPSTR lpDIBBits; HBITMAP hBitmap; HDC hDC; HPALETTE hOldPal = NULL; HPALETTE hPal = (HPALETTE)pPal->GetSafeHandle(); lpDIBBits = FindDIBBits (lpDIBHdr); hDC = GetDC (NULL); if (!hDC) return NULL; if (hPal) hOldPal = SelectPalette (hDC, hPal, FALSE); RealizePalette (hDC); hBitmap = CreateDIBitmap (hDC, (LPBITMAPINFOHEADER) lpDIBHdr, CBM_INIT, lpDIBBits, (LPBITMAPINFO) lpDIBHdr, DIB_RGB_COLORS); if (!hBitmap) return NULL; if (hOldPal) SelectPalette (hDC, hOldPal, FALSE); ReleaseDC (NULL, hDC); return hBitmap; } /************************************************************************* * * CreateDIBPalette() * * Parameter: * * LPSTR lpbi - pointer to packed-DIB memory block * * 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(LPSTR lpbi, CPalette* pPal) { LPLOGPALETTE lpPal; // pointer to a logical palette int i; // loop index WORD wNumColors; // number of colors in color table LPBITMAPINFO lpbmi; // pointer to BITMAPCOREINFO structure (win3) LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (old) BOOL bWinStyleDIB; // flag which signifies whether this is a Win3.0 DIB BOOL bResult = FALSE; /* if DIB is invalid, return FALSE */ if (lpbi == NULL) return FALSE; lpbmi = (LPBITMAPINFO)lpbi; /* get pointer to BITMAPCOREINFO (old 1.x) */ lpbmc = (LPBITMAPCOREINFO)lpbmi; /* get the number of colors in the DIB */ wNumColors = ::DIBNumColors(lpbi); if (wNumColors != 0) { /* allocate memory block for logical palette */ lpPal = (LPLOGPALETTE)new char[sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wNumColors]; /* if not enough memory, clean up and return NULL */ if (lpPal == 0) return FALSE; /* 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); delete lpPal; } return bResult; } /************************************************************************* * * FindDIBBits() * * Parameter: * * LPSTR lpbi - pointer to packed-DIB memory block * * Return Value: * * LPSTR - pointer to the DIB bits * * Description: * * This function calculates the address of the DIB's bits and returns a * pointer to the DIB bits. * ************************************************************************/ LPSTR WINAPI FindDIBBits(LPSTR lpbi) { return (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(LPSTR 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(LPSTR 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. // //--------------------------------------------------------------------- HANDLE WINAPI CopyHandle (HANDLE h) { BYTE *lpCopy; BYTE *lp; HANDLE hCopy; SIZE_T dwLen; if (h == NULL) return NULL; dwLen = ::GlobalSize((HGLOBAL) h); if ((hCopy = (HANDLE) ::GlobalAlloc (GHND, dwLen)) != NULL) { lpCopy = (BYTE *) ::GlobalLock((HGLOBAL) hCopy); lp = (BYTE *) ::GlobalLock((HGLOBAL) h); while (dwLen--) *lpCopy++ = *lp++; ::GlobalUnlock((HGLOBAL) hCopy); ::GlobalUnlock((HGLOBAL) h); } return hCopy; }