DIBAPI.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:16k
源码类别:

Windows编程

开发平台:

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. #include <math.h>
  30. #include <direct.h>
  31. /*
  32.  * Dib Header Marker - used in writing DIBs to files
  33.  */
  34. #define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')
  35. /*************************************************************************
  36.   Function:  ReadDIBFile (CFile&)
  37.    Purpose:  Reads in the specified DIB file into a global chunk of
  38.  memory.
  39.    Returns:  A handle to a dib (hDIB) if successful.
  40.  NULL if an error occurs.
  41.   Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything
  42.  from the end of the BITMAPFILEHEADER structure on is
  43.  returned in the global memory handle.
  44. *************************************************************************/
  45. HDIB WINAPI ReadDIBFile(LPCTSTR pszFileName )
  46. {
  47. BITMAPFILEHEADER bmfHeader;
  48. DWORD dwBitsSize;
  49. HDIB hDIB;
  50. LPSTR pDIB;
  51. HANDLE hFile;
  52. DWORD nBytesRead;
  53. /*
  54.  * get length of DIB in bytes for use when reading
  55.  */
  56. hFile =  CreateFile(
  57. pszFileName,    // pointer to name of the file
  58. GENERIC_READ,   // access (read-write) mode
  59. FILE_SHARE_READ,    // share mode
  60. NULL,   // pointer to security descriptor
  61. OPEN_EXISTING,  // how to create
  62. FILE_ATTRIBUTE_NORMAL,  // file attributes
  63. NULL    // handle to file with attributes to copy
  64.    );
  65. dwBitsSize = GetFileSize(hFile,NULL);
  66. /*
  67.  * Go read the DIB file header and check if it's valid.
  68.  */
  69. // attempt an asynchronous read operation
  70. if(! ReadFile(hFile, (LPSTR)&bmfHeader, sizeof(bmfHeader), &nBytesRead,
  71.  NULL))
  72. return NULL;
  73. if (bmfHeader.bfType != DIB_HEADER_MARKER)
  74. return NULL;
  75. /*
  76.  * Allocate memory for DIB
  77.  */
  78. hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
  79. if (hDIB == 0)
  80. {
  81. return NULL;
  82. }
  83. pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  84. /*
  85.  * Go read the bits.
  86.  */
  87. if(!ReadFile(hFile, (LPSTR)pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER), &nBytesRead, NULL))
  88. {
  89. ::GlobalUnlock((HGLOBAL) hDIB);
  90. ::GlobalFree((HGLOBAL) hDIB);
  91. return NULL;
  92. }
  93. ::GlobalUnlock((HGLOBAL) hDIB);
  94. CloseHandle(hFile);
  95. return hDIB;
  96. }
  97. /*************************************************************************
  98.  *
  99.  * PaintDIB()
  100.  *
  101.  * Parameters:
  102.  *
  103.  * HDC hDC          - DC to do output to
  104.  *
  105.  * LPRECT lpDCRect  - rectangle on DC to do output to
  106.  *
  107.  * HDIB hDIB        - handle to global memory with a DIB spec
  108.  *                    in it followed by the DIB bits
  109.  *
  110.  * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
  111.  *
  112.  * CPalette* pPal   - pointer to CPalette containing DIB's palette
  113.  *
  114.  * Return Value:
  115.  *
  116.  * BOOL             - TRUE if DIB was drawn, FALSE otherwise
  117.  *
  118.  * Description:
  119.  *   Painting routine for a DIB.  Calls StretchDIBits() or
  120.  *   SetDIBitsToDevice() to paint the DIB.  The DIB is
  121.  *   output to the specified DC, at the coordinates given
  122.  *   in lpDCRect.  The area of the DIB to be output is
  123.  *   given by lpDIBRect.
  124.  *
  125.  ************************************************************************/
  126. BOOL WINAPI PaintDIB(HDC     hDC,
  127. LPRECT  lpDCRect,
  128. HDIB    hDIB,
  129. LPRECT  lpDIBRect,
  130. HPALETTE hPal)
  131. {
  132. LPSTR    lpDIBHdr;            // Pointer to BITMAPINFOHEADER
  133. LPSTR    lpDIBBits;           // Pointer to DIB bits
  134. BOOL     bSuccess=FALSE;      // Success/fail flag
  135. HPALETTE hOldPal=NULL;        // Previous palette
  136. /* Check for valid DIB handle */
  137. if (hDIB == NULL)
  138. return FALSE;
  139. /* Lock down the DIB, and get a pointer to the beginning of the bit
  140.  *  buffer
  141.  */
  142. lpDIBHdr  = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  143. lpDIBBits = ::FindDIBBits(lpDIBHdr);
  144. // Get the DIB's palette, then select it into DC
  145. // Select as background since we have
  146. // already realized in forground if needed
  147. hOldPal = ::SelectPalette(hDC, hPal, TRUE);
  148. /* Make sure to use the stretching mode best for color pictures */
  149. ::SetStretchBltMode(hDC, COLORONCOLOR);
  150. /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
  151. if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDIBRect)) && (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
  152. {
  153. bSuccess = ::SetDIBitsToDevice(hDC,                    // hDC
  154. lpDCRect->left,             // DestX
  155. lpDCRect->top,              // DestY
  156. RECTWIDTH(lpDCRect),        // nDestWidth
  157. RECTHEIGHT(lpDCRect),       // nDestHeight
  158. //          RECTWIDTH(lpDIBRect),           // wSrcWidth
  159. //          RECTHEIGHT(lpDIBRect),          // wSrcHeight
  160. lpDIBRect->left,            // SrcX
  161. (int)DIBHeight(lpDIBHdr) -
  162. lpDIBRect->top -
  163. RECTHEIGHT(lpDIBRect),   // SrcY
  164. 0,                          // nStartScan
  165. (WORD)DIBHeight(lpDIBHdr),  // nNumScans
  166. lpDIBBits,                  // lpBits
  167. (LPBITMAPINFO)lpDIBHdr,     // lpBitsInfo
  168. DIB_RGB_COLORS);            // wUsage
  169. }
  170. else
  171. {
  172. bSuccess = ::StretchDIBits(hDC,                          // hDC
  173. lpDCRect->left,                 // DestX
  174. lpDCRect->top,                  // DestY
  175. RECTWIDTH(lpDCRect),            // nDestWidth
  176. RECTHEIGHT(lpDCRect),           // nDestHeight
  177. //          RECTWIDTH(lpDIBRect),           // wSrcWidth
  178. //          RECTHEIGHT(lpDIBRect),          // wSrcHeight
  179. lpDIBRect->left,                // SrcX
  180. lpDIBRect->top,                 // SrcY
  181. RECTWIDTH(lpDIBRect),           // wSrcWidth
  182. RECTHEIGHT(lpDIBRect),          // wSrcHeight
  183. lpDIBBits,                      // lpBits
  184. (LPBITMAPINFO)lpDIBHdr,         // lpBitsInfo
  185. DIB_RGB_COLORS,                 // wUsage
  186. SRCCOPY);                       // dwROP
  187. }
  188.    ::GlobalUnlock((HGLOBAL) hDIB);
  189. /* Reselect old palette */
  190. if (hOldPal != NULL)
  191. {
  192. ::SelectPalette(hDC, hOldPal, TRUE);
  193. }
  194.    return bSuccess;
  195. }
  196. /*************************************************************************
  197.  *
  198.  * CreateDIBPalette()
  199.  *
  200.  * Parameter:
  201.  *
  202.  * HDIB hDIB        - specifies the DIB
  203.  *
  204.  * Return Value:
  205.  *
  206.  * HPALETTE         - specifies the palette
  207.  *
  208.  * Description:
  209.  *
  210.  * This function creates a palette from a DIB by allocating memory for the
  211.  * logical palette, reading and storing the colors from the DIB's color table
  212.  * into the logical palette, creating a palette from this logical palette,
  213.  * and then returning the palette's handle. This allows the DIB to be
  214.  * displayed using the best possible colors (important for DIBs with 256 or
  215.  * more colors).
  216.  *
  217.  ************************************************************************/
  218. BOOL WINAPI CreateDIBPalette(HDIB hDIB, HPALETTE* pPal)
  219. {
  220. LPLOGPALETTE lpPal;      // pointer to a logical palette
  221. HANDLE hLogPal;          // handle to a logical palette
  222. HPALETTE hPal = NULL;    // handle to a palette
  223. int i;                   // loop index
  224. WORD wNumColors;         // number of colors in color table
  225. LPSTR lpbi;              // pointer to packed-DIB
  226. LPBITMAPINFO lpbmi;      // pointer to BITMAPINFO structure (Win3.0)
  227. LPBITMAPCOREINFO lpbmc;  // pointer to BITMAPCOREINFO structure (old)
  228. BOOL bWinStyleDIB;       // flag which signifies whether this is a Win3.0 DIB
  229. BOOL bResult = FALSE;
  230. /* if handle to DIB is invalid, return FALSE */
  231. if (hDIB == NULL)
  232.   return FALSE;
  233.    lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  234.    /* get pointer to BITMAPINFO (Win 3.0) */
  235.    lpbmi = (LPBITMAPINFO)lpbi;
  236.    /* get pointer to BITMAPCOREINFO (old 1.x) */
  237.    lpbmc = (LPBITMAPCOREINFO)lpbi;
  238.    /* get the number of colors in the DIB */
  239.    wNumColors = ::DIBNumColors(lpbi);
  240.    if (wNumColors != 0)
  241.    {
  242. /* allocate memory block for logical palette */
  243. hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
  244. + sizeof(PALETTEENTRY)
  245. * wNumColors);
  246. /* if not enough memory, clean up and return NULL */
  247. if (hLogPal == 0)
  248. {
  249. ::GlobalUnlock((HGLOBAL) hDIB);
  250. return FALSE;
  251. }
  252. lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
  253. /* set version and number of palette entries */
  254. lpPal->palVersion = PALVERSION;
  255. lpPal->palNumEntries = (WORD)wNumColors;
  256. /* is this a Win 3.0 DIB? */
  257. bWinStyleDIB = IS_WIN30_DIB(lpbi);
  258. for (i = 0; i < (int)wNumColors; i++)
  259. {
  260. if (bWinStyleDIB)
  261. {
  262. lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
  263. lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
  264. lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
  265. lpPal->palPalEntry[i].peFlags = 0;
  266. }
  267. else
  268. {
  269. lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
  270. lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
  271. lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
  272. lpPal->palPalEntry[i].peFlags = 0;
  273. }
  274. }
  275. /* create the palette and get handle to it */
  276. hPal = (HPALETTE)::CreatePalette((LPLOGPALETTE)lpPal);
  277. ::GlobalUnlock((HGLOBAL) hLogPal);
  278. ::GlobalFree((HGLOBAL) hLogPal);
  279. *pPal = hPal;
  280. }
  281. ::GlobalUnlock((HGLOBAL) hDIB);
  282. return (NULL != pPal);
  283. }
  284. /*************************************************************************
  285.  *
  286.  * FindDIBBits()
  287.  *
  288.  * Parameter:
  289.  *
  290.  * LPSTR lpbi       - pointer to packed-DIB memory block
  291.  *
  292.  * Return Value:
  293.  *
  294.  * LPSTR            - pointer to the DIB bits
  295.  *
  296.  * Description:
  297.  *
  298.  * This function calculates the address of the DIB's bits and returns a
  299.  * pointer to the DIB bits.
  300.  *
  301.  ************************************************************************/
  302. LPSTR WINAPI FindDIBBits(LPSTR lpbi)
  303. {
  304. return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi));
  305. }
  306. /*************************************************************************
  307.  *
  308.  * DIBWidth()
  309.  *
  310.  * Parameter:
  311.  *
  312.  * LPSTR lpbi       - pointer to packed-DIB memory block
  313.  *
  314.  * Return Value:
  315.  *
  316.  * DWORD            - width of the DIB
  317.  *
  318.  * Description:
  319.  *
  320.  * This function gets the width of the DIB from the BITMAPINFOHEADER
  321.  * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  322.  * width field if it is an other-style DIB.
  323.  *
  324.  ************************************************************************/
  325. DWORD WINAPI DIBWidth(LPSTR lpDIB)
  326. {
  327. LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
  328. LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB
  329. /* point to the header (whether Win 3.0 and old) */
  330. lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  331. lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  332. /* return the DIB width if it is a Win 3.0 DIB */
  333. if (IS_WIN30_DIB(lpDIB))
  334. return lpbmi->biWidth;
  335. else  /* it is an other-style DIB, so return its width */
  336. return (DWORD)lpbmc->bcWidth;
  337. }
  338. /*************************************************************************
  339.  *
  340.  * DIBHeight()
  341.  *
  342.  * Parameter:
  343.  *
  344.  * LPSTR lpbi       - pointer to packed-DIB memory block
  345.  *
  346.  * Return Value:
  347.  *
  348.  * DWORD            - height of the DIB
  349.  *
  350.  * Description:
  351.  *
  352.  * This function gets the height of the DIB from the BITMAPINFOHEADER
  353.  * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  354.  * height field if it is an other-style DIB.
  355.  *
  356.  ************************************************************************/
  357. DWORD WINAPI DIBHeight(LPSTR lpDIB)
  358. {
  359. LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
  360. LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB
  361. /* point to the header (whether old or Win 3.0 */
  362. lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  363. lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  364. /* return the DIB height if it is a Win 3.0 DIB */
  365. if (IS_WIN30_DIB(lpDIB))
  366. return lpbmi->biHeight;
  367. else  /* it is an other-style DIB, so return its height */
  368. return (DWORD)lpbmc->bcHeight;
  369. }
  370. /*************************************************************************
  371.  *
  372.  * PaletteSize()
  373.  *
  374.  * Parameter:
  375.  *
  376.  * LPSTR lpbi       - pointer to packed-DIB memory block
  377.  *
  378.  * Return Value:
  379.  *
  380.  * WORD             - size of the color palette of the DIB
  381.  *
  382.  * Description:
  383.  *
  384.  * This function gets the size required to store the DIB's palette by
  385.  * multiplying the number of colors by the size of an RGBQUAD (for a
  386.  * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an other-
  387.  * style DIB).
  388.  *
  389.  ************************************************************************/
  390. WORD WINAPI PaletteSize(LPSTR lpbi)
  391. {
  392.    /* calculate the size required by the palette */
  393.    if (IS_WIN30_DIB (lpbi))
  394.   return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
  395.    else
  396.   return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
  397. }
  398. /*************************************************************************
  399.  *
  400.  * DIBNumColors()
  401.  *
  402.  * Parameter:
  403.  *
  404.  * LPSTR lpbi       - pointer to packed-DIB memory block
  405.  *
  406.  * Return Value:
  407.  *
  408.  * WORD             - number of colors in the color table
  409.  *
  410.  * Description:
  411.  *
  412.  * This function calculates the number of colors in the DIB's color table
  413.  * by finding the bits per pixel for the DIB (whether Win3.0 or other-style
  414.  * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
  415.  * if 24, no colors in color table.
  416.  *
  417.  ************************************************************************/
  418. WORD WINAPI DIBNumColors(LPSTR lpbi)
  419. {
  420. WORD wBitCount;  // DIB bit count
  421. /*  If this is a Windows-style DIB, the number of colors in the
  422.  *  color table can be less than the number of bits per pixel
  423.  *  allows for (i.e. lpbi->biClrUsed can be set to some value).
  424.  *  If this is the case, return the appropriate value.
  425.  */
  426. if (IS_WIN30_DIB(lpbi))
  427. {
  428. DWORD dwClrUsed;
  429. dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
  430. if (dwClrUsed != 0)
  431. return (WORD)dwClrUsed;
  432. }
  433. /*  Calculate the number of colors in the color table based on
  434.  *  the number of bits per pixel for the DIB.
  435.  */
  436. if (IS_WIN30_DIB(lpbi))
  437. wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
  438. else
  439. wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
  440. /* return number of colors based on bits per pixel */
  441. switch (wBitCount)
  442. {
  443. case 1:
  444. return 2;
  445. case 4:
  446. return 16;
  447. case 8:
  448. return 256;
  449. default:
  450. return 0;
  451. }
  452. }
  453. //////////////////////////////////////////////////////////////////////////
  454. //// Clipboard support
  455. //---------------------------------------------------------------------
  456. //
  457. // Function:   CopyHandle (from SDK DibView sample clipbrd.c)
  458. //
  459. // Purpose:    Makes a copy of the given global memory block.  Returns
  460. //             a handle to the new memory block (NULL on error).
  461. //
  462. //             Routine stolen verbatim out of ShowDIB.
  463. //
  464. // Parms:      h == Handle to global memory to duplicate.
  465. //
  466. // Returns:    Handle to new global memory block.
  467. //
  468. //---------------------------------------------------------------------
  469. HGLOBAL WINAPI CopyHandle (HGLOBAL h)
  470. {
  471. if (h == NULL)
  472. return NULL;
  473. DWORD dwLen = ::GlobalSize((HGLOBAL) h);
  474. HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen);
  475. if (hCopy != NULL)
  476. {
  477. void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
  478. void* lp     = ::GlobalLock((HGLOBAL) h);
  479. memcpy(lpCopy, lp, dwLen);
  480. ::GlobalUnlock(hCopy);
  481. ::GlobalUnlock(h);
  482. }
  483. return hCopy;
  484. }