dibapi.cpp 14 KB

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