DIBUTIL.CPP 38 KB

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