DIBUTIL.CPP 38 KB

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