DIBUTIL.CPP 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  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 (biBits <= 24)
  501. biBits = 24;
  502. else
  503. biBits = 32;
  504. // initialize BITMAPINFOHEADER
  505. bi.biSize = sizeof(BITMAPINFOHEADER);
  506. bi.biWidth = bm.bmWidth;
  507. bi.biHeight = bm.bmHeight;
  508. bi.biPlanes = 1;
  509. bi.biBitCount = biBits;
  510. bi.biCompression = BI_RGB;
  511. bi.biSizeImage = 0;
  512. bi.biXPelsPerMeter = 0;
  513. bi.biYPelsPerMeter = 0;
  514. bi.biClrUsed = 0;
  515. bi.biClrImportant = 0;
  516. // calculate size of memory block required to store BITMAPINFO
  517. dwLen = bi.biSize + PaletteSize((LPSTR)&bi);
  518. // get a DC
  519. hDC = GetDC(NULL);
  520. // select and realize our palette
  521. hPal = SelectPalette(hDC, hPal, FALSE);
  522. RealizePalette(hDC);
  523. // alloc memory block to store our bitmap
  524. hDIB = GlobalAlloc(GHND, dwLen);
  525. // if we couldn't get memory block
  526. if (!hDIB)
  527. {
  528. // clean up and return NULL
  529. SelectPalette(hDC, hPal, TRUE);
  530. RealizePalette(hDC);
  531. ReleaseDC(NULL, hDC);
  532. return NULL;
  533. }
  534. // lock memory and get pointer to it
  535. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  536. /// use our bitmap info. to fill BITMAPINFOHEADER
  537. *lpbi = bi;
  538. // call GetDIBits with a NULL lpBits param, so it will calculate the
  539. // biSizeImage field for us
  540. GetDIBits(hDC, hBitmap, 0, (UINT)bi.biHeight, NULL, (LPBITMAPINFO)lpbi,
  541. DIB_RGB_COLORS);
  542. // get the info. returned by GetDIBits and unlock memory block
  543. bi = *lpbi;
  544. GlobalUnlock(hDIB);
  545. // if the driver did not fill in the biSizeImage field, make one up
  546. if (bi.biSizeImage == 0)
  547. bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
  548. // realloc the buffer big enough to hold all the bits
  549. dwLen = bi.biSize + PaletteSize((LPSTR)&bi) + bi.biSizeImage;
  550. if (h = GlobalReAlloc(hDIB, dwLen, 0))
  551. hDIB = h;
  552. else
  553. {
  554. // clean up and return NULL
  555. GlobalFree(hDIB);
  556. hDIB = NULL;
  557. SelectPalette(hDC, hPal, TRUE);
  558. RealizePalette(hDC);
  559. ReleaseDC(NULL, hDC);
  560. return NULL;
  561. }
  562. // lock memory block and get pointer to it */
  563. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  564. // call GetDIBits with a NON-NULL lpBits param, and actualy get the
  565. // bits this time
  566. if (GetDIBits(hDC, hBitmap, 0, (UINT)bi.biHeight, (LPSTR)lpbi +
  567. (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,
  568. DIB_RGB_COLORS) == 0)
  569. {
  570. // clean up and return NULL
  571. GlobalUnlock(hDIB);
  572. hDIB = NULL;
  573. SelectPalette(hDC, hPal, TRUE);
  574. RealizePalette(hDC);
  575. ReleaseDC(NULL, hDC);
  576. return NULL;
  577. }
  578. bi = *lpbi;
  579. // clean up
  580. GlobalUnlock(hDIB);
  581. SelectPalette(hDC, hPal, TRUE);
  582. RealizePalette(hDC);
  583. ReleaseDC(NULL, hDC);
  584. // return handle to the DIB
  585. return hDIB;
  586. }
  587. /*************************************************************************
  588. *
  589. * PalEntriesOnDevice()
  590. *
  591. * Parameter:
  592. *
  593. * HDC hDC - device context
  594. *
  595. * Return Value:
  596. *
  597. * int - number of palette entries on device
  598. *
  599. * Description:
  600. *
  601. * This function gets the number of palette entries on the specified device
  602. *
  603. ************************************************************************/
  604. int PalEntriesOnDevice(HDC hDC)
  605. {
  606. int nColors; // number of colors
  607. // Find out the number of colors on this device.
  608. nColors = (1 << (GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES)));
  609. assert(nColors);
  610. return nColors;
  611. }
  612. /*************************************************************************
  613. *
  614. * GetSystemPalette()
  615. *
  616. * Parameters:
  617. *
  618. * None
  619. *
  620. * Return Value:
  621. *
  622. * HPALETTE - handle to a copy of the current system palette
  623. *
  624. * Description:
  625. *
  626. * This function returns a handle to a palette which represents the system
  627. * palette. The system RGB values are copied into our logical palette using
  628. * the GetSystemPaletteEntries function.
  629. *
  630. ************************************************************************/
  631. HPALETTE GetSystemPalette(void)
  632. {
  633. HDC hDC; // handle to a DC
  634. static HPALETTE hPal = NULL; // handle to a palette
  635. HANDLE hLogPal; // handle to a logical palette
  636. LPLOGPALETTE lpLogPal; // pointer to a logical palette
  637. int nColors; // number of colors
  638. // Find out how many palette entries we want.
  639. hDC = GetDC(NULL);
  640. if (!hDC)
  641. return NULL;
  642. nColors = PalEntriesOnDevice(hDC); // Number of palette entries
  643. // Allocate room for the palette and lock it.
  644. hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + nColors *
  645. sizeof(PALETTEENTRY));
  646. // if we didn't get a logical palette, return NULL
  647. if (!hLogPal)
  648. return NULL;
  649. // get a pointer to the logical palette
  650. lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);
  651. // set some important fields
  652. lpLogPal->palVersion = PALVERSION;
  653. lpLogPal->palNumEntries = nColors;
  654. // Copy the current system palette into our logical palette
  655. GetSystemPaletteEntries(hDC, 0, nColors,
  656. (LPPALETTEENTRY)(lpLogPal->palPalEntry));
  657. // Go ahead and create the palette. Once it's created,
  658. // we no longer need the LOGPALETTE, so free it.
  659. hPal = CreatePalette(lpLogPal);
  660. // clean up
  661. GlobalUnlock(hLogPal);
  662. GlobalFree(hLogPal);
  663. ReleaseDC(NULL, hDC);
  664. return hPal;
  665. }
  666. /*************************************************************************
  667. *
  668. * AllocRoomForDIB()
  669. *
  670. * Parameters:
  671. *
  672. * BITMAPINFOHEADER - bitmap info header stucture
  673. *
  674. * HBITMAP - handle to the bitmap
  675. *
  676. * Return Value:
  677. *
  678. * HDIB - handle to memory block
  679. *
  680. * Description:
  681. *
  682. * This routine takes a BITMAPINOHEADER, and returns a handle to global
  683. * memory which can contain a DIB with that header. It also initializes
  684. * the header portion of the global memory. GetDIBits() is used to determine
  685. * the amount of room for the DIB's bits. The total amount of memory
  686. * needed = sizeof(BITMAPINFOHEADER) + size of color table + size of bits.
  687. *
  688. ************************************************************************/
  689. HANDLE AllocRoomForDIB(BITMAPINFOHEADER bi, HBITMAP hBitmap)
  690. {
  691. DWORD dwLen;
  692. HANDLE hDIB;
  693. HDC hDC;
  694. LPBITMAPINFOHEADER lpbi;
  695. HANDLE hTemp;
  696. // Figure out the size needed to hold the BITMAPINFO structure
  697. // (which includes the BITMAPINFOHEADER and the color table).
  698. dwLen = bi.biSize + PaletteSize((LPSTR) &bi);
  699. hDIB = GlobalAlloc(GHND,dwLen);
  700. // Check that DIB handle is valid
  701. if (!hDIB)
  702. return NULL;
  703. // Set up the BITMAPINFOHEADER in the newly allocated global memory,
  704. // then call GetDIBits() with lpBits = NULL to have it fill in the
  705. // biSizeImage field for us.
  706. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  707. *lpbi = bi;
  708. hDC = GetDC(NULL);
  709. GetDIBits(hDC, hBitmap, 0, (UINT) bi.biHeight, NULL, (LPBITMAPINFO)lpbi,
  710. DIB_RGB_COLORS);
  711. ReleaseDC(NULL, hDC);
  712. // If the driver did not fill in the biSizeImage field,
  713. // fill it in -- NOTE: this is a bug in the driver!
  714. if (lpbi->biSizeImage == 0)
  715. lpbi->biSizeImage = WIDTHBYTES((DWORD)lpbi->biWidth *
  716. lpbi->biBitCount) * lpbi->biHeight;
  717. // Get the size of the memory block we need
  718. dwLen = lpbi->biSize + PaletteSize((LPSTR) &bi) + lpbi->biSizeImage;
  719. // Unlock the memory block
  720. GlobalUnlock(hDIB);
  721. // ReAlloc the buffer big enough to hold all the bits
  722. if (hTemp = GlobalReAlloc(hDIB,dwLen,0))
  723. return hTemp;
  724. else
  725. {
  726. // Else free memory block and return failure
  727. GlobalFree(hDIB);
  728. return NULL;
  729. }
  730. }
  731. /*************************************************************************
  732. *
  733. * ChangeDIBFormat()
  734. *
  735. * Parameter:
  736. *
  737. * HDIB - handle to packed-DIB in memory
  738. *
  739. * WORD - desired bits per pixel
  740. *
  741. * DWORD - desired compression format
  742. *
  743. * Return Value:
  744. *
  745. * HDIB - handle to the new DIB if successful, else NULL
  746. *
  747. * Description:
  748. *
  749. * This function will convert the bits per pixel and/or the compression
  750. * format of the specified DIB. Note: If the conversion was unsuccessful,
  751. * we return NULL. The original DIB is left alone. Don't use code like the
  752. * following:
  753. *
  754. * hMyDIB = ChangeDIBFormat(hMyDIB, 8, BI_RLE4);
  755. *
  756. * The conversion will fail, but hMyDIB will now be NULL and the original
  757. * DIB will now hang around in memory. We could have returned the old
  758. * DIB, but we wanted to allow the programmer to check whether this
  759. * conversion succeeded or failed.
  760. *
  761. ************************************************************************/
  762. HDIB ChangeDIBFormat(HDIB hDIB, WORD wBitCount, DWORD dwCompression)
  763. {
  764. HDC hDC; // Handle to DC
  765. HBITMAP hBitmap; // Handle to bitmap
  766. BITMAP Bitmap; // BITMAP data structure
  767. BITMAPINFOHEADER bi; // Bitmap info header
  768. LPBITMAPINFOHEADER lpbi; // Pointer to bitmap info
  769. HDIB hNewDIB = NULL; // Handle to new DIB
  770. HPALETTE hPal, hOldPal; // Handle to palette, prev pal
  771. WORD DIBBPP, NewBPP; // DIB bits per pixel, new bpp
  772. DWORD DIBComp, NewComp;// DIB compression, new compression
  773. // Check for a valid DIB handle
  774. if (!hDIB)
  775. return NULL;
  776. // Get the old DIB's bits per pixel and compression format
  777. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
  778. DIBBPP = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
  779. DIBComp = ((LPBITMAPINFOHEADER)lpbi)->biCompression;
  780. GlobalUnlock(hDIB);
  781. // Validate wBitCount and dwCompression
  782. // They must match correctly (i.e., BI_RLE4 and 4 BPP or
  783. // BI_RLE8 and 8BPP, etc.) or we return failure
  784. if (wBitCount == 0)
  785. {
  786. NewBPP = DIBBPP;
  787. if ((dwCompression == BI_RLE4 && NewBPP == 4) ||
  788. (dwCompression == BI_RLE8 && NewBPP == 8) ||
  789. (dwCompression == BI_RGB))
  790. NewComp = dwCompression;
  791. else
  792. return NULL;
  793. }
  794. else if (wBitCount == 1 && dwCompression == BI_RGB)
  795. {
  796. NewBPP = wBitCount;
  797. NewComp = BI_RGB;
  798. }
  799. else if (wBitCount == 4)
  800. {
  801. NewBPP = wBitCount;
  802. if (dwCompression == BI_RGB || dwCompression == BI_RLE4)
  803. NewComp = dwCompression;
  804. else
  805. return NULL;
  806. }
  807. else if (wBitCount == 8)
  808. {
  809. NewBPP = wBitCount;
  810. if (dwCompression == BI_RGB || dwCompression == BI_RLE8)
  811. NewComp = dwCompression;
  812. else
  813. return NULL;
  814. }
  815. else if (wBitCount == 24 && dwCompression == BI_RGB)
  816. {
  817. NewBPP = wBitCount;
  818. NewComp = BI_RGB;
  819. }
  820. else
  821. return NULL;
  822. // Save the old DIB's palette
  823. hPal = CreateDIBPalette(hDIB);
  824. if (!hPal)
  825. return NULL;
  826. // Convert old DIB to a bitmap
  827. hBitmap = DIBToBitmap(hDIB, hPal);
  828. if (!hBitmap)
  829. {
  830. DeleteObject(hPal);
  831. return NULL;
  832. }
  833. // Get info about the bitmap
  834. GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
  835. // Fill in the BITMAPINFOHEADER appropriately
  836. bi.biSize = sizeof(BITMAPINFOHEADER);
  837. bi.biWidth = Bitmap.bmWidth;
  838. bi.biHeight = Bitmap.bmHeight;
  839. bi.biPlanes = 1;
  840. bi.biBitCount = NewBPP;
  841. bi.biCompression = NewComp;
  842. bi.biSizeImage = 0;
  843. bi.biXPelsPerMeter = 0;
  844. bi.biYPelsPerMeter = 0;
  845. bi.biClrUsed = 0;
  846. bi.biClrImportant = 0;
  847. // Go allocate room for the new DIB
  848. hNewDIB = AllocRoomForDIB(bi, hBitmap);
  849. if (!hNewDIB)
  850. return NULL;
  851. // Get a pointer to the new DIB
  852. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);
  853. // Get a DC and select/realize our palette in it
  854. hDC = GetDC(NULL);
  855. hOldPal = SelectPalette(hDC, hPal, FALSE);
  856. RealizePalette(hDC);
  857. // Call GetDIBits and get the new DIB bits
  858. if (!GetDIBits(hDC, hBitmap, 0, (UINT) lpbi->biHeight,
  859. (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi),
  860. (LPBITMAPINFO)lpbi, DIB_RGB_COLORS))
  861. {
  862. GlobalUnlock(hNewDIB);
  863. GlobalFree(hNewDIB);
  864. hNewDIB = NULL;
  865. }
  866. // Clean up and return
  867. SelectPalette(hDC, hOldPal, TRUE);
  868. RealizePalette(hDC);
  869. ReleaseDC(NULL, hDC);
  870. // Unlock the new DIB's memory block
  871. if (hNewDIB)
  872. GlobalUnlock(hNewDIB);
  873. DeleteObject(hBitmap);
  874. DeleteObject(hPal);
  875. return hNewDIB;
  876. }
  877. /*************************************************************************
  878. *
  879. * ChangeBitmapFormat()
  880. *
  881. * Parameter:
  882. *
  883. * HBITMAP - handle to a bitmap
  884. *
  885. * WORD - desired bits per pixel
  886. *
  887. * DWORD - desired compression format
  888. *
  889. * HPALETTE - handle to palette
  890. *
  891. * Return Value:
  892. *
  893. * HDIB - handle to the new DIB if successful, else NULL
  894. *
  895. * Description:
  896. *
  897. * This function will convert a bitmap to the specified bits per pixel
  898. * and compression format. The bitmap and it's palette will remain
  899. * after calling this function.
  900. *
  901. ************************************************************************/
  902. HDIB ChangeBitmapFormat(HBITMAP hBitmap, WORD wBitCount, DWORD dwCompression,
  903. HPALETTE hPal)
  904. {
  905. HDC hDC; // Screen DC
  906. HDIB hNewDIB=NULL; // Handle to new DIB
  907. BITMAP Bitmap; // BITMAP data structure
  908. BITMAPINFOHEADER bi; // Bitmap info. header
  909. LPBITMAPINFOHEADER lpbi; // Pointer to bitmap header
  910. HPALETTE hOldPal=NULL; // Handle to palette
  911. WORD NewBPP; // New bits per pixel
  912. DWORD NewComp; // New compression format
  913. // Check for a valid bitmap handle
  914. if (!hBitmap)
  915. return NULL;
  916. // Validate wBitCount and dwCompression
  917. // They must match correctly (i.e., BI_RLE4 and 4 BPP or
  918. // BI_RLE8 and 8BPP, etc.) or we return failure
  919. if (wBitCount == 0)
  920. {
  921. NewComp = dwCompression;
  922. if (NewComp == BI_RLE4)
  923. NewBPP = 4;
  924. else if (NewComp == BI_RLE8)
  925. NewBPP = 8;
  926. else // Not enough info */
  927. return NULL;
  928. }
  929. else if (wBitCount == 1 && dwCompression == BI_RGB)
  930. {
  931. NewBPP = wBitCount;
  932. NewComp = BI_RGB;
  933. }
  934. else if (wBitCount == 4)
  935. {
  936. NewBPP = wBitCount;
  937. if (dwCompression == BI_RGB || dwCompression == BI_RLE4)
  938. NewComp = dwCompression;
  939. else
  940. return NULL;
  941. }
  942. else if (wBitCount == 8)
  943. {
  944. NewBPP = wBitCount;
  945. if (dwCompression == BI_RGB || dwCompression == BI_RLE8)
  946. NewComp = dwCompression;
  947. else
  948. return NULL;
  949. }
  950. else if (wBitCount == 24 && dwCompression == BI_RGB)
  951. {
  952. NewBPP = wBitCount;
  953. NewComp = BI_RGB;
  954. }
  955. else
  956. return NULL;
  957. // Get info about the bitmap
  958. GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
  959. // Fill in the BITMAPINFOHEADER appropriately
  960. bi.biSize = sizeof(BITMAPINFOHEADER);
  961. bi.biWidth = Bitmap.bmWidth;
  962. bi.biHeight = Bitmap.bmHeight;
  963. bi.biPlanes = 1;
  964. bi.biBitCount = NewBPP;
  965. bi.biCompression = NewComp;
  966. bi.biSizeImage = 0;
  967. bi.biXPelsPerMeter = 0;
  968. bi.biYPelsPerMeter = 0;
  969. bi.biClrUsed = 0;
  970. bi.biClrImportant = 0;
  971. // Go allocate room for the new DIB
  972. hNewDIB = AllocRoomForDIB(bi, hBitmap);
  973. if (!hNewDIB)
  974. return NULL;
  975. // Get a pointer to the new DIB
  976. lpbi = (LPBITMAPINFOHEADER)GlobalLock(hNewDIB);
  977. // If we have a palette, get a DC and select/realize it
  978. if (hPal)
  979. {
  980. hDC = GetDC(NULL);
  981. hOldPal = SelectPalette(hDC, hPal, FALSE);
  982. RealizePalette(hDC);
  983. }
  984. // Call GetDIBits and get the new DIB bits
  985. if (!GetDIBits(hDC, hBitmap, 0, (UINT) lpbi->biHeight, (LPSTR)lpbi +
  986. (WORD)lpbi->biSize + PaletteSize((LPSTR)lpbi), (LPBITMAPINFO)lpbi,
  987. DIB_RGB_COLORS))
  988. {
  989. GlobalUnlock(hNewDIB);
  990. GlobalFree(hNewDIB);
  991. hNewDIB = NULL;
  992. }
  993. // Clean up and return
  994. if (hOldPal)
  995. {
  996. SelectPalette(hDC, hOldPal, TRUE);
  997. RealizePalette(hDC);
  998. ReleaseDC(NULL, hDC);
  999. }
  1000. // Unlock the new DIB's memory block
  1001. if (hNewDIB)
  1002. GlobalUnlock(hNewDIB);
  1003. return hNewDIB;
  1004. }