DIBAPI.CPP
上传用户:zbjinju
上传日期:2022-07-30
资源大小:11893k
文件大小:14k
源码类别:

图形图象

开发平台:

Visual C++

  1. //  dibapi.cpp
  2. //
  3. //  Source file for Device-Independent Bitmap (DIB) API.  Provides
  4. //  the following functions:
  5. //
  6. //  PaintDIB()          - Painting routine for a DIB
  7. //  CreateDIBPalette()  - Creates a palette from a DIB
  8. //  FindDIBBits()       - Returns a pointer to the DIB bits
  9. //  DIBWidth()          - Gets the width of the DIB
  10. //  DIBHeight()         - Gets the height of the DIB
  11. //  PaletteSize()       - Gets the size required to store the DIB's palette
  12. //  DIBNumColors()      - Calculates the number of colors
  13. //                        in the DIB's color table
  14. //  CopyHandle()        - Makes a copy of the given global memory block
  15. //
  16. // This is a part of the Microsoft Foundation Classes C++ library.
  17. // Copyright (C) 1992-1998 Microsoft Corporation
  18. // All rights reserved.
  19. //
  20. // This source code is only intended as a supplement to the
  21. // Microsoft Foundation Classes Reference and related
  22. // electronic documentation provided with the library.
  23. // See these sources for detailed information regarding the
  24. // Microsoft Foundation Classes product.
  25. #include "stdafx.h"
  26. #include "dibapi.h"
  27. #include <io.h>
  28. #include <errno.h>
  29. /*************************************************************************
  30.  *
  31.  * PaintDIB()
  32.  *
  33.  * Parameters:
  34.  *
  35.  * HDC hDC          - DC to do output to
  36.  *
  37.  * LPRECT lpDCRect  - rectangle on DC to do output to
  38.  *
  39.  * HDIB hDIB        - handle to global memory with a DIB spec
  40.  *                    in it followed by the DIB bits
  41.  *
  42.  * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
  43.  *
  44.  * CPalette* pPal   - pointer to CPalette containing DIB's palette
  45.  *
  46.  * Return Value:
  47.  *
  48.  * BOOL             - TRUE if DIB was drawn, FALSE otherwise
  49.  *
  50.  * Description:
  51.  *   Painting routine for a DIB.  Calls StretchDIBits() or
  52.  *   SetDIBitsToDevice() to paint the DIB.  The DIB is
  53.  *   output to the specified DC, at the coordinates given
  54.  *   in lpDCRect.  The area of the DIB to be output is
  55.  *   given by lpDIBRect.
  56.  *
  57.  ************************************************************************/
  58. BOOL WINAPI PaintDIB(HDC     hDC,
  59. LPRECT  lpDCRect,
  60. HDIB    hDIB,
  61. LPRECT  lpDIBRect,
  62. CPalette* pPal)
  63. {
  64. LPSTR    lpDIBHdr;            // Pointer to BITMAPINFOHEADER
  65. LPSTR    lpDIBBits;           // Pointer to DIB bits
  66. BOOL     bSuccess=FALSE;      // Success/fail flag
  67. HPALETTE hPal=NULL;           // Our DIB's palette
  68. HPALETTE hOldPal=NULL;        // Previous palette
  69. /* Check for valid DIB handle */
  70. if (hDIB == NULL)
  71. return FALSE;
  72. /* Lock down the DIB, and get a pointer to the beginning of the bit
  73.  *  buffer
  74.  */
  75. lpDIBHdr  = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  76. lpDIBBits = ::FindDIBBits(lpDIBHdr);
  77. // Get the DIB's palette, then select it into DC
  78. if (pPal != NULL)
  79. {
  80. hPal = (HPALETTE) pPal->m_hObject;
  81. // Select as background since we have
  82. // already realized in forground if needed
  83. hOldPal = ::SelectPalette(hDC, hPal, TRUE);
  84. }
  85. /* Make sure to use the stretching mode best for color pictures */
  86. ::SetStretchBltMode(hDC, COLORONCOLOR);
  87. /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
  88. if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDIBRect)) &&
  89.    (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
  90. bSuccess = ::SetDIBitsToDevice(hDC,                    // hDC
  91.    lpDCRect->left,             // DestX
  92.    lpDCRect->top,              // DestY
  93.    RECTWIDTH(lpDCRect),        // nDestWidth
  94.    RECTHEIGHT(lpDCRect),       // nDestHeight
  95.    lpDIBRect->left,            // SrcX
  96.    (int)DIBHeight(lpDIBHdr) -
  97.   lpDIBRect->top -
  98.   RECTHEIGHT(lpDIBRect),   // SrcY
  99.    0,                          // nStartScan
  100.    (WORD)DIBHeight(lpDIBHdr),  // nNumScans
  101.    lpDIBBits,                  // lpBits
  102.    (LPBITMAPINFO)lpDIBHdr,     // lpBitsInfo
  103.    DIB_RGB_COLORS);            // wUsage
  104.    else
  105.   bSuccess = ::StretchDIBits(hDC,                          // hDC
  106.    lpDCRect->left,                 // DestX
  107.    lpDCRect->top,                  // DestY
  108.    RECTWIDTH(lpDCRect),            // nDestWidth
  109.    RECTHEIGHT(lpDCRect),           // nDestHeight
  110.    lpDIBRect->left,                // SrcX
  111.    lpDIBRect->top,                 // SrcY
  112.    RECTWIDTH(lpDIBRect),           // wSrcWidth
  113.    RECTHEIGHT(lpDIBRect),          // wSrcHeight
  114.    lpDIBBits,                      // lpBits
  115.    (LPBITMAPINFO)lpDIBHdr,         // lpBitsInfo
  116.    DIB_RGB_COLORS,                 // wUsage
  117.    SRCCOPY);                       // dwROP
  118.    ::GlobalUnlock((HGLOBAL) hDIB);
  119. /* Reselect old palette */
  120. if (hOldPal != NULL)
  121. {
  122. ::SelectPalette(hDC, hOldPal, TRUE);
  123. }
  124.    return bSuccess;
  125. }
  126. /*************************************************************************
  127.  *
  128.  * CreateDIBPalette()
  129.  *
  130.  * Parameter:
  131.  *
  132.  * HDIB hDIB        - specifies the DIB
  133.  *
  134.  * Return Value:
  135.  *
  136.  * HPALETTE         - specifies the palette
  137.  *
  138.  * Description:
  139.  *
  140.  * This function creates a palette from a DIB by allocating memory for the
  141.  * logical palette, reading and storing the colors from the DIB's color table
  142.  * into the logical palette, creating a palette from this logical palette,
  143.  * and then returning the palette's handle. This allows the DIB to be
  144.  * displayed using the best possible colors (important for DIBs with 256 or
  145.  * more colors).
  146.  *
  147.  ************************************************************************/
  148. BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal)
  149. {
  150. LPLOGPALETTE lpPal;      // pointer to a logical palette
  151. HANDLE hLogPal;          // handle to a logical palette
  152. HPALETTE hPal = NULL;    // handle to a palette
  153. int i;                   // loop index
  154. WORD wNumColors;         // number of colors in color table
  155. LPSTR lpbi;              // pointer to packed-DIB
  156. LPBITMAPINFO lpbmi;      // pointer to BITMAPINFO structure (Win3.0)
  157. LPBITMAPCOREINFO lpbmc;  // pointer to BITMAPCOREINFO structure (old)
  158. BOOL bWinStyleDIB;       // flag which signifies whether this is a Win3.0 DIB
  159. BOOL bResult = FALSE;
  160. /* if handle to DIB is invalid, return FALSE */
  161. if (hDIB == NULL)
  162.   return FALSE;
  163.    lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  164.    /* get pointer to BITMAPINFO (Win 3.0) */
  165.    lpbmi = (LPBITMAPINFO)lpbi;
  166.    /* get pointer to BITMAPCOREINFO (old 1.x) */
  167.    lpbmc = (LPBITMAPCOREINFO)lpbi;
  168.    /* get the number of colors in the DIB */
  169.    wNumColors = ::DIBNumColors(lpbi);
  170.    if (wNumColors != 0)
  171.    {
  172. /* allocate memory block for logical palette */
  173. hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
  174. + sizeof(PALETTEENTRY)
  175. * wNumColors);
  176. /* if not enough memory, clean up and return NULL */
  177. if (hLogPal == 0)
  178. {
  179. ::GlobalUnlock((HGLOBAL) hDIB);
  180. return FALSE;
  181. }
  182. lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
  183. /* set version and number of palette entries */
  184. lpPal->palVersion = PALVERSION;
  185. lpPal->palNumEntries = (WORD)wNumColors;
  186. /* is this a Win 3.0 DIB? */
  187. bWinStyleDIB = IS_WIN30_DIB(lpbi);
  188. for (i = 0; i < (int)wNumColors; i++)
  189. {
  190. if (bWinStyleDIB)
  191. {
  192. lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
  193. lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
  194. lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
  195. lpPal->palPalEntry[i].peFlags = 0;
  196. }
  197. else
  198. {
  199. lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
  200. lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
  201. lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
  202. lpPal->palPalEntry[i].peFlags = 0;
  203. }
  204. }
  205. /* create the palette and get handle to it */
  206. bResult = pPal->CreatePalette(lpPal);
  207. ::GlobalUnlock((HGLOBAL) hLogPal);
  208. ::GlobalFree((HGLOBAL) hLogPal);
  209. }
  210. ::GlobalUnlock((HGLOBAL) hDIB);
  211. return bResult;
  212. }
  213. /*************************************************************************
  214.  *
  215.  * FindDIBBits()
  216.  *
  217.  * Parameter:
  218.  *
  219.  * LPSTR lpbi       - pointer to packed-DIB memory block
  220.  *
  221.  * Return Value:
  222.  *
  223.  * LPSTR            - pointer to the DIB bits
  224.  *
  225.  * Description:
  226.  *
  227.  * This function calculates the address of the DIB's bits and returns a
  228.  * pointer to the DIB bits.
  229.  *
  230.  ************************************************************************/
  231. LPSTR WINAPI FindDIBBits(LPSTR lpbi)
  232. {
  233. return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi));
  234. }
  235. /*************************************************************************
  236.  *
  237.  * DIBWidth()
  238.  *
  239.  * Parameter:
  240.  *
  241.  * LPSTR lpbi       - pointer to packed-DIB memory block
  242.  *
  243.  * Return Value:
  244.  *
  245.  * DWORD            - width of the DIB
  246.  *
  247.  * Description:
  248.  *
  249.  * This function gets the width of the DIB from the BITMAPINFOHEADER
  250.  * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  251.  * width field if it is an other-style DIB.
  252.  *
  253.  ************************************************************************/
  254. DWORD WINAPI DIBWidth(LPSTR lpDIB)
  255. {
  256. LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
  257. LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB
  258. /* point to the header (whether Win 3.0 and old) */
  259. lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  260. lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  261. /* return the DIB width if it is a Win 3.0 DIB */
  262. if (IS_WIN30_DIB(lpDIB))
  263. return lpbmi->biWidth;
  264. else  /* it is an other-style DIB, so return its width */
  265. return (DWORD)lpbmc->bcWidth;
  266. }
  267. /*************************************************************************
  268.  *
  269.  * DIBHeight()
  270.  *
  271.  * Parameter:
  272.  *
  273.  * LPSTR lpbi       - pointer to packed-DIB memory block
  274.  *
  275.  * Return Value:
  276.  *
  277.  * DWORD            - height of the DIB
  278.  *
  279.  * Description:
  280.  *
  281.  * This function gets the height of the DIB from the BITMAPINFOHEADER
  282.  * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  283.  * height field if it is an other-style DIB.
  284.  *
  285.  ************************************************************************/
  286. DWORD WINAPI DIBHeight(LPSTR lpDIB)
  287. {
  288. LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
  289. LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB
  290. /* point to the header (whether old or Win 3.0 */
  291. lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  292. lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  293. /* return the DIB height if it is a Win 3.0 DIB */
  294. if (IS_WIN30_DIB(lpDIB))
  295. return lpbmi->biHeight;
  296. else  /* it is an other-style DIB, so return its height */
  297. return (DWORD)lpbmc->bcHeight;
  298. }
  299. /*************************************************************************
  300.  *
  301.  * PaletteSize()
  302.  *
  303.  * Parameter:
  304.  *
  305.  * LPSTR lpbi       - pointer to packed-DIB memory block
  306.  *
  307.  * Return Value:
  308.  *
  309.  * WORD             - size of the color palette of the DIB
  310.  *
  311.  * Description:
  312.  *
  313.  * This function gets the size required to store the DIB's palette by
  314.  * multiplying the number of colors by the size of an RGBQUAD (for a
  315.  * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an other-
  316.  * style DIB).
  317.  *
  318.  ************************************************************************/
  319. WORD WINAPI PaletteSize(LPSTR lpbi)
  320. {
  321.    /* calculate the size required by the palette */
  322.    if (IS_WIN30_DIB (lpbi))
  323.   return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
  324.    else
  325.   return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
  326. }
  327. /*************************************************************************
  328.  *
  329.  * DIBNumColors()
  330.  *
  331.  * Parameter:
  332.  *
  333.  * LPSTR lpbi       - pointer to packed-DIB memory block
  334.  *
  335.  * Return Value:
  336.  *
  337.  * WORD             - number of colors in the color table
  338.  *
  339.  * Description:
  340.  *
  341.  * This function calculates the number of colors in the DIB's color table
  342.  * by finding the bits per pixel for the DIB (whether Win3.0 or other-style
  343.  * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
  344.  * if 24, no colors in color table.
  345.  *
  346.  ************************************************************************/
  347. WORD WINAPI DIBNumColors(LPSTR lpbi)
  348. {
  349. WORD wBitCount;  // DIB bit count
  350. /*  If this is a Windows-style DIB, the number of colors in the
  351.  *  color table can be less than the number of bits per pixel
  352.  *  allows for (i.e. lpbi->biClrUsed can be set to some value).
  353.  *  If this is the case, return the appropriate value.
  354.  */
  355. if (IS_WIN30_DIB(lpbi))
  356. {
  357. DWORD dwClrUsed;
  358. dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
  359. if (dwClrUsed != 0)
  360. return (WORD)dwClrUsed;
  361. }
  362. /*  Calculate the number of colors in the color table based on
  363.  *  the number of bits per pixel for the DIB.
  364.  */
  365. if (IS_WIN30_DIB(lpbi))
  366. wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
  367. else
  368. wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
  369. /* return number of colors based on bits per pixel */
  370. switch (wBitCount)
  371. {
  372. case 1:
  373. return 2;
  374. case 4:
  375. return 16;
  376. case 8:
  377. return 256;
  378. default:
  379. return 0;
  380. }
  381. }
  382. //////////////////////////////////////////////////////////////////////////
  383. //// Clipboard support
  384. //---------------------------------------------------------------------
  385. //
  386. // Function:   CopyHandle (from SDK DibView sample clipbrd.c)
  387. //
  388. // Purpose:    Makes a copy of the given global memory block.  Returns
  389. //             a handle to the new memory block (NULL on error).
  390. //
  391. //             Routine stolen verbatim out of ShowDIB.
  392. //
  393. // Parms:      h == Handle to global memory to duplicate.
  394. //
  395. // Returns:    Handle to new global memory block.
  396. //
  397. //---------------------------------------------------------------------
  398. HGLOBAL WINAPI CopyHandle (HGLOBAL h)
  399. {
  400. if (h == NULL)
  401. return NULL;
  402. DWORD dwLen = ::GlobalSize((HGLOBAL) h);
  403. HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen);
  404. if (hCopy != NULL)
  405. {
  406. void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
  407. void* lp     = ::GlobalLock((HGLOBAL) h);
  408. memcpy(lpCopy, lp, dwLen);
  409. ::GlobalUnlock(hCopy);
  410. ::GlobalUnlock(h);
  411. }
  412. return hCopy;
  413. }