DIBUTIL.CPP 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  1. //**********************************************************************
  2. //
  3. // dibutil.c
  4. //
  5. // Source file for Device-Independent Bitmap (DIB) API. Provides
  6. // the following functions:
  7. //
  8. // CreateDIB() - Creates new DIB
  9. // FindDIBBits() - Sets pointer to the DIB bits
  10. // DIBWidth() - Gets the width of the DIB
  11. // DIBHeight() - Gets the height of the DIB
  12. // PaletteSize() - Calculates the buffer size required by a palette
  13. // DIBNumColors() - Calculates number of colors in the DIB's color table
  14. // CreateDIBPalette() - Creates a palette from a DIB
  15. // DIBToBitmap() - Creates a bitmap from a DIB
  16. // BitmapToDIB() - Creates a DIB from a bitmap
  17. // PalEntriesOnDevice()- Gets the number of palette entries of a device
  18. // GetSystemPalette() - Returns a handle to the current system palette
  19. // AllocRoomForDIB() - Allocates memory for a DIB
  20. // ChangeDIBFormat() - Changes a DIB's BPP and/or compression format
  21. // ChangeBitmapFormat()- Changes a bitmap to a DIB with specified BPP and
  22. // compression format
  23. //
  24. // Written by Microsoft Product Support Services, Developer Support.
  25. // Copyright 1991-1998 Microsoft Corporation. All rights reserved.
  26. //**********************************************************************
  27. #define STRICT // enable strict type checking
  28. #include "stdafx.h"
  29. #include <assert.h>
  30. #include "dibapi.h"
  31. #include "dibutil.h"
  32. #include <stdio.h>
  33. /*************************************************************************
  34. *
  35. * CreateDIB()
  36. *
  37. * Parameters:
  38. *
  39. * DWORD dwWidth - Width for new bitmap, in pixels
  40. * DWORD dwHeight - Height for new bitmap
  41. * WORD wBitCount - Bit Count for new DIB (1, 4, 8, or 24)
  42. *
  43. * Return Value:
  44. *
  45. * HDIB - Handle to new DIB
  46. *
  47. * Description:
  48. *
  49. * This function allocates memory for and initializes a new DIB by
  50. * filling in the BITMAPINFOHEADER, allocating memory for the color
  51. * table, and allocating memory for the bitmap bits. As with all
  52. * HDIBs, the header, colortable and bits are all in one contiguous
  53. * memory block. This function is similar to the CreateBitmap()
  54. * Windows API.
  55. *
  56. * The colortable and bitmap bits are left uninitialized (zeroed) in the
  57. * returned HDIB.
  58. *
  59. *
  60. ************************************************************************/
  61. HDIB CreateDIB(DWORD dwWidth, DWORD dwHeight, WORD wBitCount)
  62. {
  63. BITMAPINFOHEADER bi; // bitmap header
  64. LPBITMAPINFOHEADER lpbi; // pointer to BITMAPINFOHEADER
  65. DWORD dwLen; // size of memory block
  66. HDIB hDIB;
  67. DWORD dwBytesPerLine; // Number of bytes per scanline
  68. // Make sure bits per pixel is valid
  69. if (wBitCount <= 1)
  70. wBitCount = 1;
  71. else if (wBitCount <= 4)
  72. wBitCount = 4;
  73. else if (wBitCount <= 8)
  74. wBitCount = 8;
  75. else if (wBitCount <= 24)
  76. wBitCount = 24;
  77. else
  78. wBitCount = 4; // set default value to 4 if parameter is bogus
  79. // initialize BITMAPINFOHEADER
  80. bi.biSize = sizeof(BITMAPINFOHEADER);
  81. bi.biWidth = dwWidth; // fill in width from parameter
  82. bi.biHeight = dwHeight; // fill in height from parameter
  83. bi.biPlanes = 1; // must be 1
  84. bi.biBitCount = wBitCount; // from parameter
  85. bi.biCompression = BI_RGB;
  86. bi.biSizeImage = 0; // 0's here mean "default"
  87. bi.biXPelsPerMeter = 0;
  88. bi.biYPelsPerMeter = 0;
  89. bi.biClrUsed = 0;
  90. bi.biClrImportant = 0;
  91. // calculate size of memory block required to store the DIB. This
  92. // block should be big enough to hold the BITMAPINFOHEADER, the color
  93. // table, and the bits
  94. dwBytesPerLine = WIDTHBYTES(wBitCount * dwWidth);
  95. dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + (dwBytesPerLine * dwHeight);
  96. // alloc memory block to store our bitmap
  97. hDIB = GlobalAlloc(GHND, dwLen);
  98. // major bummer if we couldn't get memory block
  99. if (!hDIB)
  100. return NULL;
  101. // lock memory and get pointer to it
  102. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  103. // use our bitmap info structure to fill in first part of
  104. // our DIB with the BITMAPINFOHEADER
  105. *lpbi = bi;
  106. // Since we don't know what the colortable and bits should contain,
  107. // just leave these blank. Unlock the DIB and return the HDIB.
  108. GlobalUnlock(hDIB);
  109. //return handle to the DIB
  110. return hDIB;
  111. }
  112. /*************************************************************************
  113. *
  114. * FindDIBBits()
  115. *
  116. * Parameter:
  117. *
  118. * LPSTR lpDIB - pointer to packed-DIB memory block
  119. *
  120. * Return Value:
  121. *
  122. * LPSTR - pointer to the DIB bits
  123. *
  124. * Description:
  125. *
  126. * This function calculates the address of the DIB's bits and returns a
  127. * pointer to the DIB bits.
  128. *
  129. ************************************************************************/
  130. LPSTR FindDIBBits(LPSTR lpDIB)
  131. {
  132. return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));
  133. }
  134. /*************************************************************************
  135. *
  136. * DIBWidth()
  137. *
  138. * Parameter:
  139. *
  140. * LPSTR lpDIB - pointer to packed-DIB memory block
  141. *
  142. * Return Value:
  143. *
  144. * DWORD - width of the DIB
  145. *
  146. * Description:
  147. *
  148. * This function gets the width of the DIB from the BITMAPINFOHEADER
  149. * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  150. * width field if it is an OS/2-style DIB.
  151. *
  152. ************************************************************************/
  153. DWORD DIBWidth(LPSTR lpDIB)
  154. {
  155. LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
  156. LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB
  157. // point to the header (whether Win 3.0 and OS/2)
  158. lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  159. lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  160. // return the DIB width if it is a Win 3.0 DIB
  161. if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))
  162. return lpbmi->biWidth;
  163. else // it is an OS/2 DIB, so return its width
  164. return (DWORD)lpbmc->bcWidth;
  165. }
  166. /*************************************************************************
  167. *
  168. * DIBHeight()
  169. *
  170. * Parameter:
  171. *
  172. * LPSTR lpDIB - pointer to packed-DIB memory block
  173. *
  174. * Return Value:
  175. *
  176. * DWORD - height of the DIB
  177. *
  178. * Description:
  179. *
  180. * This function gets the height of the DIB from the BITMAPINFOHEADER
  181. * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  182. * height field if it is an OS/2-style DIB.
  183. *
  184. ************************************************************************/
  185. DWORD DIBHeight(LPSTR lpDIB)
  186. {
  187. LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
  188. LPBITMAPCOREHEADER lpbmc; // pointer to an OS/2-style DIB
  189. // point to the header (whether OS/2 or Win 3.0
  190. lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  191. lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  192. // return the DIB height if it is a Win 3.0 DIB
  193. if (lpbmi->biSize == sizeof(BITMAPINFOHEADER))
  194. return lpbmi->biHeight;
  195. else // it is an OS/2 DIB, so return its height
  196. return (DWORD)lpbmc->bcHeight;
  197. }
  198. /*************************************************************************
  199. *
  200. * PaletteSize()
  201. *
  202. * Parameter:
  203. *
  204. * LPSTR lpDIB - pointer to packed-DIB memory block
  205. *
  206. * Return Value:
  207. *
  208. * WORD - size of the color palette of the DIB
  209. *
  210. * Description:
  211. *
  212. * This function gets the size required to store the DIB's palette by
  213. * multiplying the number of colors by the size of an RGBQUAD (for a
  214. * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an OS/2-
  215. * style DIB).
  216. *
  217. ************************************************************************/
  218. WORD PaletteSize(LPSTR lpDIB)
  219. {
  220. // calculate the size required by the palette
  221. if (IS_WIN30_DIB (lpDIB))
  222. return (DIBNumColors(lpDIB) * sizeof(RGBQUAD));
  223. else
  224. return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
  225. }
  226. /*************************************************************************
  227. *
  228. * DIBNumColors()
  229. *
  230. * Parameter:
  231. *
  232. * LPSTR lpDIB - pointer to packed-DIB memory block
  233. *
  234. * Return Value:
  235. *
  236. * WORD - number of colors in the color table
  237. *
  238. * Description:
  239. *
  240. * This function calculates the number of colors in the DIB's color table
  241. * by finding the bits per pixel for the DIB (whether Win3.0 or OS/2-style
  242. * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
  243. * if 24, no colors in color table.
  244. *
  245. ************************************************************************/
  246. WORD DIBNumColors(LPSTR lpDIB)
  247. {
  248. WORD wBitCount; // DIB bit count
  249. // If this is a Windows-style DIB, the number of colors in the
  250. // color table can be less than the number of bits per pixel
  251. // allows for (i.e. lpbi->biClrUsed can be set to some value).
  252. // If this is the case, return the appropriate value.
  253. if (IS_WIN30_DIB(lpDIB))
  254. {
  255. DWORD dwClrUsed;
  256. dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed;
  257. if (dwClrUsed)
  258. return (WORD)dwClrUsed;
  259. }
  260. // Calculate the number of colors in the color table based on
  261. // the number of bits per pixel for the DIB.
  262. if (IS_WIN30_DIB(lpDIB))
  263. wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
  264. else
  265. wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
  266. // return number of colors based on bits per pixel
  267. switch (wBitCount)
  268. {
  269. case 1:
  270. return 2;
  271. case 4:
  272. return 16;
  273. case 8:
  274. return 256;
  275. default:
  276. return 0;
  277. }
  278. }
  279. /*************************************************************************
  280. *
  281. * CreateDIBPalette()
  282. *
  283. * Parameter:
  284. *
  285. * HDIB hDIB - specifies the DIB
  286. *
  287. * Return Value:
  288. *
  289. * HPALETTE - specifies the palette
  290. *
  291. * Description:
  292. *
  293. * This function creates a palette from a DIB by allocating memory for the
  294. * logical palette, reading and storing the colors from the DIB's color table
  295. * into the logical palette, creating a palette from this logical palette,
  296. * and then returning the palette's handle. This allows the DIB to be
  297. * displayed using the best possible colors (important for DIBs with 256 or
  298. * more colors).
  299. *
  300. ************************************************************************/
  301. HPALETTE CreateDIBPalette(HDIB hDIB)
  302. {
  303. LPLOGPALETTE lpPal; // pointer to a logical palette
  304. HANDLE hLogPal; // handle to a logical palette
  305. HPALETTE hPal = NULL; // handle to a palette
  306. int i, wNumColors; // loop index, number of colors in color table
  307. LPSTR lpbi; // pointer to packed-DIB
  308. LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0)
  309. LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (OS/2)
  310. BOOL bWinStyleDIB; // Win3.0 DIB?
  311. // if handle to DIB is invalid, return NULL
  312. if (!hDIB)
  313. return NULL;
  314. // lock DIB memory block and get a pointer to it
  315. lpbi = (LPSTR)GlobalLock(hDIB);
  316. // get pointer to BITMAPINFO (Win 3.0)
  317. lpbmi = (LPBITMAPINFO)lpbi;
  318. // get pointer to BITMAPCOREINFO (OS/2 1.x)
  319. lpbmc = (LPBITMAPCOREINFO)lpbi;
  320. // get the number of colors in the DIB
  321. wNumColors = DIBNumColors(lpbi);
  322. // is this a Win 3.0 DIB?
  323. bWinStyleDIB = IS_WIN30_DIB(lpbi);
  324. if (wNumColors)
  325. {
  326. // allocate memory block for logical palette
  327. hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) +
  328. sizeof(PALETTEENTRY) * wNumColors);
  329. // if not enough memory, clean up and return NULL
  330. if (!hLogPal)
  331. {
  332. GlobalUnlock(hDIB);
  333. return NULL;
  334. }
  335. // lock memory block and get pointer to it
  336. lpPal = (LPLOGPALETTE)GlobalLock(hLogPal);
  337. // set version and number of palette entries
  338. lpPal->palVersion = PALVERSION;
  339. lpPal->palNumEntries = wNumColors;
  340. // store RGB triples (if Win 3.0 DIB) or RGB quads (if OS/2 DIB)
  341. // into palette
  342. for (i = 0; i < wNumColors; i++)
  343. {
  344. if (bWinStyleDIB)
  345. {
  346. lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
  347. lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
  348. lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
  349. lpPal->palPalEntry[i].peFlags = 0;
  350. }
  351. else
  352. {
  353. lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
  354. lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
  355. lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
  356. lpPal->palPalEntry[i].peFlags = 0;
  357. }
  358. }
  359. // create the palette and get handle to it
  360. hPal = CreatePalette(lpPal);
  361. // if error getting handle to palette, clean up and return NULL
  362. if (!hPal)
  363. {
  364. GlobalUnlock(hLogPal);
  365. GlobalFree(hLogPal);
  366. return NULL;
  367. }
  368. }
  369. // clean up
  370. GlobalUnlock(hLogPal);
  371. GlobalFree(hLogPal);
  372. GlobalUnlock(hDIB);
  373. // return handle to DIB's palette
  374. return hPal;
  375. }
  376. /*************************************************************************
  377. *
  378. * DIBToBitmap()
  379. *
  380. * Parameters:
  381. *
  382. * HDIB hDIB - specifies the DIB to convert
  383. *
  384. * HPALETTE hPal - specifies the palette to use with the bitmap
  385. *
  386. * Return Value:
  387. *
  388. * HBITMAP - identifies the device-dependent bitmap
  389. *
  390. * Description:
  391. *
  392. * This function creates a bitmap from a DIB using the specified palette.
  393. * If no palette is specified, default is used.
  394. *
  395. * NOTE:
  396. *
  397. * The bitmap returned from this funciton is always a bitmap compatible
  398. * with the screen (e.g. same bits/pixel and color planes) rather than
  399. * a bitmap with the same attributes as the DIB. This behavior is by
  400. * design, and occurs because this function calls CreateDIBitmap to
  401. * do its work, and CreateDIBitmap always creates a bitmap compatible
  402. * with the hDC parameter passed in (because it in turn calls
  403. * CreateCompatibleBitmap).
  404. *
  405. * So for instance, if your DIB is a monochrome DIB and you call this
  406. * function, you will not get back a monochrome HBITMAP -- you will
  407. * get an HBITMAP compatible with the screen DC, but with only 2
  408. * colors used in the bitmap.
  409. *
  410. * If your application requires a monochrome HBITMAP returned for a
  411. * monochrome DIB, use the function SetDIBits().
  412. *
  413. * Also, the DIBpassed in to the function is not destroyed on exit. This
  414. * must be done later, once it is no longer needed.
  415. *
  416. ************************************************************************/
  417. HBITMAP DIBToBitmap(HDIB hDIB, HPALETTE hPal)
  418. {
  419. LPSTR lpDIBHdr, lpDIBBits; // pointer to DIB header, pointer to DIB bits
  420. HBITMAP hBitmap; // handle to device-dependent bitmap
  421. HDC hDC; // handle to DC
  422. HPALETTE hOldPal = NULL; // handle to a palette
  423. // if invalid handle, return NULL
  424. if (!hDIB)
  425. return NULL;
  426. // lock memory block and get a pointer to it
  427. lpDIBHdr = (LPSTR)GlobalLock(hDIB);
  428. // get a pointer to the DIB bits
  429. lpDIBBits = FindDIBBits(lpDIBHdr);
  430. // get a DC
  431. hDC = GetDC(NULL);
  432. if (!hDC)
  433. {
  434. // clean up and return NULL
  435. GlobalUnlock(hDIB);
  436. return NULL;
  437. }
  438. // select and realize palette
  439. if (hPal)
  440. hOldPal = SelectPalette(hDC, hPal, FALSE);
  441. RealizePalette(hDC);
  442. // create bitmap from DIB info. and bits
  443. hBitmap = CreateDIBitmap(hDC, (LPBITMAPINFOHEADER)lpDIBHdr, CBM_INIT,
  444. lpDIBBits, (LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS);
  445. // restore previous palette
  446. if (hOldPal)
  447. SelectPalette(hDC, hOldPal, FALSE);
  448. // clean up
  449. ReleaseDC(NULL, hDC);
  450. GlobalUnlock(hDIB);
  451. // return handle to the bitmap
  452. return hBitmap;
  453. }
  454. /*************************************************************************
  455. *
  456. * BitmapToDIB()
  457. *
  458. * Parameters:
  459. *
  460. * HBITMAP hBitmap - specifies the bitmap to convert
  461. *
  462. * HPALETTE hPal - specifies the palette to use with the bitmap
  463. *
  464. * Return Value:
  465. *
  466. * HDIB - identifies the device-dependent bitmap
  467. *
  468. * Description:
  469. *
  470. * This function creates a DIB from a bitmap using the specified palette.
  471. *
  472. ************************************************************************/
  473. HDIB BitmapToDIB(HBITMAP hBitmap, HPALETTE hPal)
  474. {
  475. BITMAP bm; // bitmap structure
  476. BITMAPINFOHEADER bi; // bitmap header
  477. LPBITMAPINFOHEADER lpbi; // pointer to BITMAPINFOHEADER
  478. DWORD dwLen; // size of memory block
  479. HANDLE hDIB, h; // handle to DIB, temp handle
  480. HDC hDC; // handle to DC
  481. WORD biBits; // bits per pixel
  482. // check if bitmap handle is valid
  483. if (!hBitmap)
  484. return NULL;
  485. // fill in BITMAP structure, return NULL if it didn't work
  486. if (!GetObject(hBitmap, sizeof(bm), (LPSTR)&bm))
  487. return NULL;
  488. // if no palette is specified, use default palette
  489. if (hPal == NULL)
  490. hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  491. // calculate bits per pixel
  492. biBits = bm.bmPlanes * bm.bmBitsPixel;
  493. // make sure bits per pixel is valid
  494. if (biBits <= 1)
  495. biBits = 1;
  496. else if (biBits <= 4)
  497. biBits = 4;
  498. else if (biBits <= 8)
  499. biBits = 8;
  500. else // if greater than 8-bit, force to 24-bit
  501. biBits = 24;
  502. // initialize BITMAPINFOHEADER
  503. bi.biSize = sizeof(BITMAPINFOHEADER);
  504. bi.biWidth = bm.bmWidth;
  505. bi.biHeight = bm.bmHeight;
  506. bi.biPlanes = 1;
  507. bi.biBitCount = biBits;
  508. bi.biCompression = BI_RGB;
  509. bi.biSizeImage = 0;
  510. bi.biXPelsPerMeter = 0;
  511. bi.biYPelsPerMeter = 0;
  512. bi.biClrUsed = 0;
  513. bi.biClrImportant = 0;
  514. // calculate size of memory block required to store BITMAPINFO
  515. dwLen = bi.biSize + PaletteSize((LPSTR)&bi);
  516. // get a DC
  517. hDC = GetDC(NULL);
  518. // select and realize our palette
  519. hPal = SelectPalette(hDC, hPal, FALSE);
  520. RealizePalette(hDC);
  521. // alloc memory block to store our bitmap
  522. hDIB = GlobalAlloc(GHND, dwLen);
  523. // if we couldn't get memory block
  524. if (!hDIB)
  525. {
  526. // clean up and return NULL
  527. SelectPalette(hDC, hPal, TRUE);
  528. RealizePalette(hDC);
  529. ReleaseDC(NULL, hDC);
  530. return NULL;
  531. }
  532. // lock memory and get pointer to it
  533. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  534. /// use our bitmap info. to fill BITMAPINFOHEADER
  535. *lpbi = bi;
  536. // call GetDIBits with a NULL lpBits param, so it will calculate the
  537. // biSizeImage field for us
  538. GetDIBits(hDC, hBitmap, 0, (UINT)bi.biHeight, NULL, (LPBITMAPINFO)lpbi,
  539. DIB_RGB_COLORS);
  540. // get the info. returned by GetDIBits and unlock memory block
  541. bi = *lpbi;
  542. GlobalUnlock(hDIB);
  543. // if the driver did not fill in the biSizeImage field, make one up
  544. if (bi.biSizeImage == 0)
  545. bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
  546. // realloc the buffer big enough to hold all the bits
  547. dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage;
  548. if (h = GlobalReAlloc(hDIB, dwLen, 0))
  549. hDIB = h;
  550. else
  551. {
  552. // clean up and return NULL
  553. GlobalFree(hDIB);
  554. hDIB = NULL;
  555. SelectPalette(hDC, hPal, TRUE);
  556. RealizePalette(hDC);
  557. ReleaseDC(NULL, hDC);
  558. return NULL;
  559. }
  560. // lock memory block and get pointer to it */
  561. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  562. // call GetDIBits with a NON-NULL lpBits param, and actualy get the
  563. // bits this time
  564. if (GetDIBits(hDC, hBitmap, 0, (UINT)bi.biHeight, (LPSTR)lpbi +
  565. (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,
  566. DIB_RGB_COLORS) == 0)
  567. {
  568. // clean up and return NULL
  569. GlobalUnlock(hDIB);
  570. hDIB = NULL;
  571. SelectPalette(hDC, hPal, TRUE);
  572. RealizePalette(hDC);
  573. ReleaseDC(NULL, hDC);
  574. return NULL;
  575. }
  576. bi = *lpbi;
  577. // clean up
  578. GlobalUnlock(hDIB);
  579. SelectPalette(hDC, hPal, TRUE);
  580. RealizePalette(hDC);
  581. ReleaseDC(NULL, hDC);
  582. // return handle to the DIB
  583. return hDIB;
  584. }
  585. /*************************************************************************
  586. *
  587. * PalEntriesOnDevice()
  588. *
  589. * Parameter:
  590. *
  591. * HDC hDC - device context
  592. *
  593. * Return Value:
  594. *
  595. * int - number of palette entries on device
  596. *
  597. * Description:
  598. *
  599. * This function gets the number of palette entries on the specified device
  600. *
  601. ************************************************************************/
  602. int PalEntriesOnDevice(HDC hDC)
  603. {
  604. int nColors; // number of colors
  605. // Find out the number of colors on this device.
  606. nColors = (1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)));
  607. assert(nColors);
  608. return nColors;
  609. }
  610. /*************************************************************************
  611. *
  612. * GetSystemPalette()
  613. *
  614. * Parameters:
  615. *
  616. * None
  617. *
  618. * Return Value:
  619. *
  620. * HPALETTE - handle to a copy of the current system palette
  621. *
  622. * Description:
  623. *
  624. * This function returns a handle to a palette which represents the system
  625. * palette. The system RGB values are copied into our logical palette using
  626. * the GetSystemPaletteEntries function.
  627. *
  628. ************************************************************************/
  629. HPALETTE GetSystemPalette(void)
  630. {
  631. HDC hDC; // handle to a DC
  632. static HPALETTE hPal = NULL; // handle to a palette
  633. HANDLE hLogPal; // handle to a logical palette
  634. LPLOGPALETTE lpLogPal; // pointer to a logical palette
  635. int nColors; // number of colors
  636. // Find out how many palette entries we want.
  637. hDC = GetDC(NULL);
  638. if (!hDC)
  639. return NULL;
  640. nColors = PalEntriesOnDevice(hDC); // Number of palette entries
  641. // Allocate room for the palette and lock it.
  642. hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors *
  643. sizeof(PALETTEENTRY));
  644. // if we didn't get a logical palette, return NULL
  645. if (!hLogPal)
  646. return NULL;
  647. // get a pointer to the logical palette
  648. lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);
  649. // set some important fields
  650. lpLogPal->palVersion = PALVERSION;
  651. lpLogPal->palNumEntries = nColors;
  652. // Copy the current system palette into our logical palette
  653. GetSystemPaletteEntries(hDC, 0, nColors,
  654. (LPPALETTEENTRY)(lpLogPal->palPalEntry));
  655. // Go ahead and create the palette. Once it's created,
  656. // we no longer need the LOGPALETTE, so free it.
  657. hPal = CreatePalette(lpLogPal);
  658. // clean up
  659. GlobalUnlock(hLogPal);
  660. GlobalFree(hLogPal);
  661. ReleaseDC(NULL, hDC);
  662. return hPal;
  663. }
  664. /*************************************************************************
  665. *
  666. * AllocRoomForDIB()
  667. *
  668. * Parameters:
  669. *
  670. * BITMAPINFOHEADER - bitmap info header stucture
  671. *
  672. * HBITMAP - handle to the bitmap
  673. *
  674. * Return Value:
  675. *
  676. * HDIB - handle to memory block
  677. *
  678. * Description:
  679. *
  680. * This routine takes a BITMAPINOHEADER, and returns a handle to global
  681. * memory which can contain a DIB with that header. It also initializes
  682. * the header portion of the global memory. GetDIBits() is used to determine
  683. * the amount of room for the DIB's bits. The total amount of memory
  684. * needed = sizeof(BITMAPINFOHEADER) + size of color table + size of bits.
  685. *
  686. ************************************************************************/
  687. HANDLE AllocRoomForDIB(BITMAPINFOHEADER bi, HBITMAP hBitmap)
  688. {
  689. DWORD dwLen;
  690. HANDLE hDIB;
  691. HDC hDC;
  692. LPBITMAPINFOHEADER lpbi;
  693. HANDLE hTemp;
  694. // Figure out the size needed to hold the BITMAPINFO structure
  695. // (which includes the BITMAPINFOHEADER and the color table).
  696. dwLen = bi.biSize + PaletteSize((LPSTR) &bi);
  697. hDIB = GlobalAlloc(GHND,dwLen);
  698. // Check that DIB handle is valid
  699. if (!hDIB)
  700. return NULL;
  701. // Set up the BITMAPINFOHEADER in the newly allocated global memory,
  702. // then call GetDIBits() with lpBits = NULL to have it fill in the
  703. // biSizeImage field for us.
  704. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  705. *lpbi = bi;
  706. hDC = GetDC(NULL);
  707. GetDIBits(hDC, hBitmap, 0, (UINT) bi.biHeight, NULL, (LPBITMAPINFO)lpbi,
  708. DIB_RGB_COLORS);
  709. ReleaseDC(NULL, hDC);
  710. // If the driver did not fill in the biSizeImage field,
  711. // fill it in -- NOTE: this is a bug in the driver!
  712. if (lpbi->biSizeImage == 0)
  713. lpbi->biSizeImage = WIDTHBYTES((DWORD)lpbi->biWidth *
  714. lpbi->biBitCount) * lpbi->biHeight;
  715. // Get the size of the memory block we need
  716. dwLen = lpbi->biSize + PaletteSize((LPSTR) &bi) + lpbi->biSizeImage;
  717. // Unlock the memory block
  718. GlobalUnlock(hDIB);
  719. // ReAlloc the buffer big enough to hold all the bits
  720. if (hTemp = GlobalReAlloc(hDIB,dwLen,0))
  721. return hTemp;
  722. else
  723. {
  724. // Else free memory block and return failure
  725. GlobalFree(hDIB);
  726. return NULL;
  727. }
  728. }
  729. /*************************************************************************
  730. *
  731. * ChangeDIBFormat()
  732. *
  733. * Parameter:
  734. *
  735. * HDIB - handle to packed-DIB in memory
  736. *
  737. * WORD - desired bits per pixel
  738. *
  739. * DWORD - desired compression format
  740. *
  741. * Return Value:
  742. *
  743. * HDIB - handle to the new DIB if successful, else NULL
  744. *
  745. * Description:
  746. *
  747. * This function will convert the bits per pixel and/or the compression
  748. * format of the specified DIB. Note: If the conversion was unsuccessful,
  749. * we return NULL. The original DIB is left alone. Don't use code like the
  750. * following:
  751. *
  752. * hMyDIB = ChangeDIBFormat(hMyDIB, 8, BI_RLE4);
  753. *
  754. * The conversion will fail, but hMyDIB will now be NULL and the original
  755. * DIB will now hang around in memory. We could have returned the old
  756. * DIB, but we wanted to allow the programmer to check whether this
  757. * conversion succeeded or failed.
  758. *
  759. ************************************************************************/
  760. HDIB ChangeDIBFormat(HDIB hDIB, WORD wBitCount, DWORD dwCompression)
  761. {
  762. HDC hDC; // Handle to DC
  763. HBITMAP hBitmap; // Handle to bitmap
  764. BITMAP Bitmap; // BITMAP data structure
  765. BITMAPINFOHEADER bi; // Bitmap info header
  766. LPBITMAPINFOHEADER lpbi; // Pointer to bitmap info
  767. HDIB hNewDIB = NULL; // Handle to new DIB
  768. HPALETTE hPal, hOldPal; // Handle to palette, prev pal
  769. WORD DIBBPP, NewBPP; // DIB bits per pixel, new bpp
  770. DWORD DIBComp, NewComp;// DIB compression, new compression
  771. // Check for a valid DIB handle
  772. if (!hDIB)
  773. return NULL;
  774. // Get the old DIB's bits per pixel and compression format
  775. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  776. DIBBPP = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
  777. DIBComp = ((LPBITMAPINFOHEADER)lpbi)->biCompression;
  778. GlobalUnlock(hDIB);
  779. // Validate wBitCount and dwCompression
  780. // They must match correctly (i.e., BI_RLE4 and 4 BPP or
  781. // BI_RLE8 and 8BPP, etc.) or we return failure
  782. if (wBitCount == 0)
  783. {
  784. NewBPP = DIBBPP;
  785. if ((dwCompression == BI_RLE4 && NewBPP == 4) ||
  786. (dwCompression == BI_RLE8 && NewBPP == 8) ||
  787. (dwCompression == BI_RGB))
  788. NewComp = dwCompression;
  789. else
  790. return NULL;
  791. }
  792. else if (wBitCount == 1 && dwCompression == BI_RGB)
  793. {
  794. NewBPP = wBitCount;
  795. NewComp = BI_RGB;
  796. }
  797. else if (wBitCount == 4)
  798. {
  799. NewBPP = wBitCount;
  800. if (dwCompression == BI_RGB || dwCompression == BI_RLE4)
  801. NewComp = dwCompression;
  802. else
  803. return NULL;
  804. }
  805. else if (wBitCount == 8)
  806. {
  807. NewBPP = wBitCount;
  808. if (dwCompression == BI_RGB || dwCompression == BI_RLE8)
  809. NewComp = dwCompression;
  810. else
  811. return NULL;
  812. }
  813. else if (wBitCount == 24 && dwCompression == BI_RGB)
  814. {
  815. NewBPP = wBitCount;
  816. NewComp = BI_RGB;
  817. }
  818. else
  819. return NULL;
  820. // Save the old DIB's palette
  821. hPal = CreateDIBPalette(hDIB);
  822. if (!hPal)
  823. return NULL;
  824. // Convert old DIB to a bitmap
  825. hBitmap = DIBToBitmap(hDIB, hPal);
  826. if (!hBitmap)
  827. {
  828. DeleteObject(hPal);
  829. return NULL;
  830. }
  831. // Get info about the bitmap
  832. GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
  833. // Fill in the BITMAPINFOHEADER appropriately
  834. bi.biSize = sizeof(BITMAPINFOHEADER);
  835. bi.biWidth = Bitmap.bmWidth;
  836. bi.biHeight = Bitmap.bmHeight;
  837. bi.biPlanes = 1;
  838. bi.biBitCount = NewBPP;
  839. bi.biCompression = NewComp;
  840. bi.biSizeImage = 0;
  841. bi.biXPelsPerMeter = 0;
  842. bi.biYPelsPerMeter = 0;
  843. bi.biClrUsed = 0;
  844. bi.biClrImportant = 0;
  845. // Go allocate room for the new DIB
  846. hNewDIB = AllocRoomForDIB(bi, hBitmap);
  847. if (!hNewDIB)
  848. return NULL;
  849. // Get a pointer to the new DIB
  850. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);
  851. // Get a DC and select/realize our palette in it
  852. hDC = GetDC(NULL);
  853. hOldPal = SelectPalette(hDC, hPal, FALSE);
  854. RealizePalette(hDC);
  855. // Call GetDIBits and get the new DIB bits
  856. if (!GetDIBits(hDC, hBitmap, 0, (UINT) lpbi->biHeight,
  857. (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),
  858. (LPBITMAPINFO)lpbi, DIB_RGB_COLORS))
  859. {
  860. GlobalUnlock(hNewDIB);
  861. GlobalFree(hNewDIB);
  862. hNewDIB = NULL;
  863. }
  864. // Clean up and return
  865. SelectPalette(hDC, hOldPal, TRUE);
  866. RealizePalette(hDC);
  867. ReleaseDC(NULL, hDC);
  868. // Unlock the new DIB's memory block
  869. if (hNewDIB)
  870. GlobalUnlock(hNewDIB);
  871. DeleteObject(hBitmap);
  872. DeleteObject(hPal);
  873. return hNewDIB;
  874. }
  875. /*************************************************************************
  876. *
  877. * ChangeBitmapFormat()
  878. *
  879. * Parameter:
  880. *
  881. * HBITMAP - handle to a bitmap
  882. *
  883. * WORD - desired bits per pixel
  884. *
  885. * DWORD - desired compression format
  886. *
  887. * HPALETTE - handle to palette
  888. *
  889. * Return Value:
  890. *
  891. * HDIB - handle to the new DIB if successful, else NULL
  892. *
  893. * Description:
  894. *
  895. * This function will convert a bitmap to the specified bits per pixel
  896. * and compression format. The bitmap and it's palette will remain
  897. * after calling this function.
  898. *
  899. ************************************************************************/
  900. HDIB ChangeBitmapFormat(HBITMAP hBitmap, WORD wBitCount, DWORD dwCompression,
  901. HPALETTE hPal)
  902. {
  903. HDC hDC; // Screen DC
  904. HDIB hNewDIB=NULL; // Handle to new DIB
  905. BITMAP Bitmap; // BITMAP data structure
  906. BITMAPINFOHEADER bi; // Bitmap info. header
  907. LPBITMAPINFOHEADER lpbi; // Pointer to bitmap header
  908. HPALETTE hOldPal=NULL; // Handle to palette
  909. WORD NewBPP; // New bits per pixel
  910. DWORD NewComp; // New compression format
  911. // Check for a valid bitmap handle
  912. if (!hBitmap)
  913. return NULL;
  914. // Validate wBitCount and dwCompression
  915. // They must match correctly (i.e., BI_RLE4 and 4 BPP or
  916. // BI_RLE8 and 8BPP, etc.) or we return failure
  917. if (wBitCount == 0)
  918. {
  919. NewComp = dwCompression;
  920. if (NewComp == BI_RLE4)
  921. NewBPP = 4;
  922. else if (NewComp == BI_RLE8)
  923. NewBPP = 8;
  924. else // Not enough info */
  925. return NULL;
  926. }
  927. else if (wBitCount == 1 && dwCompression == BI_RGB)
  928. {
  929. NewBPP = wBitCount;
  930. NewComp = BI_RGB;
  931. }
  932. else if (wBitCount == 4)
  933. {
  934. NewBPP = wBitCount;
  935. if (dwCompression == BI_RGB || dwCompression == BI_RLE4)
  936. NewComp = dwCompression;
  937. else
  938. return NULL;
  939. }
  940. else if (wBitCount == 8)
  941. {
  942. NewBPP = wBitCount;
  943. if (dwCompression == BI_RGB || dwCompression == BI_RLE8)
  944. NewComp = dwCompression;
  945. else
  946. return NULL;
  947. }
  948. else if (wBitCount == 24 && dwCompression == BI_RGB)
  949. {
  950. NewBPP = wBitCount;
  951. NewComp = BI_RGB;
  952. }
  953. else
  954. return NULL;
  955. // Get info about the bitmap
  956. GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
  957. // Fill in the BITMAPINFOHEADER appropriately
  958. bi.biSize = sizeof(BITMAPINFOHEADER);
  959. bi.biWidth = Bitmap.bmWidth;
  960. bi.biHeight = Bitmap.bmHeight;
  961. bi.biPlanes = 1;
  962. bi.biBitCount = NewBPP;
  963. bi.biCompression = NewComp;
  964. bi.biSizeImage = 0;
  965. bi.biXPelsPerMeter = 0;
  966. bi.biYPelsPerMeter = 0;
  967. bi.biClrUsed = 0;
  968. bi.biClrImportant = 0;
  969. // Go allocate room for the new DIB
  970. hNewDIB = AllocRoomForDIB(bi, hBitmap);
  971. if (!hNewDIB)
  972. return NULL;
  973. // Get a pointer to the new DIB
  974. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);
  975. // If we have a palette, get a DC and select/realize it
  976. if (hPal)
  977. {
  978. hDC = GetDC(NULL);
  979. hOldPal = SelectPalette(hDC, hPal, FALSE);
  980. RealizePalette(hDC);
  981. }
  982. // Call GetDIBits and get the new DIB bits
  983. if (!GetDIBits(hDC, hBitmap, 0, (UINT) lpbi->biHeight, (LPSTR)lpbi +
  984. (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,
  985. DIB_RGB_COLORS))
  986. {
  987. GlobalUnlock(hNewDIB);
  988. GlobalFree(hNewDIB);
  989. hNewDIB = NULL;
  990. }
  991. // Clean up and return
  992. if (hOldPal)
  993. {
  994. SelectPalette(hDC, hOldPal, TRUE);
  995. RealizePalette(hDC);
  996. ReleaseDC(NULL, hDC);
  997. }
  998. // Unlock the new DIB's memory block
  999. if (hNewDIB)
  1000. GlobalUnlock(hNewDIB);
  1001. return hNewDIB;
  1002. }