dibapi.cpp
上传用户:gzboli
上传日期:2013-04-10
资源大小:471k
文件大小:239k
源码类别:

图片显示

开发平台:

Visual C++

  1. // RotateBitmapNT - Create a new bitmap with rotated image
  2. // Returns - Returns new bitmap with rotated image
  3. // hBitmap - Bitmap to rotate
  4. // fDegrees - Angle of rotation in degree
  5. // clrBack - Color of pixels in the resulting bitmap that do
  6. //   not get covered by source pixels
  7. HBITMAP RotateBitmapNT(HBITMAP hBitmap, double fDegrees, COLORREF clrBack)
  8. {
  9. // Create a memory DC compatible with the display
  10. CDC sourceDC, destDC;
  11. sourceDC.CreateCompatibleDC( NULL );
  12. destDC.CreateCompatibleDC( NULL );
  13. // Get logical coordinates
  14. BITMAP bm;
  15. ::GetObject( hBitmap, sizeof( bm ), &bm );
  16. // Convert angle degree to radians 
  17. #define PI 3.1415926
  18. double radians = (fDegrees/90.0)*(PI/2);
  19. // Compute the cosine and sine only once
  20. float cosine = (float)cos(radians);
  21. float sine = (float)sin(radians);
  22. // Compute dimensions of the resulting bitmap
  23. // First get the coordinates of the 3 corners other than origin
  24. int x1 = (int)(bm.bmHeight * sine);
  25. int y1 = (int)(bm.bmHeight * cosine);
  26. int x2 = (int)(bm.bmWidth * cosine + bm.bmHeight * sine);
  27. int y2 = (int)(bm.bmHeight * cosine - bm.bmWidth * sine);
  28. int x3 = (int)(bm.bmWidth * cosine);
  29. int y3 = (int)(-bm.bmWidth * sine);
  30. int minx = min(0,min(x1, min(x2,x3)));
  31. int miny = min(0,min(y1, min(y2,y3)));
  32. int maxx = max(0,max(x1, max(x2,x3)));
  33. int maxy = max(0,max(y1, max(y2,y3)));
  34. int w = maxx - minx;
  35. int h = maxy - miny;
  36. // Create a bitmap to hold the result
  37. HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL), w, h);
  38. HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
  39. HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
  40. // Draw the background color before we change mapping mode
  41. HBRUSH hbrBack = CreateSolidBrush( clrBack );
  42. HBRUSH hbrOld = (HBRUSH)::SelectObject( destDC.m_hDC, hbrBack );
  43. destDC.PatBlt( 0, 0, w, h, PATCOPY );
  44. ::DeleteObject( ::SelectObject( destDC.m_hDC, hbrOld ) );
  45. // We will use world transform to rotate the bitmap
  46. SetGraphicsMode(destDC.m_hDC, GM_ADVANCED);
  47. XFORM xform;
  48. xform.eM11 = cosine;
  49. xform.eM12 = -sine;
  50. xform.eM21 = sine;
  51. xform.eM22 = cosine;
  52. xform.eDx = (float)-minx;
  53. xform.eDy = (float)-miny;
  54. SetWorldTransform( destDC.m_hDC, &xform );
  55. // Now do the actual rotating - a pixel at a time
  56. destDC.BitBlt(0,0,bm.bmWidth, bm.bmHeight, &sourceDC, 0, 0, SRCCOPY );
  57. // Restore DCs
  58. ::SelectObject( sourceDC.m_hDC, hbmOldSource );
  59. ::SelectObject( destDC.m_hDC, hbmOldDest );
  60. return hbmResult;
  61. }
  62. // RotateBitmap - Create a new bitmap with rotated image
  63. // Returns - Returns new bitmap with rotated image
  64. // hBitmap - Bitmap to rotate
  65. // fDegrees - Angle of rotation in degree
  66. // clrBack - Color of pixels in the resulting bitmap that do
  67. //   not get covered by source pixels
  68. // Note - If the bitmap uses colors not in the system palette 
  69. //   then the result is unexpected. You can fix this by
  70. //   adding an argument for the logical palette.
  71. HBITMAP RotateBitmap(HBITMAP hBitmap, double fDegrees, COLORREF clrBack)
  72. {
  73. // Create a memory DC compatible with the display
  74. CDC sourceDC, destDC;
  75. sourceDC.CreateCompatibleDC( NULL );
  76. destDC.CreateCompatibleDC( NULL );
  77. // Get logical coordinates
  78. BITMAP bm;
  79. ::GetObject( hBitmap, sizeof( bm ), &bm );
  80. // Convert angle degree to radians 
  81. #define PI 3.1415926
  82. double radians = (fDegrees/90.0)*(PI/2);
  83. // Compute the cosine and sine only once
  84. float cosine = (float)cos(radians);
  85. float sine = (float)sin(radians);
  86. // Compute dimensions of the resulting bitmap
  87. // First get the coordinates of the 3 corners other than origin
  88. int x1 = (int)(-bm.bmHeight * sine);
  89. int y1 = (int)(bm.bmHeight * cosine);
  90. int x2 = (int)(bm.bmWidth * cosine - bm.bmHeight * sine);
  91. int y2 = (int)(bm.bmHeight * cosine + bm.bmWidth * sine);
  92. int x3 = (int)(bm.bmWidth * cosine);
  93. int y3 = (int)(bm.bmWidth * sine);
  94. int minx = min(0,min(x1, min(x2,x3)));
  95. int miny = min(0,min(y1, min(y2,y3)));
  96. int maxx = max(x1, max(x2,x3));
  97. int maxy = max(y1, max(y2,y3));
  98. int w = maxx - minx;
  99. int h = maxy - miny;
  100. // Create a bitmap to hold the result
  101. HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL), w, h);
  102. HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
  103. HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
  104. // Draw the background color before we change mapping mode
  105. HBRUSH hbrBack = CreateSolidBrush( clrBack );
  106. HBRUSH hbrOld = (HBRUSH)::SelectObject( destDC.m_hDC, hbrBack );
  107. destDC.PatBlt( 0, 0, w, h, PATCOPY );
  108. ::DeleteObject( ::SelectObject( destDC.m_hDC, hbrOld ) );
  109. // Set mapping mode so that +ve y axis is upwords
  110. sourceDC.SetMapMode(MM_ISOTROPIC);
  111. sourceDC.SetWindowExt(1,1);
  112. sourceDC.SetViewportExt(1,-1);
  113. sourceDC.SetViewportOrg(0, bm.bmHeight-1);
  114. destDC.SetMapMode(MM_ISOTROPIC);
  115. destDC.SetWindowExt(1,1);
  116. destDC.SetViewportExt(1,-1);
  117. destDC.SetWindowOrg(minx, maxy);
  118. // Now do the actual rotating - a pixel at a time
  119. // Computing the destination point for each source point
  120. // will leave a few pixels that do not get covered
  121. // So we use a reverse transform - e.i. compute the source point
  122. // for each destination point
  123. for( int y = miny; y < maxy; y++ )
  124. {
  125. for( int x = minx; x < maxx; x++ )
  126. {
  127. int sourcex = (int)(x*cosine + y*sine);
  128. int sourcey = (int)(y*cosine - x*sine);
  129. if( sourcex >= 0 && sourcex < bm.bmWidth && sourcey >= 0 
  130. && sourcey < bm.bmHeight )
  131. destDC.SetPixel(x,y,sourceDC.GetPixel(sourcex,sourcey));
  132. }
  133. }
  134. // Restore DCs
  135. ::SelectObject( sourceDC.m_hDC, hbmOldSource );
  136. ::SelectObject( destDC.m_hDC, hbmOldDest );
  137. return hbmResult;
  138. }
  139. // RotateDIB - Create a new bitmap with rotated image
  140. // Returns - Returns new bitmap with rotated image
  141. // hDIB - Device-independent bitmap to rotate
  142. // fDegrees - Angle of rotation in degree
  143. // clrBack - Color of pixels in the resulting bitmap that do
  144. //   not get covered by source pixels
  145. HDIB RotateDIB(HDIB hDIB, double fDegrees, COLORREF clrBack)
  146. {
  147. WaitCursorBegin();
  148. // Get source bitmap info
  149. LPBITMAPINFO lpBmInfo = (LPBITMAPINFO)GlobalLock(hDIB);
  150. int bpp = lpBmInfo->bmiHeader.biBitCount; // Bits per pixel
  151. int nColors = lpBmInfo->bmiHeader.biClrUsed ? lpBmInfo->bmiHeader.biClrUsed : 
  152. 1 << bpp;
  153. int nWidth = lpBmInfo->bmiHeader.biWidth;
  154. int nHeight = lpBmInfo->bmiHeader.biHeight;
  155. int nRowBytes = ((((nWidth * bpp) + 31) & ~31) / 8);
  156. // Make sure height is positive and biCompression is BI_RGB or BI_BITFIELDS
  157. DWORD compression = lpBmInfo->bmiHeader.biCompression;
  158. if( nHeight < 0 || (compression!=BI_RGB))
  159. {
  160. GlobalUnlock(hDIB);
  161. WaitCursorEnd();
  162. return NULL;
  163. }
  164. LPSTR lpDIBBits = FindDIBBits((LPSTR)lpBmInfo);
  165.     
  166. // Convert angle degree to radians 
  167. #define PI 3.1415926
  168. double radians = (fDegrees/90.0)*(PI/2);
  169. // Compute the cosine and sine only once
  170. float cosine = (float)cos(radians);
  171. float sine = (float)sin(radians);
  172. // Compute dimensions of the resulting bitmap
  173. // First get the coordinates of the 3 corners other than origin
  174. int x1 = (int)(-nHeight * sine);
  175. int y1 = (int)(nHeight * cosine);
  176. int x2 = (int)(nWidth * cosine - nHeight * sine);
  177. int y2 = (int)(nHeight * cosine + nWidth * sine);
  178. int x3 = (int)(nWidth * cosine);
  179. int y3 = (int)(nWidth * sine);
  180. int minx = min(0,min(x1, min(x2,x3)));
  181. int miny = min(0,min(y1, min(y2,y3)));
  182. int maxx = max(x1, max(x2,x3));
  183. int maxy = max(y1, max(y2,y3));
  184. int w = maxx - minx;
  185. int h = maxy - miny;
  186. // Create a DIB to hold the result
  187. int nResultRowBytes = ((((w * bpp) + 31) & ~31) / 8);
  188. long len = nResultRowBytes * h;
  189. int nHeaderSize = ((LPSTR)lpDIBBits-(LPSTR)lpBmInfo) ;
  190. HANDLE hDIBResult = GlobalAlloc(GHND,len+nHeaderSize);
  191. // Initialize the header information
  192. LPBITMAPINFO lpBmInfoResult = (LPBITMAPINFO)GlobalLock(hDIBResult);
  193. memcpy( (void*)lpBmInfoResult, (void*)lpBmInfo, nHeaderSize);
  194. lpBmInfoResult->bmiHeader.biWidth = w;
  195. lpBmInfoResult->bmiHeader.biHeight = h;
  196. lpBmInfoResult->bmiHeader.biSizeImage = len;
  197. LPSTR lpDIBBitsResult = FindDIBBits((LPSTR)lpBmInfoResult);
  198. // Get the back color value (index)
  199. ZeroMemory( lpDIBBitsResult, len );
  200. DWORD dwBackColor;
  201. switch(bpp)
  202. {
  203. case 1: //Monochrome
  204. if( clrBack == RGB(255,255,255) )
  205. memset( lpDIBBitsResult, 0xff, len );
  206. break;
  207. case 4:
  208. case 8: //Search the color table
  209. int i;
  210. for(i = 0; i < nColors; i++ )
  211. {
  212. if( lpBmInfo->bmiColors[i].rgbBlue ==  GetBValue(clrBack)
  213. && lpBmInfo->bmiColors[i].rgbGreen ==  GetGValue(clrBack)
  214. && lpBmInfo->bmiColors[i].rgbRed ==  GetRValue(clrBack) )
  215. {
  216. if(bpp==4) i = i | i<<4;
  217. memset( lpDIBBitsResult, i, len );
  218. break;
  219. }
  220. }
  221. // If not match found the color remains black
  222. break;
  223. case 16:
  224. // Windows95 supports 5 bits each for all colors or 5 bits for red & blue
  225. // and 6 bits for green - Check the color mask for RGB555 or RGB565
  226. if( *((DWORD*)lpBmInfo->bmiColors) == 0x7c00 )
  227. {
  228. // Bitmap is RGB555
  229. dwBackColor = ((GetRValue(clrBack)>>3) << 10) + 
  230. ((GetRValue(clrBack)>>3) << 5) +
  231. (GetBValue(clrBack)>>3) ;
  232. }
  233. else
  234. {
  235. // Bitmap is RGB565
  236. dwBackColor = ((GetRValue(clrBack)>>3) << 11) + 
  237. ((GetRValue(clrBack)>>2) << 5) +
  238. (GetBValue(clrBack)>>3) ;
  239. }
  240. break;
  241. case 24:
  242. case 32:
  243. dwBackColor = (((DWORD)GetRValue(clrBack)) << 16) | 
  244. (((DWORD)GetGValue(clrBack)) << 8) |
  245. (((DWORD)GetBValue(clrBack)));
  246. break;
  247. }
  248. // Now do the actual rotating - a pixel at a time
  249. // Computing the destination point for each source point
  250. // will leave a few pixels that do not get covered
  251. // So we use a reverse transform - e.i. compute the source point
  252. // for each destination point
  253. for( int y = 0; y < h; y++ )
  254. {
  255. for( int x = 0; x < w; x++ )
  256. {
  257. int sourcex = (int)((x+minx)*cosine + (y+miny)*sine);
  258. int sourcey = (int)((y+miny)*cosine - (x+minx)*sine);
  259. if( sourcex >= 0 && sourcex < nWidth && sourcey >= 0 
  260. && sourcey < nHeight )
  261. {
  262. // Set the destination pixel
  263. switch(bpp)
  264. {
  265. BYTE mask;
  266. case 1: //Monochrome
  267. mask = *((LPSTR)lpDIBBits + nRowBytes*sourcey + 
  268. sourcex/8) & (0x80 >> sourcex%8);
  269. //Adjust mask for destination bitmap
  270. mask = mask ? (0x80 >> x%8) : 0;
  271. *((LPSTR)lpDIBBitsResult + nResultRowBytes*(y) + 
  272. (x/8)) &= ~(0x80 >> x%8);
  273. *((LPSTR)lpDIBBitsResult + nResultRowBytes*(y) + 
  274. (x/8)) |= mask;
  275. break;
  276. case 4:
  277. mask = *((LPSTR)lpDIBBits + nRowBytes*sourcey + 
  278. sourcex/2) & ((sourcex&1) ? 0x0f : 0xf0);
  279. //Adjust mask for destination bitmap
  280. if( (sourcex&1) != (x&1) )
  281. mask = (mask&0xf0) ? (mask>>4) : (mask<<4);
  282. *((LPSTR)lpDIBBitsResult + nResultRowBytes*(y) + 
  283. (x/2)) &= ~((x&1) ? 0x0f : 0xf0);
  284. *((LPSTR)lpDIBBitsResult + nResultRowBytes*(y) + 
  285. (x/2)) |= mask;
  286. break;
  287. case 8:
  288. BYTE pixel ;
  289. pixel = *((LPSTR)lpDIBBits + nRowBytes*sourcey + 
  290. sourcex);
  291. *((LPSTR)lpDIBBitsResult + nResultRowBytes*(y) + 
  292. (x)) = pixel;
  293. break;
  294. case 16:
  295. DWORD dwPixel;
  296. dwPixel = *((LPWORD)((LPSTR)lpDIBBits + 
  297. nRowBytes*sourcey + sourcex*2));
  298. *((LPWORD)((LPSTR)lpDIBBitsResult + 
  299. nResultRowBytes*y + x*2)) = (WORD)dwPixel;
  300. break;
  301. case 24:
  302. dwPixel = *((LPDWORD)((LPSTR)lpDIBBits + 
  303. nRowBytes*sourcey + sourcex*3)) & 0xffffff;
  304. *((LPDWORD)((LPSTR)lpDIBBitsResult + 
  305. nResultRowBytes*y + x*3)) |= dwPixel;
  306. break;
  307. case 32:
  308. dwPixel = *((LPDWORD)((LPSTR)lpDIBBits + 
  309. nRowBytes*sourcey + sourcex*4));
  310. *((LPDWORD)((LPSTR)lpDIBBitsResult + 
  311. nResultRowBytes*y + x*4)) = dwPixel;
  312. }
  313. }
  314. else 
  315. {
  316. // Draw the background color. The background color
  317. // has already been drawn for 8 bits per pixel and less
  318. switch(bpp)
  319. {
  320. case 16:
  321. *((LPWORD)((LPSTR)lpDIBBitsResult + 
  322. nResultRowBytes*y + x*2)) = 
  323. (WORD)dwBackColor;
  324. break;
  325. case 24:
  326. *((LPDWORD)((LPSTR)lpDIBBitsResult + 
  327. nResultRowBytes*y + x*3)) |= dwBackColor;
  328. break;
  329. case 32:
  330. *((LPDWORD)((LPSTR)lpDIBBitsResult + 
  331. nResultRowBytes*y + x*4)) = dwBackColor;
  332. break;
  333. }
  334. }
  335. }
  336. }
  337. GlobalUnlock(hDIB);
  338. GlobalUnlock(hDIBResult);
  339. WaitCursorEnd();
  340. return hDIBResult;
  341. }
  342. /************************************************************************* 
  343.  * 
  344.  * RotateDIB() 
  345.  * 
  346.  * Parameters: 
  347.  * 
  348.  * HDIB hDIB  - handle of DIB to rotate
  349.  * 
  350.  * Return Value: 
  351.  * 
  352.  * HDIB             - Handle to new DIB 
  353.  * 
  354.  * Description: 
  355.  * 
  356.  * This function rotate DIB 90 degree counter clockwise, and return
  357.  * the rotated DIB in a new DIB handle, let the source DIB unchanged
  358.  * 
  359.  ************************************************************************/ 
  360. HDIB RotateDIB(HDIB hDib)
  361. {
  362. WaitCursorBegin();
  363. // old DIB
  364. LPSTR lpDIBSrc = (LPSTR)GlobalLock(hDib);
  365. DWORD lSrcWidth = DIBWidth(lpDIBSrc);
  366. DWORD lSrcHeight = DIBHeight(lpDIBSrc);
  367. WORD wBitCount = ((LPBITMAPINFOHEADER)lpDIBSrc)->biBitCount;
  368. // bits position
  369.     LPSTR lpOldBits = FindDIBBits(lpDIBSrc);
  370. // get bytes/pixel, bytes/row of new DIB
  371. double fColorBytes = (double)((double)wBitCount/8.0);
  372. DWORD lSrcRowBytes = WIDTHBYTES(lSrcWidth*((DWORD)wBitCount));
  373. DWORD lDestRowBytes = WIDTHBYTES(lSrcHeight*((DWORD)wBitCount));
  374. // adjust new DIB size
  375. DWORD dwDataLength = GlobalSize(hDib);
  376. dwDataLength += lDestRowBytes*(lSrcWidth-1)+(DWORD)((lSrcHeight-1)*fColorBytes) - 
  377.   lSrcRowBytes*(lSrcHeight-1)+(DWORD)((lSrcWidth-1)*fColorBytes);
  378. HDIB hNewDib = GlobalAlloc(GHND, dwDataLength);
  379. if (! hNewDib)
  380. {
  381. WaitCursorEnd();
  382. return NULL;
  383. }
  384. // new DIB buffer
  385. LPSTR lpDIB = (LPSTR)GlobalLock(hNewDib);
  386. // copy LPBITMAPINFO from old to new
  387. memcpy(lpDIB, lpDIBSrc, sizeof(BITMAPINFOHEADER)+PaletteSize(lpDIBSrc));
  388. // swap width and height
  389. ((LPBITMAPINFOHEADER)lpDIB)->biHeight = lSrcWidth;
  390. ((LPBITMAPINFOHEADER)lpDIB)->biWidth = lSrcHeight;
  391. // new bits position
  392. LPSTR lpData = FindDIBBits(lpDIB);
  393. // trandform bits
  394. DWORD i, j;
  395. switch (wBitCount)
  396. {
  397. case 1:
  398. for (i=0; i<lSrcHeight; ++i)
  399. {
  400. for (j=0; j<lSrcWidth; ++j)
  401. {
  402. *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)/8)) &= ~(1<<(7-((lSrcHeight-i-1)%8)));
  403. *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)/8)) |= 
  404. ((*(lpOldBits+(lSrcRowBytes*i+j/8))<<(j%8))>>7)<<(7-((lSrcHeight-i-1)%8));
  405. }
  406. }
  407. break;
  408. case 4:
  409. for (i=0; i<lSrcHeight; ++i)
  410. {
  411. for (j=0; j<lSrcWidth; ++j)
  412. {
  413. *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)/2)) &= ((lSrcHeight-i-1)%2) ? 0xf0 : 0x0f;
  414. *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)/2)) |= 
  415. ((*(lpOldBits+(lSrcRowBytes*i+j/2))<<(j%2 ? 4 : 0))>>4)<<(((lSrcHeight-i-1)%2) ? 0 : 4);
  416. }
  417. }
  418. break;
  419. case 8:
  420. for (i=0; i<lSrcHeight; ++i)
  421. {
  422. for (j=0; j<lSrcWidth; ++j)
  423. {
  424. *(lpData+(lDestRowBytes*j+lSrcHeight-i-1))
  425. = *(lpOldBits+(lSrcRowBytes*i+j));
  426. }
  427. }
  428. break;
  429. case 24:
  430. for (i=0; i<lSrcHeight; ++i)
  431. {
  432. for (j=0; j<lSrcWidth; j++)
  433. {
  434. *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)*3))
  435. = *(lpOldBits+(lSrcRowBytes*i+j*3));
  436. *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)*3)+1)
  437. = *(lpOldBits+(lSrcRowBytes*i+j*3)+1);
  438. *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)*3)+2)
  439. = *(lpOldBits+(lSrcRowBytes*i+j*3)+2);
  440. }
  441. }
  442. break;
  443. }
  444. // cleanup
  445. GlobalUnlock(hDib);
  446. GlobalUnlock(hNewDib);
  447. WaitCursorEnd();
  448. return hNewDib;
  449. }
  450. /************************************************************************* 
  451.  * 
  452.  * FlipHorzDIB() 
  453.  * 
  454.  * Parameters: 
  455.  * 
  456.  * HDIB hDIB  - handle of DIB to flip horzonly
  457.  * 
  458.  * Return Value: 
  459.  * 
  460.  * HDIB             - Handle to new DIB 
  461.  * 
  462.  * Description: 
  463.  * 
  464.  * This function flip DIB horzonly, and return
  465.  * the flipped DIB in a new DIB handle, let the source DIB unchanged
  466.  * 
  467.  ************************************************************************/ 
  468. HDIB FlipHorzDIB(HDIB hDib)
  469. {
  470. WaitCursorBegin();
  471. // create new DIB
  472. DWORD dwDataLength = GlobalSize(hDib);
  473. HDIB hNewDib = GlobalAlloc(GHND, dwDataLength);
  474. if (! hNewDib)
  475. {
  476. WaitCursorEnd();
  477. return NULL;
  478. }
  479. LPSTR lpDIB = (LPSTR)GlobalLock(hNewDib);
  480. if (lpDIB == NULL)
  481. {
  482. WaitCursorEnd();
  483. return FALSE;
  484. }
  485. // old DIB buffer
  486. LPSTR lpDIBSrc = (LPSTR)GlobalLock(hDib);
  487. // copy LPBITMAPINFO from old to new
  488. memcpy(lpDIB, lpDIBSrc, sizeof(BITMAPINFOHEADER)+PaletteSize(lpDIBSrc));
  489. DWORD lSrcWidth = DIBWidth(lpDIBSrc);
  490. DWORD lSrcHeight = DIBHeight(lpDIBSrc);
  491. WORD wBitCount = ((LPBITMAPINFOHEADER)lpDIBSrc)->biBitCount;
  492. // get bytesbytes/pixel, bytes/row  
  493. double fColorBytes = (double)((double)wBitCount/8.0);
  494. DWORD lSrcRowBytes = WIDTHBYTES(lSrcWidth*((DWORD)wBitCount));
  495. // bits position
  496.     LPSTR lpOldBits = FindDIBBits(lpDIBSrc);
  497. LPSTR lpData = FindDIBBits(lpDIB);
  498. // trandform bits
  499. DWORD i, j;
  500. switch (wBitCount)
  501. {
  502. case 1:
  503. for (i=0; i<lSrcHeight; ++i)
  504. for (j=0; j<lSrcWidth; ++j)
  505. {
  506. *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)/8)) &= ~(1<<(7-((lSrcWidth-j-1)%8)));
  507. *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)/8)) |= 
  508. ((*(lpOldBits+(lSrcRowBytes*i+j/8))<<(j%8))>>7)<<(7-(lSrcWidth-j-1)%8);
  509. }
  510. break;
  511. case 4:
  512. for (i=0; i<lSrcHeight; ++i)
  513. {
  514. for (j=0; j<lSrcWidth; ++j)
  515. {
  516. *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)/2)) &= ((lSrcWidth-j-1)%2) ? 0xf0 : 0x0f;
  517. *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)/2)) |= 
  518. ((*(lpOldBits+(lSrcRowBytes*i+j/2))<<(j%2 ? 4 : 0))>>4)<<(((lSrcWidth-j-1)%2) ? 0 : 4);
  519. }
  520. }
  521. break;
  522. case 8:
  523. for (i=0; i<lSrcHeight; ++i)
  524. for (j=0; j<lSrcWidth; ++j)
  525. *(lpData+(lSrcRowBytes*i+lSrcWidth-j-1))
  526. = *(lpOldBits+(lSrcRowBytes*i+j));
  527. break;
  528. case 24:
  529. for (i=0; i<lSrcHeight; ++i)
  530. for (j=0; j<lSrcWidth; j++)
  531. {
  532. *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)*3))
  533. = *(lpOldBits+(lSrcRowBytes*i+j*3));
  534. *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)*3)+1)
  535. = *(lpOldBits+(lSrcRowBytes*i+j*3)+1);
  536. *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)*3)+2)
  537. = *(lpOldBits+(lSrcRowBytes*i+j*3)+2);
  538. }
  539. break;
  540. }
  541. GlobalUnlock(hDib);
  542. GlobalUnlock(hNewDib);
  543. WaitCursorEnd();
  544. return hNewDib;
  545. }
  546. /************************************************************************* 
  547.  * 
  548.  * FlipVertDIB() 
  549.  * 
  550.  * Parameters: 
  551.  * 
  552.  * HDIB hDIB  - handle of DIB to flip vertically
  553.  * 
  554.  * Return Value: 
  555.  * 
  556.  * HDIB             - Handle to new DIB 
  557.  * 
  558.  * Description: 
  559.  * 
  560.  * This function flip DIB vertically, and return
  561.  * the flipped DIB in a new DIB handle, let the source DIB unchanged
  562.  * 
  563.  ************************************************************************/ 
  564. HDIB FlipVertDIB(HDIB hDib)
  565. {
  566. WaitCursorBegin();
  567. // create new DIB
  568. DWORD dwDataLength = GlobalSize(hDib);
  569. HDIB hNewDib = GlobalAlloc(GHND, dwDataLength);
  570. if (! hNewDib)
  571. {
  572. WaitCursorEnd();
  573. return NULL;
  574. }
  575. LPSTR lpDIB = (LPSTR)GlobalLock(hNewDib);
  576. if (lpDIB == NULL)
  577. {
  578. WaitCursorEnd();
  579. return FALSE;
  580. }
  581. // old DIB buffer
  582. LPSTR lpDIBSrc = (LPSTR)GlobalLock(hDib);
  583. // copy LPBITMAPINFO from old to new
  584. memcpy(lpDIB, lpDIBSrc, sizeof(BITMAPINFOHEADER)+PaletteSize(lpDIBSrc));
  585. DWORD lSrcWidth = DIBWidth(lpDIBSrc);
  586. DWORD lSrcHeight = DIBHeight(lpDIBSrc);
  587. WORD wBitCount = ((LPBITMAPINFOHEADER)lpDIBSrc)->biBitCount;
  588. // get bytesbytes/pixel, bytes/row  
  589. double fColorBytes = (double)((double)wBitCount/8.0);
  590. DWORD lSrcRowBytes = WIDTHBYTES(lSrcWidth*((DWORD)wBitCount));
  591. // bits position
  592.     LPSTR lpOldBits = FindDIBBits(lpDIBSrc);
  593. LPSTR lpData = FindDIBBits(lpDIB);
  594. // trandform bits
  595. for (DWORD i=0; i<lSrcHeight; ++i)
  596. for (DWORD j=0; j<lSrcRowBytes; ++j)
  597. *(lpData+(lSrcRowBytes*(lSrcHeight-i-1)+j))
  598. = *(lpOldBits+(lSrcRowBytes*i+j));
  599. GlobalUnlock(hDib);
  600. GlobalUnlock(hNewDib);
  601. WaitCursorEnd();
  602. return hNewDib;
  603. }
  604. /************************************************************************* 
  605.  * 
  606.  * ChangeDIBSize() 
  607.  * 
  608.  * Parameters: 
  609.  * 
  610.  * HDIB hDIB  - handle of DIB to zoom
  611.  * int nWidth, int nHeight   - new size of DIB
  612.  * 
  613.  * Return Value: 
  614.  * 
  615.  * HDIB             - Handle to new DIB 
  616.  * 
  617.  * Description: 
  618.  * 
  619.  * This function zoom a DIB to specified size, and return
  620.  * the zoomed DIB in a new DIB handle, let the source DIB unchanged
  621.  * 
  622.  ************************************************************************/ 
  623. HDIB ChangeDIBSize(HDIB hDIB, int nWidth, int nHeight)
  624. {
  625.     LPBITMAPINFO lpbmi = NULL; 
  626.     LPSTR       lpSourceBits, lpTargetBits, lpResult; 
  627.     HDC  hDC = NULL, hSourceDC, hTargetDC; 
  628.     HBITMAP      hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; 
  629.     DWORD        dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize; 
  630. HDIB  hNewDIB;
  631. DWORD  dwSize;
  632. WaitCursorBegin();
  633. // Get DIB pointer
  634. if (! hDIB)
  635. {
  636. WaitCursorEnd();
  637. return NULL;
  638. }
  639. LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
  640. if (! lpSrcDIB)
  641. {
  642. WaitCursorEnd();
  643. return NULL;
  644. }
  645.     // Allocate and fill out a BITMAPINFO struct for the new DIB 
  646.     dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) + PaletteSize(lpSrcDIB); 
  647.     lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); 
  648. memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize);
  649.     lpbmi->bmiHeader.biWidth = nWidth; 
  650.     lpbmi->bmiHeader.biHeight = nHeight; 
  651.  
  652.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  653. hDC = GetDC( NULL ); 
  654.     hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
  655.     hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); 
  656.     hSourceDC = CreateCompatibleDC( hDC ); 
  657.     hTargetDC = CreateCompatibleDC( hDC ); 
  658.  
  659.     // Flip the bits on the source DIBSection to match the source DIB 
  660.     dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpSrcDIB->bmiHeader)); 
  661.     dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader)); 
  662.     memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); 
  663.     lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; 
  664.  
  665.     // Select DIBSections into DCs 
  666.     hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); 
  667.     hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
  668.  
  669. // put old bitmap in new bitmap 
  670.     SetStretchBltMode( hTargetDC, COLORONCOLOR ); 
  671.     StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY ); 
  672.  
  673.     // Clean up and delete the DCs 
  674.     SelectObject( hSourceDC, hOldSourceBitmap ); 
  675.     SelectObject( hTargetDC, hOldTargetBitmap ); 
  676.     DeleteDC( hSourceDC ); 
  677.     DeleteDC( hTargetDC ); 
  678.     ReleaseDC( NULL, hDC ); 
  679.  
  680.     // Flush the GDI batch, so we can play with the bits 
  681.     GdiFlush(); 
  682.  
  683.     // Allocate enough memory for the new CF_DIB, and copy bits 
  684. dwSize = dwTargetHeaderSize + dwTargetBitsSize;
  685. hNewDIB = GlobalAlloc(GHND, dwSize);
  686.     lpResult = (LPSTR)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); 
  687.     memcpy( lpResult, lpbmi, dwTargetHeaderSize ); 
  688.     memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize ); 
  689.  
  690.     // final cleanup 
  691.     DeleteObject( hTargetBitmap ); 
  692.     DeleteObject( hSourceBitmap ); 
  693.     free( lpbmi ); 
  694. GlobalUnlock(hDIB);
  695. GlobalUnlock(hNewDIB);
  696. WaitCursorEnd();
  697.  
  698.     return hNewDIB;
  699. }
  700. /************************************************************************* 
  701.  * 
  702.  * ChangeDIBCanvasSize() 
  703.  * 
  704.  * Parameters: 
  705.  * 
  706.  * HDIB hDIB  - handle of DIB to change
  707.  * int nWidth, int nHeight   - new size of DIB
  708.  * int nPosition  - position of source DIB in new DIB
  709.  * 
  710.  * Return Value: 
  711.  * 
  712.  * HDIB             - Handle to new DIB 
  713.  * 
  714.  * Description: 
  715.  * 
  716.  * This function change the canvas of DIB, and put source DIB in the
  717.  * specified position of new DIB (canvas), and return the changed DIB 
  718.  * in a new DIB handle, let the source DIB unchanged
  719.  * 
  720.  ************************************************************************/ 
  721. HDIB ChangeDIBCanvasSize(HDIB hDIB, int nWidth, int nHeight, int nPosition)
  722. {
  723.     LPBITMAPINFO lpbmi = NULL; 
  724.     LPSTR       lpSourceBits, lpTargetBits, lpResult; 
  725.     HDC  hDC = NULL, hSourceDC, hTargetDC; 
  726.     HBITMAP      hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap; 
  727.     DWORD        dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize; 
  728. HDIB  hNewDIB;
  729. DWORD  dwSize;
  730. WaitCursorBegin();
  731. // Get DIB pointer
  732. if (! hDIB)
  733. {
  734. WaitCursorEnd();
  735. return NULL;
  736. }
  737. LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
  738. if (! lpSrcDIB)
  739. {
  740. WaitCursorEnd();
  741. return NULL;
  742. }
  743.     // Allocate and fill out a BITMAPINFO struct for the new DIB 
  744.     dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) + PaletteSize(lpSrcDIB); 
  745.     lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize ); 
  746. memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize);
  747.     lpbmi->bmiHeader.biWidth = nWidth; 
  748.     lpbmi->bmiHeader.biHeight = nHeight; 
  749.  
  750.     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em 
  751. hDC = GetDC( NULL ); 
  752.     hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 ); 
  753.     hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 ); 
  754.     hSourceDC = CreateCompatibleDC( hDC ); 
  755.     hTargetDC = CreateCompatibleDC( hDC ); 
  756.  
  757.     // Flip the bits on the source DIBSection to match the source DIB 
  758.     dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpSrcDIB->bmiHeader)); 
  759.     dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader)); 
  760.     memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize ); 
  761.     lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize; 
  762.  
  763.     // Select DIBSections into DCs 
  764.     hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap ); 
  765.     hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap ); 
  766.  
  767. // old bitmap position in new bitmap
  768. int x = 0;
  769. int y = 0;
  770. int nOldWidth = lpSrcDIB->bmiHeader.biWidth;
  771. int nOldHeight = lpSrcDIB->bmiHeader.biHeight; 
  772.   switch (nPosition)
  773. {
  774. case LEFT_UP:
  775. x = 0;
  776. y = 0;
  777. break;
  778. case CENTER_UP:
  779. x = (nWidth-nOldWidth)/2;
  780. y = 0;
  781. break;
  782. case RIGHT_UP:
  783. x = nWidth-nOldWidth;
  784. y = 0;
  785. break;
  786. case LEFT_CENTER:
  787. x = 0;
  788. y = (nHeight-nOldHeight)/2;
  789. break;
  790. case CENTER_CENTER:
  791. x = (nWidth-nOldWidth)/2;
  792. y = (nHeight-nOldHeight)/2;
  793. break;
  794. case CENTER_RIGHT:
  795. x = nWidth-nOldWidth;
  796. y = (nHeight-nOldHeight)/2;
  797. break;
  798. case LEFT_DOWN:
  799. x = 0;
  800. y = nHeight-nOldHeight;
  801. break;
  802. case CENTER_DOWN:
  803. x = (nWidth-nOldWidth)/2;
  804. y = nHeight-nOldHeight;
  805. break;
  806. case RIGHT_DOWN:
  807. x = nWidth-nOldWidth;
  808. y = nHeight-nOldHeight;
  809. break;
  810. }
  811. // first clear the new bitmap with whitwness
  812. HBRUSH hBrush = CreateSolidBrush(RGB(255,255,255));
  813. HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
  814. HBRUSH hOldBrush = (HBRUSH)SelectObject(hTargetDC, hBrush);
  815. HPEN hOldPen = (HPEN)SelectObject(hTargetDC, hPen);
  816. Rectangle(hTargetDC, 0, 0, nWidth, nHeight);
  817. SelectObject(hTargetDC, hOldBrush);
  818. SelectObject(hTargetDC, hOldPen);
  819. // put old bitmap in new bitmap 
  820.     BitBlt(hTargetDC, x, y, nOldWidth, nOldHeight, hSourceDC, 0, 0, SRCCOPY); 
  821.  
  822.     // Clean up and delete the DCs 
  823.     SelectObject( hSourceDC, hOldSourceBitmap ); 
  824.     SelectObject( hTargetDC, hOldTargetBitmap ); 
  825.     DeleteDC( hSourceDC ); 
  826.     DeleteDC( hTargetDC ); 
  827.     ReleaseDC( NULL, hDC ); 
  828.  
  829.     // Flush the GDI batch, so we can play with the bits 
  830.     GdiFlush(); 
  831.  
  832.     // Allocate enough memory for the new CF_DIB, and copy bits 
  833. dwSize = dwTargetHeaderSize + dwTargetBitsSize;
  834. hNewDIB = GlobalAlloc(GHND, dwSize);
  835.     lpResult = (LPSTR)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize ); 
  836.     memcpy( lpResult, lpbmi, dwTargetHeaderSize ); 
  837.     memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize ); 
  838.  
  839.     // final cleanup 
  840.     DeleteObject( hTargetBitmap ); 
  841.     DeleteObject( hSourceBitmap ); 
  842.     free( lpbmi ); 
  843. GlobalUnlock(hDIB);
  844. GlobalUnlock(hNewDIB);
  845. WaitCursorEnd();
  846.  
  847.     return hNewDIB;
  848. }
  849. /************************************************************************* 
  850.  * 
  851.  * ColorQuantizeDIB() 
  852.  * 
  853.  * Parameters: 
  854.  * 
  855.  * HDIB hDIB        - handle to global memory with a DIB spec 
  856.  *                    in it followed by the DIB bits 
  857.  * 
  858.  * UINT nColorBits  - reduced DIB color bits
  859.  *
  860.  * UINT nMaxColors  - reduced DIB color number
  861.  *
  862.  * 
  863.  * Return Value: 
  864.  * 
  865.  * HDIB             - destination DIB handle
  866.  * 
  867.  * Description: 
  868.  *   Perform DIB color quatization
  869.  * 
  870.  ************************************************************************/ 
  871. HDIB ColorQuantizeDIB(HDIB hDIB, UINT nColorBits, UINT nMaxColors)
  872. {
  873. HPALETTE hPal = NULL;
  874. WaitCursorBegin();
  875. // color quantization palette
  876. LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
  877. hPal = CreateOctreePalette(lpDIB, nMaxColors, nColorBits);
  878. GlobalUnlock(hDIB);
  879. // convert DIB to new format
  880. HDIB hNewDIB = ConvertDIBFormat(hDIB, nColorBits, hPal);
  881. WaitCursorEnd();
  882. return hNewDIB;
  883. }
  884. /************************************************************************* 
  885.  * 
  886.  * ConvertToGrayscale() 
  887.  * 
  888.  * Parameters: 
  889.  * 
  890.  * HDIB hDIB        - handle to global memory with a DIB spec 
  891.  *                    in it followed by the DIB bits 
  892.  * 
  893.  * int nMethod      - method used to convert color to grayscale
  894.  *
  895.  * double fRedWeight    - weight of Red
  896.  *
  897.  * double fGreenWeight - weight of Green
  898.  *
  899.  * double fBlueWeight - weight of Blue
  900.  * 
  901.  * Return Value: 
  902.  * 
  903.  * HPALETTE         - handle of result grayscale palette
  904.  * 
  905.  * Description: 
  906.  *   Change DIB color table from color to grayscale
  907.  * 
  908.  ************************************************************************/ 
  909. HPALETTE ConvertToGrayscale(HDIB hDib, int nMethod, 
  910. double fRedWeight, double fGreenWeight, double fBlueWeight)
  911. {
  912. if (hDib == NULL)
  913. return NULL;
  914. BITMAPINFO* lpbi = (BITMAPINFO *)GlobalLock(hDib);
  915. if (! lpbi)
  916. return NULL;
  917. WaitCursorBegin();
  918. // get color number
  919. WORD wNumColors = DIBNumColors((LPSTR)lpbi);
  920. if (wNumColors == 0) // There is no palette
  921. {
  922. GlobalUnlock(hDib);
  923. // reduce colors to 256
  924. HDIB hNewDib = ColorQuantizeDIB(hDib, 8, 256);
  925. LPSTR lpDIB = (LPSTR)GlobalLock(hNewDib);
  926. if (! lpDIB)
  927. {
  928. WaitCursorEnd();
  929. return NULL;
  930. }
  931. DWORD dwSize = DIBlockSize(lpDIB);
  932. hDib = GlobalReAlloc(hDib, dwSize, 0);
  933. lpbi = (BITMAPINFO *)GlobalLock(hDib);
  934. CopyMemory((LPSTR)lpbi, (LPSTR)lpDIB, dwSize);
  935. GlobalUnlock(hNewDib);
  936. GlobalFree(hNewDib);
  937. }
  938. wNumColors = DIBNumColors((LPSTR)lpbi);
  939. BYTE GrayValue = 0;
  940. WORD i;
  941. switch (nMethod)
  942. {
  943. case MAXIMUM_GRAY:
  944. for (i=0; i<wNumColors; i++)
  945. {
  946. GrayValue = max(max(lpbi->bmiColors[i].rgbRed, 
  947. lpbi->bmiColors[i].rgbGreen),
  948. lpbi->bmiColors[i].rgbBlue);
  949. lpbi->bmiColors[i].rgbRed   =
  950. lpbi->bmiColors[i].rgbGreen =
  951. lpbi->bmiColors[i].rgbBlue  = GrayValue;
  952. }
  953. break;
  954. case MEAN_GRAY:
  955. for (i=0; i<wNumColors; i++)
  956. {
  957. GrayValue = min(255, 
  958. (lpbi->bmiColors[i].rgbRed + 
  959.  lpbi->bmiColors[i].rgbGreen +
  960.  lpbi->bmiColors[i].rgbBlue)/3);
  961. lpbi->bmiColors[i].rgbRed   =
  962. lpbi->bmiColors[i].rgbGreen =
  963. lpbi->bmiColors[i].rgbBlue  = GrayValue;
  964. }
  965. break;
  966. case WEIGHT_GRAY:
  967. for (i=0; i<wNumColors; i++)
  968. {
  969. GrayValue = min(255, 
  970. (BYTE)(lpbi->bmiColors[i].rgbRed*fRedWeight + 
  971. lpbi->bmiColors[i].rgbGreen*fGreenWeight +
  972. lpbi->bmiColors[i].rgbBlue*fBlueWeight));
  973. lpbi->bmiColors[i].rgbRed   =
  974. lpbi->bmiColors[i].rgbGreen =
  975. lpbi->bmiColors[i].rgbBlue  = GrayValue;
  976. }
  977. break;
  978. }
  979. GlobalUnlock(hDib);
  980. WaitCursorEnd();
  981. return CreateDIBPalette(hDib);
  982. }
  983. /************************************************************************* 
  984.  * 
  985.  * AdjustDIBColor() 
  986.  * 
  987.  * Parameters: 
  988.  * 
  989.  * HDIB hDIB        - handle to global memory with a DIB spec 
  990.  *                    in it followed by the DIB bits 
  991.  * 
  992.  * int nColorModel  - color model type, maybe RGB, HSI, HLS or CMYK
  993.  *
  994.  * int v1, v2, v3   - changed value to color value
  995.  *
  996.  * 
  997.  * Return Value: 
  998.  * 
  999.  * BOOL - TRUE is success, else FALSE
  1000.  * 
  1001.  * Description: 
  1002.  *   Adjust DIB color by RGB, CMYK, HSI, HLS color model 
  1003.  * 
  1004.  ************************************************************************/ 
  1005. BOOL AdjustDIBColor(HDIB hDib, int nColorModel, int v1, int v2, int v3)
  1006. {
  1007. BYTE r, g, b, c, m, y, k;
  1008. int  dr, dg, db, dc, dm, dy;
  1009. double dh, ds, dv, dl, h, s, v, l;
  1010. if (hDib == NULL)
  1011. return FALSE;
  1012. BITMAPINFO *bmi = (BITMAPINFO *)GlobalLock(hDib);
  1013. if (! bmi)
  1014. return FALSE;
  1015. WaitCursorBegin();
  1016. switch (nColorModel)
  1017. {
  1018. case RGB_COLOR:
  1019. dr = v1;
  1020. dg = v2;
  1021. db = v3;
  1022. break;
  1023. case CMYK_COLOR:
  1024. dc = v1;
  1025. dm = v2;
  1026. dy = v3;
  1027. break;
  1028. case HSI_COLOR:
  1029. if (v1 < 0)
  1030. v1 += 360;
  1031. dh = v1;
  1032. ds = v2;
  1033. dv = v3;
  1034. break;
  1035. case HLS_COLOR:
  1036. if (v1 < 0)
  1037. v1 += 360;
  1038. dh = v1;
  1039. dl = v2/100.0;
  1040. ds = v3/100.0;
  1041. break;
  1042. }
  1043. // get color number
  1044. WORD wNumColors = DIBNumColors((LPSTR)bmi);
  1045. if (wNumColors) // There is palette
  1046. {
  1047. WORD i;
  1048. switch (nColorModel)
  1049. {
  1050. case RGB_COLOR:
  1051. for (i=0; i<wNumColors; i++)
  1052. {
  1053. bmi->bmiColors[i].rgbRed = BOUND(bmi->bmiColors[i].rgbRed+dr, 0, 255);
  1054. bmi->bmiColors[i].rgbGreen = BOUND(bmi->bmiColors[i].rgbGreen+dg, 0, 255);
  1055. bmi->bmiColors[i].rgbBlue  = BOUND(bmi->bmiColors[i].rgbBlue+db, 0, 255);
  1056. }
  1057. break;
  1058. case CMYK_COLOR:
  1059. for (i=0; i<wNumColors; i++)
  1060. {
  1061. r = bmi->bmiColors[i].rgbRed;
  1062. g = bmi->bmiColors[i].rgbGreen;
  1063. b = bmi->bmiColors[i].rgbBlue;
  1064. RGBtoCMYK(r, g, b, &c, &m, &y, &k);
  1065. c += dc;
  1066. m += dm;
  1067. y += dy;
  1068. CMYKtoRGB(c, m, y, k, &r, &g, &b);
  1069. bmi->bmiColors[i].rgbRed   = r;
  1070. bmi->bmiColors[i].rgbGreen = g;
  1071. bmi->bmiColors[i].rgbBlue  = b;
  1072. }
  1073. break;
  1074. case HSI_COLOR:
  1075. for (i=0; i<wNumColors; i++)
  1076. {
  1077. r = bmi->bmiColors[i].rgbRed;
  1078. g = bmi->bmiColors[i].rgbGreen;
  1079. b = bmi->bmiColors[i].rgbBlue;
  1080. RGBtoHSI(r, g, b, &h, &s, &v);
  1081. h += dh;
  1082. s += ds;
  1083. v += dv;
  1084. HSItoRGB(h, s, v, &r, &g, &b);
  1085. bmi->bmiColors[i].rgbRed   = r;
  1086. bmi->bmiColors[i].rgbGreen = g;
  1087. bmi->bmiColors[i].rgbBlue  = b;
  1088. }
  1089. break;
  1090. case HLS_COLOR:
  1091. for (i=0; i<wNumColors; i++)
  1092. {
  1093. r = bmi->bmiColors[i].rgbRed;
  1094. g = bmi->bmiColors[i].rgbGreen;
  1095. b = bmi->bmiColors[i].rgbBlue;
  1096. RGBtoHLS(r, g, b, &h, &l, &s);
  1097. if (h != UNDEFINED)
  1098. h = BOUND(h+dh, 0.0, 360.0);
  1099. l = BOUND(l+dl, 0.0, 1.0);
  1100. s = BOUND(s+ds, 0.0, 1.0);
  1101. HLStoRGB(h, l, s, &r, &g, &b);
  1102. bmi->bmiColors[i].rgbRed   = r;
  1103. bmi->bmiColors[i].rgbGreen = g;
  1104. bmi->bmiColors[i].rgbBlue  = b;
  1105. }
  1106. break;
  1107. }
  1108. }
  1109. else // No palette
  1110. {
  1111. // bits position
  1112. LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)bmi;
  1113. LPSTR lpBits = (LPSTR)lpbi + lpbi->biSize;
  1114. int nDelta = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) - lpbi->biWidth*lpbi->biBitCount/8;
  1115. int nx, ny;
  1116. switch (nColorModel)
  1117. {
  1118. case RGB_COLOR:
  1119. for (ny=0; ny<lpbi->biHeight; ny++)
  1120. {
  1121. for (nx=0; nx<lpbi->biWidth; nx++)
  1122. {
  1123. b = (BYTE)*(lpBits);
  1124. g = (BYTE)*(lpBits+1);
  1125. r = (BYTE)*(lpBits+2);
  1126. *lpBits++ = BOUND(b+db, 0, 255);
  1127. *lpBits++ = BOUND(g+dg, 0, 255);
  1128. *lpBits++ = BOUND(r+dr, 0, 255);
  1129. }
  1130. lpBits += nDelta; 
  1131. }
  1132. break;
  1133. case CMYK_COLOR:
  1134. for (ny=0; ny<lpbi->biHeight; ny++)
  1135. {
  1136. for (nx=0; nx<lpbi->biWidth; nx++)
  1137. {
  1138. b = (BYTE)*(lpBits);
  1139. g = (BYTE)*(lpBits+1);
  1140. r = (BYTE)*(lpBits+2);
  1141. RGBtoCMYK(r, g, b, &c, &m, &y, &k);
  1142. c += dc;
  1143. m += dm;
  1144. y += dy;
  1145. CMYKtoRGB(c, m, y, k, &r, &g, &b);
  1146. *lpBits++ = b;
  1147. *lpBits++ = g;
  1148. *lpBits++ = r;
  1149. }
  1150. lpBits += nDelta; 
  1151. }
  1152. break;
  1153. case HSI_COLOR:
  1154. for (ny=0; ny<lpbi->biHeight; ny++)
  1155. {
  1156. for (nx=0; nx<lpbi->biWidth; nx++)
  1157. {
  1158. b = (BYTE)*(lpBits);
  1159. g = (BYTE)*(lpBits+1);
  1160. r = (BYTE)*(lpBits+2);
  1161. RGBtoHSI(r, g, b, &h, &s, &v);
  1162. h += dh;
  1163. s += ds;
  1164. v += dv;
  1165. HSItoRGB(h, s, v, &r, &g, &b);
  1166. *lpBits++ = b;
  1167. *lpBits++ = g;
  1168. *lpBits++ = r;
  1169. }
  1170. lpBits += nDelta; 
  1171. }
  1172. break;
  1173. case HLS_COLOR:
  1174. for (ny=0; ny<lpbi->biHeight; ny++)
  1175. {
  1176. for (nx=0; nx<lpbi->biWidth; nx++)
  1177. {
  1178. b = (BYTE)*(lpBits);
  1179. g = (BYTE)*(lpBits+1);
  1180. r = (BYTE)*(lpBits+2);
  1181. RGBtoHLS(r, g, b, &h, &l, &s);
  1182. if (h != UNDEFINED)
  1183. h = BOUND(h+dh, 0.0, 360.0);
  1184. l = BOUND(l+dl, 0.0, 1.0);
  1185. s = BOUND(s+ds, 0.0, 1.0);
  1186. HLStoRGB(h, l, s, &r, &g, &b);
  1187. *lpBits++ = b;
  1188. *lpBits++ = g;
  1189. *lpBits++ = r;
  1190. }
  1191. lpBits += nDelta; 
  1192. }
  1193. break;
  1194. }
  1195. }
  1196. GlobalUnlock(hDib);
  1197. WaitCursorEnd();
  1198. return TRUE;
  1199. }
  1200. /************************************************************************* 
  1201.  * 
  1202.  * SeparateRGBfromDIB() 
  1203.  * 
  1204.  * Parameters: 
  1205.  * 
  1206.  * HDIB hDIB        - handle to global memory with a DIB spec 
  1207.  *                    in it followed by the DIB bits 
  1208.  * 
  1209.  * int  nIndex      - index to specify the color to Separate from DIB
  1210.  *
  1211.  * 
  1212.  * Return Value: 
  1213.  * 
  1214.  * HDIB         - the handle of result DIB
  1215.  *
  1216.  * 
  1217.  * Description: 
  1218.  *   Separate DIB to R, G, B
  1219.  * 
  1220.  ************************************************************************/ 
  1221. HDIB SeparateRGBfromDIB(HDIB hDib, int nIndex)
  1222. {
  1223. if (hDib == NULL)
  1224. return NULL;
  1225. HDIB hNewDIB = CopyHandle(hDib);
  1226. if (hNewDIB == NULL)
  1227. return NULL;
  1228. BITMAPINFO *bmi = (BITMAPINFO *)GlobalLock(hNewDIB);
  1229. if (! bmi)
  1230. return NULL;
  1231. WaitCursorBegin();
  1232. // get color number
  1233. WORD wNumColors = DIBNumColors((LPSTR)bmi);
  1234. if (wNumColors) // There is palette
  1235. {
  1236. for (WORD i=0; i<wNumColors; i++)
  1237. {
  1238. switch (nIndex)
  1239. {
  1240. case SEPARATE_RED:
  1241.  bmi->bmiColors[i].rgbGreen = 0;
  1242.  bmi->bmiColors[i].rgbBlue = 0;
  1243.  break;
  1244. case SEPARATE_GREEN:
  1245.  bmi->bmiColors[i].rgbRed = 0;
  1246.  bmi->bmiColors[i].rgbBlue = 0;
  1247.  break;
  1248. case SEPARATE_BLUE:
  1249.  bmi->bmiColors[i].rgbRed = 0;
  1250.  bmi->bmiColors[i].rgbGreen = 0;
  1251.  break;
  1252. }
  1253. }
  1254. }
  1255. else // No palette
  1256. {
  1257. // bits position
  1258. LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)bmi;
  1259. LPSTR lpBits = (LPSTR)lpbi + lpbi->biSize;
  1260. int nDelta = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) - lpbi->biWidth*lpbi->biBitCount/8;
  1261. for (int ny=0; ny<lpbi->biHeight; ny++)
  1262. {
  1263. for (int nx=0; nx<lpbi->biWidth; nx++)
  1264. {
  1265. switch (nIndex)
  1266. {
  1267. case SEPARATE_RED:
  1268. *lpBits++ = 0;
  1269. *lpBits++ = 0;
  1270. lpBits++;
  1271.  break;
  1272. case SEPARATE_GREEN:
  1273. *lpBits++ = 0;
  1274. lpBits++;
  1275. *lpBits++ = 0;
  1276.  break;
  1277. case SEPARATE_BLUE:
  1278. lpBits++;
  1279. *lpBits++ = 0;
  1280. *lpBits++ = 0;
  1281.  break;
  1282. }
  1283. }
  1284. lpBits += nDelta; 
  1285. }
  1286. }
  1287. GlobalUnlock(hNewDIB);
  1288. WaitCursorEnd();
  1289. return hNewDIB;
  1290. }
  1291. /************************************************************************* 
  1292.  * 
  1293.  * FilteRGBfromDIB() 
  1294.  * 
  1295.  * Parameters: 
  1296.  * 
  1297.  * HDIB hDIB        - handle to global memory with a DIB spec 
  1298.  *                    in it followed by the DIB bits 
  1299.  * 
  1300.  * int  nIndex      - index to specify the color to filte from DIB
  1301.  *
  1302.  * 
  1303.  * Return Value: 
  1304.  * 
  1305.  * HDIB         - the handle of result DIB
  1306.  *
  1307.  * 
  1308.  * Description: 
  1309.  *   Filte DIB to R, G, B
  1310.  * 
  1311.  ************************************************************************/ 
  1312. HDIB FilteRGBfromDIB(HDIB hDib, int nIndex)
  1313. {
  1314. if (hDib == NULL)
  1315. return NULL;
  1316. HDIB hNewDIB = CopyHandle(hDib);
  1317. if (hNewDIB == NULL)
  1318. return NULL;
  1319. BITMAPINFO *bmi = (BITMAPINFO *)GlobalLock(hNewDIB);
  1320. if (! bmi)
  1321. return NULL;
  1322. WaitCursorBegin();
  1323. // get color number
  1324. WORD wNumColors = DIBNumColors((LPSTR)bmi);
  1325. if (wNumColors) // There is palette
  1326. {
  1327. for (WORD i=0; i<wNumColors; i++)
  1328. {
  1329. switch (nIndex)
  1330. {
  1331. case FILTE_RED:
  1332.  bmi->bmiColors[i].rgbRed = 0;
  1333.  break;
  1334. case FILTE_GREEN:
  1335.  bmi->bmiColors[i].rgbGreen = 0;
  1336.  break;
  1337. case FILTE_BLUE:
  1338.  bmi->bmiColors[i].rgbBlue = 0;
  1339.  break;
  1340. }
  1341. }
  1342. }
  1343. else // No palette
  1344. {
  1345. // bits position
  1346. LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)bmi;
  1347. LPSTR lpBits = (LPSTR)lpbi + lpbi->biSize;
  1348. int nDelta = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) - lpbi->biWidth*lpbi->biBitCount/8;
  1349. for (int ny=0; ny<lpbi->biHeight; ny++)
  1350. {
  1351. for (int nx=0; nx<lpbi->biWidth; nx++)
  1352. {
  1353. switch (nIndex)
  1354. {
  1355. case FILTE_RED:
  1356. lpBits++;
  1357. lpBits++;
  1358. *lpBits++ = 0;
  1359.  break;
  1360. case FILTE_GREEN:
  1361. lpBits++;
  1362. *lpBits++ = 0;
  1363. lpBits++;
  1364.  break;
  1365. case FILTE_BLUE:
  1366. *lpBits++ = 0;
  1367. lpBits++;
  1368. lpBits++;
  1369.  break;
  1370. }
  1371. }
  1372. lpBits += nDelta; 
  1373. }
  1374. }
  1375. GlobalUnlock(hNewDIB);
  1376. WaitCursorEnd();
  1377. return hNewDIB;
  1378. }
  1379. /************************************************************************* 
  1380.  * 
  1381.  * AdjustDIBBrightness() 
  1382.  * 
  1383.  * Parameters: 
  1384.  * 
  1385.  * HDIB hDIB        - handle to global memory with a DIB spec 
  1386.  *                    in it followed by the DIB bits 
  1387.  * 
  1388.  * int v     - changed value to color value
  1389.  *
  1390.  * 
  1391.  * Return Value: 
  1392.  * 
  1393.  * BOOL - TRUE is success, else FALSE
  1394.  * 
  1395.  * Description: 
  1396.  *   Adjust DIB brightness
  1397.  * 
  1398.  ************************************************************************/ 
  1399. BOOL AdjustDIBBrightness(HDIB hDib, int v)
  1400. {
  1401. if (hDib == NULL)
  1402. return FALSE;
  1403. BITMAPINFO *bmi = (BITMAPINFO *)GlobalLock(hDib);
  1404. if (! bmi)
  1405. return FALSE;
  1406. WaitCursorBegin();
  1407. // get color number
  1408. WORD wNumColors = DIBNumColors((LPSTR)bmi);
  1409. if (wNumColors) // There is palette
  1410. {
  1411. for (WORD i=0; i<wNumColors; i++)
  1412. {
  1413. ChangeBrightness(v, 
  1414.  &(bmi->bmiColors[i].rgbRed),
  1415.  &(bmi->bmiColors[i].rgbGreen),
  1416.  &(bmi->bmiColors[i].rgbBlue));
  1417. }
  1418. }
  1419. else // No palette
  1420. {
  1421. // bits position
  1422. LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)bmi;
  1423. LPSTR lpBits = (LPSTR)lpbi + lpbi->biSize;
  1424. int nDelta = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) - lpbi->biWidth*lpbi->biBitCount/8;
  1425. BYTE r, g, b;
  1426. for (int ny=0; ny<lpbi->biHeight; ny++)
  1427. {
  1428. for (int nx=0; nx<lpbi->biWidth; nx++)
  1429. {
  1430. b = (BYTE)*(lpBits);
  1431. g = (BYTE)*(lpBits+1);
  1432. r = (BYTE)*(lpBits+2);
  1433. ChangeBrightness(v, &r, &g, &b);
  1434. *lpBits++ = b;
  1435. *lpBits++ = g;
  1436. *lpBits++ = r;
  1437. }
  1438. lpBits += nDelta; 
  1439. }
  1440. }
  1441. GlobalUnlock(hDib);
  1442. WaitCursorEnd();
  1443. return TRUE;
  1444. }
  1445. /************************************************************************* 
  1446.  * 
  1447.  * AdjustDIBContrast() 
  1448.  * 
  1449.  * Parameters: 
  1450.  * 
  1451.  * HDIB hDIB        - handle to global memory with a DIB spec 
  1452.  *                    in it followed by the DIB bits 
  1453.  * 
  1454.  * int v     - changed value to color value
  1455.  *
  1456.  * 
  1457.  * Return Value: 
  1458.  * 
  1459.  * BOOL - TRUE is success, else FALSE
  1460.  * 
  1461.  * Description: 
  1462.  *   Adjust DIB contrast
  1463.  * 
  1464.  ************************************************************************/ 
  1465. BOOL AdjustDIBContrast(HDIB hDib, int v)
  1466. {
  1467. if (hDib == NULL)
  1468. return FALSE;
  1469. BITMAPINFO *bmi = (BITMAPINFO *)GlobalLock(hDib);
  1470. if (! bmi)
  1471. return FALSE;
  1472. WaitCursorBegin();
  1473. // get color number
  1474. WORD wNumColors = DIBNumColors((LPSTR)bmi);
  1475. if (wNumColors) // There is palette
  1476. {
  1477. for (WORD i=0; i<wNumColors; i++)
  1478. {
  1479. ChangeContrast(v, 
  1480.    &(bmi->bmiColors[i].rgbRed),
  1481.    &(bmi->bmiColors[i].rgbGreen),
  1482.    &(bmi->bmiColors[i].rgbBlue));
  1483. }
  1484. }
  1485. else // No palette
  1486. {
  1487. // bits position
  1488. LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)bmi;
  1489. LPSTR lpBits = (LPSTR)lpbi + lpbi->biSize;
  1490. int nDelta = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) - lpbi->biWidth*lpbi->biBitCount/8;
  1491. BYTE r, g, b;
  1492. for (int ny=0; ny<lpbi->biHeight; ny++)
  1493. {
  1494. for (int nx=0; nx<lpbi->biWidth; nx++)
  1495. {
  1496. b = (BYTE)*(lpBits);
  1497. g = (BYTE)*(lpBits+1);
  1498. r = (BYTE)*(lpBits+2);
  1499. ChangeContrast(v, &r, &g, &b);
  1500. *lpBits++ = b;
  1501. *lpBits++ = g;
  1502. *lpBits++ = r;
  1503. }
  1504. lpBits += nDelta; 
  1505. }
  1506. }
  1507. GlobalUnlock(hDib);
  1508. WaitCursorEnd();
  1509. return TRUE;
  1510. }
  1511. /************************************************************************* 
  1512.  * 
  1513.  * HSItoRGB() 
  1514.  * 
  1515.  * Parameters: 
  1516.  * 
  1517.  * h, s, i        - input h, s, i value
  1518.  * 
  1519.  * r, g, b        - output r, g, b value
  1520.  *
  1521.  * 
  1522.  * Return Value:  none
  1523.  * 
  1524.  * 
  1525.  * Description: 
  1526.  *   Change HSI color to RGB color
  1527.  * 
  1528.  ************************************************************************/ 
  1529. void HSItoRGB(double h, double s, double i, BYTE *r, BYTE *g, BYTE *b)
  1530. {
  1531. double V1 = s * cos(h);
  1532. double V2 = s * sin(h);
  1533. int iR = (int)( 0.816496*V2 + 0.57735*i);
  1534. int iG = (int)( 0.7071  *V1 - 0.40824*V2 + 0.57735*i);
  1535. int iB = (int)(-0.7071  *V1 - 0.40824*V2 + 0.57735*i);
  1536. *r = BOUND(iR, 0, 255);
  1537. *g = BOUND(iG, 0, 255);
  1538. *b = BOUND(iB, 0, 255);
  1539. }
  1540. /************************************************************************* 
  1541.  * 
  1542.  * RGBtoHSI() 
  1543.  * 
  1544.  * Parameters: 
  1545.  * 
  1546.  * r, g, b        - input r, g, b value
  1547.  * 
  1548.  * h, s, i        - output h, s, i value
  1549.  *
  1550.  * 
  1551.  * Return Value:  none
  1552.  * 
  1553.  * 
  1554.  * Description: 
  1555.  *   Change RGB color to HSI color
  1556.  * 
  1557.  ************************************************************************/ 
  1558. void RGBtoHSI(BYTE r, BYTE g, BYTE b, double *h, double *s, double *i)
  1559. {
  1560. double V1 = 0.7071*((double)g-(double)b);
  1561. double V2 = 0.816496*(double)r-0.40824*((double)g+(double)b);
  1562. *h = atan2(V1, V2);
  1563. *s = sqrt(V1*V1+V2*V2);
  1564. *i = 0.57735*((double)r+(double)g+(double)b);
  1565. }
  1566. // local function used in HLStoRGB
  1567. double Value(double n1, double n2, double hue)
  1568. {
  1569. if (hue > 360.0)
  1570. hue -= 360.0;
  1571. else if (hue < 0.0)
  1572. hue += 360.0;
  1573. if (hue < 60.0)
  1574. return (n1+(n2-n1)*hue/60.0);
  1575. else if (hue < 180.0)
  1576. return n2;
  1577. else if (hue < 240.0)
  1578. return (n1+(n2-n1)*(240.0-hue)/60.0);
  1579. else
  1580. return n1;
  1581. }
  1582. /************************************************************************* 
  1583.  * 
  1584.  * HLStoRGB() 
  1585.  * 
  1586.  * Parameters: 
  1587.  * 
  1588.  * h, l, s        - input h, l, s value
  1589.  * 
  1590.  * r, g, b        - output r, g, b value
  1591.  *
  1592.  * 
  1593.  * Return Value:  none
  1594.  * 
  1595.  * 
  1596.  * Description: 
  1597.  *   Change HLS color to RGB color
  1598.  * 
  1599.  ************************************************************************/ 
  1600. void HLStoRGB(double h, double l, double s, BYTE *r, BYTE *g, BYTE *b)
  1601. {
  1602. double m1, m2;
  1603. double R, G, B;
  1604. if (l <= 0.5)
  1605. m2 = l*(1.0+s);
  1606. else
  1607. m2 = l+s-l*s;
  1608. m1 = 2.0*l-m2;
  1609. if (s == 0)
  1610. {
  1611. if (h == UNDEFINED)
  1612. R = G = B = l;
  1613. else // error!!
  1614. R = G = B = 0.0;
  1615. }
  1616. else
  1617. {
  1618. R = Value(m1, m2, h+120.0);
  1619. G = Value(m1, m2, h);
  1620. B = Value(m1, m2, h-120.0);
  1621. }
  1622. int iR = (int)(R*255.0);
  1623. int iG = (int)(G*255.0);
  1624. int iB = (int)(B*255.0);
  1625. *r = (BYTE)BOUND(iR, 0, 255);
  1626. *g = (BYTE)BOUND(iG, 0, 255);
  1627. *b = (BYTE)BOUND(iB, 0, 255);
  1628. }
  1629. /************************************************************************* 
  1630.  * 
  1631.  * RGBtoHLS() 
  1632.  * 
  1633.  * Parameters: 
  1634.  * 
  1635.  * r, g, b        - input r, g, b value
  1636.  * 
  1637.  * h, l, s        - output h, l, s value
  1638.  *
  1639.  * 
  1640.  * Return Value:  none
  1641.  * 
  1642.  * 
  1643.  * Description: 
  1644.  *   Change RGB color to HLS color
  1645.  * 
  1646.  ************************************************************************/ 
  1647. void RGBtoHLS(BYTE r, BYTE g, BYTE b, double *h, double *l, double *s)
  1648. {
  1649. double mx, mn, delta;
  1650. double R, G, B;
  1651. R = (double)r/255.0;
  1652. G = (double)g/255.0;
  1653. B = (double)b/255.0;
  1654. mx = max(R, max(G, B));
  1655. mn = min(R, min(G, B));
  1656. *l = (mx+mn)/2.0;
  1657. if (mx == mn)
  1658. {
  1659. *s = 0.0;
  1660. *h = UNDEFINED; // undefined!
  1661. }
  1662. else
  1663. {
  1664. delta = mx-mn;
  1665. if (*l < 0.5)
  1666. *s = delta/(mx+mn);
  1667. else
  1668. *s = delta/(2.0-mx-mn);
  1669. if (R == mx)
  1670. *h = (G-B)/delta;
  1671. else if (G == mx)
  1672. *h = 2.0+(B-R)/delta;
  1673. else if (B == mx)
  1674. *h = 4.0+(R-G)/delta;
  1675. *h *= 60.0;
  1676. if (*h < 0.0)
  1677. *h += 360.0;
  1678. else if (*h > 360.0)
  1679. *h -= 360.0;
  1680. }
  1681. }
  1682. /************************************************************************* 
  1683.  * 
  1684.  * CMYKtoRGB() 
  1685.  * 
  1686.  * Parameters: 
  1687.  * 
  1688.  * c, m, y, k     - input c, m, y, k value
  1689.  * 
  1690.  * r, g, b        - output r, g, b value
  1691.  *
  1692.  * 
  1693.  * Return Value:  none
  1694.  * 
  1695.  * 
  1696.  * Description: 
  1697.  *   Change CMYK color to RGB color
  1698.  * 
  1699.  ************************************************************************/ 
  1700. void CMYKtoRGB(BYTE c, BYTE m, BYTE y, BYTE k, BYTE *r, BYTE *g, BYTE *b)
  1701. {
  1702. c += k;
  1703. m += k;
  1704. y += k;
  1705. *r = 255 - c;
  1706. *g = 255 - m;
  1707. *b = 255 - y;
  1708. }
  1709. /************************************************************************* 
  1710.  * 
  1711.  * RGBtoCMYK() 
  1712.  * 
  1713.  * Parameters: 
  1714.  * 
  1715.  * r, g, b        - input r, g, b value
  1716.  * 
  1717.  * c, m, y, k     - output c, m, y, k value
  1718.  *
  1719.  * 
  1720.  * Return Value:  none
  1721.  * 
  1722.  * 
  1723.  * Description: 
  1724.  *   Change RGB color to CMYK color
  1725.  * 
  1726.  ************************************************************************/ 
  1727. void RGBtoCMYK(BYTE r, BYTE g, BYTE b, BYTE *c, BYTE *m, BYTE *y, BYTE *k)
  1728. {
  1729. *c = 255 - r;
  1730. *m = 255 - g;
  1731. *y = 255 - b;
  1732. *k = min(*c, min(*m, *y));
  1733. *c -= *k;
  1734. *m -= *k;
  1735. *y -= *k;
  1736. }
  1737. // IncreaseContrast 
  1738. void IncreaseContrast(BYTE *pByte, const int Low, const int High, const float Grad)
  1739.     if (*pByte <= Low) 
  1740.         *pByte = 0; 
  1741.     else if ((Low < *pByte) && (*pByte <  High))
  1742. *pByte = (BYTE)( (*pByte - Low) / Grad); 
  1743.     else // pElem->rgbGreen >= High 
  1744.         *pByte = 255; 
  1745. }
  1746.  // DecreaseContrast 
  1747. void DecreaseContrast(BYTE *pByte, const int Level, const float Grad)
  1748.     ASSERT(pByte); 
  1749.     ASSERT(Grad != 0.0); 
  1750.     *pByte = (BYTE) ( ((int) (*pByte / Grad)) - Level); 
  1751. }
  1752. /************************************************************************* 
  1753.  * 
  1754.  * ChangeContrast() 
  1755.  * 
  1756.  * Parameters: 
  1757.  * 
  1758.  * int nDelta     - delta value to R, G, B
  1759.  *
  1760.  * r, g, b        - r, g, b value to change
  1761.  * 
  1762.  * 
  1763.  * Return Value:  none
  1764.  * 
  1765.  * 
  1766.  * Description: 
  1767.  *   Change contrast
  1768.  * 
  1769.  ************************************************************************/ 
  1770. void ChangeContrast(int nDelta, BYTE *r, BYTE *g, BYTE *b)
  1771. {
  1772. if (nDelta >= 0)
  1773. {
  1774.         int Low  = 0 + nDelta; 
  1775.         int High = 255 - nDelta; 
  1776. float Grad= ((float)(High - Low)) / 255; 
  1777.     IncreaseContrast(r, Low, High, Grad); 
  1778. IncreaseContrast(g, Low, High, Grad); 
  1779. IncreaseContrast(b, Low, High, Grad); 
  1780. }
  1781. else
  1782. {
  1783.         float Grad = 255 / (255 + (float)nDelta + (float)nDelta); 
  1784.     DecreaseContrast(r, nDelta, Grad); 
  1785. DecreaseContrast(g, nDelta, Grad); 
  1786. DecreaseContrast(b, nDelta, Grad); 
  1787. }
  1788. }
  1789. /************************************************************************* 
  1790.  * 
  1791.  * ChangeBrightness() 
  1792.  * 
  1793.  * Parameters: 
  1794.  * 
  1795.  * int nDelta     - delta value to R, G, B
  1796.  *
  1797.  * r, g, b        - r, g, b value to change
  1798.  * 
  1799.  * 
  1800.  * Return Value:  none
  1801.  * 
  1802.  * 
  1803.  * Description: 
  1804.  *   Change brightness
  1805.  * 
  1806.  ************************************************************************/ 
  1807. void ChangeBrightness(int nDelta, BYTE *r, BYTE *g, BYTE *b)
  1808. {
  1809. int R = *r + nDelta;
  1810. int G = *g + nDelta;
  1811. int B = *b + nDelta;
  1812. *r = (BYTE)BOUND(R, 0, 255);
  1813. *g = (BYTE)BOUND(G, 0, 255);
  1814. *b = (BYTE)BOUND(B, 0, 255);
  1815. }
  1816. ///////////////////// local used only !!! /////////////////////////////
  1817. // macros used to dither
  1818. #define ALIGN_DWORD(x) (((x)+3)/4 * 4)  // Double word alignment macro
  1819. // Macros used to facilitate RGB pixel access for dithering
  1820. #define GetRGBPixel(Addr, Red, Green, Blue)
  1821.   Blue  = (int) *(Addr);
  1822.   Green = (int) *(Addr+1);
  1823.   Red   = (int) *(Addr+2);
  1824. #define PutRGBPixel(Addr, Red, Green, Blue)
  1825.   Red = (Red<0)   ? 0 : Red;        
  1826.   Red = (Red>255) ? 255 : Red;      
  1827.   Green = (Green<0)   ? 0 : Green;  
  1828.   Green = (Green>255) ? 255 : Green;
  1829.   Blue = (Blue<0)   ? 0 : Blue;     
  1830.   Blue = (Blue>255) ? 255 : Blue;   
  1831.   *(Addr)   = (BYTE)Blue;           
  1832.   *(Addr+1) = (BYTE)Green;          
  1833.   *(Addr+2) = (BYTE)Red;
  1834. // This is the palette with which all true color images will be
  1835. // displayed when hardware support is unavailable.
  1836. typedef struct  
  1837. {
  1838.   BYTE Red;
  1839.   BYTE Green;
  1840.   BYTE Blue;
  1841. } RGBCOLOR;
  1842. RGBCOLOR DitherPalette[256] = 
  1843. {
  1844.      {0,   0,   0},   {0,   0,  85},   {0,   0, 170},  {0,   0, 255},
  1845.      {0,  36,   0},   {0,  36,  85},   {0,  36, 170},  {0,  36, 255},
  1846.      {0,  73,   0},   {0,  73,  85},   {0,  73, 170},  {0,  73, 255},
  1847.      {0, 109,   0},   {0, 109,  85},   {0, 109, 170},  {0, 109, 255},
  1848.      {0, 146,   0},   {0, 146,  85},   {0, 146, 170},  {0, 146, 255},
  1849.      {0, 182,   0},   {0, 182,  85},   {0, 182, 170},  {0, 182, 255},
  1850.      {0, 219,   0},   {0, 219,  85},   {0, 219, 170},  {0, 219, 255},
  1851.      {0, 255,   0},   {0, 255,  85},   {0, 255, 170},  {0, 255, 255},
  1852.     {36,   0,   0},  {36,   0,  85},  {36,   0, 170}, {36,   0, 255},
  1853.     {36,  36,   0},  {36,  36,  85},  {36,  36, 170}, {36,  36, 255},
  1854.     {36,  73,   0},  {36,  73,  85},  {36,  73, 170}, {36,  73, 255},
  1855.     {36, 109,   0},  {36, 109,  85},  {36, 109, 170}, {36, 109, 255},
  1856.     {36, 146,   0},  {36, 146,  85},  {36, 146, 170}, {36, 146, 255},
  1857.     {36, 182,   0},  {36, 182,  85},  {36, 182, 170}, {36, 182, 255},
  1858.     {36, 219,   0},  {36, 219,  85},  {36, 219, 170}, {36, 219, 255},
  1859.     {36, 255,   0},  {36, 255,  85},  {36, 255, 170}, {36, 255, 255},
  1860.     {73,   0,   0},  {73,   0,  85},  {73,   0, 170}, {73,   0, 255},
  1861.     {73,  36,   0},  {73,  36,  85},  {73,  36, 170}, {73,  36, 255},
  1862.     {73,  73,   0},  {73,  73,  85},  {73,  73, 170}, {73,  73, 255},
  1863.     {73, 109,   0},  {73, 109,  85},  {73, 109, 170}, {73, 109, 255},
  1864.     {73, 146,   0},  {73, 146,  85},  {73, 146, 170}, {73, 146, 255},
  1865.     {73, 182,   0},  {73, 182,  85},  {73, 182, 170}, {73, 182, 255},
  1866.     {73, 219,   0},  {73, 219,  85},  {73, 219, 170}, {73, 219, 255},
  1867.     {73, 255,   0},  {73, 255,  85},  {73, 255, 170}, {73, 255, 255},
  1868.   {109,   0,   0}, {109,   0,  85}, {109,   0, 170}, {109,   0, 255},
  1869.   {109,  36,   0}, {109,  36,  85}, {109,  36, 170}, {109,  36, 255},
  1870.   {109,  73,   0}, {109,  73,  85}, {109,  73, 170}, {109,  73, 255},
  1871.   {109, 109,   0}, {109, 109,  85}, {109, 109, 170}, {109, 109, 255},
  1872.   {109, 146,   0}, {109, 146,  85}, {109, 146, 170}, {109, 146, 255},
  1873.   {109, 182,   0}, {109, 182,  85}, {109, 182, 170}, {109, 182, 255},
  1874.   {109, 219,   0}, {109, 219,  85}, {109, 219, 170}, {109, 219, 255},
  1875.   {109, 255,   0}, {109, 255,  85}, {109, 255, 170}, {109, 255, 255},
  1876.   {146,   0,   0}, {146,   0,  85}, {146,   0, 170}, {146,   0, 255},
  1877.   {146,  36,   0}, {146,  36,  85}, {146,  36, 170}, {146,  36, 255},
  1878.   {146,  73,   0}, {146,  73,  85}, {146,  73, 170}, {146,  73, 255},
  1879.   {146, 109,   0}, {146, 109,  85}, {146, 109, 170}, {146, 109, 255},
  1880.   {146, 146,   0}, {146, 146,  85}, {146, 146, 170}, {146, 146, 255},
  1881.   {146, 182,   0}, {146, 182,  85}, {146, 182, 170}, {146, 182, 255},
  1882.   {146, 219,   0}, {146, 219,  85}, {146, 219, 170}, {146, 219, 255},
  1883.   {146, 255,   0}, {146, 255,  85}, {146, 255, 170}, {146, 255, 255},
  1884.   {182,   0,   0}, {182,   0,  85}, {182,   0, 170}, {182,   0, 255},
  1885.   {182,  36,   0}, {182,  36,  85}, {182,  36, 170}, {182,  36, 255},
  1886.   {182,  73,   0}, {182,  73,  85}, {182,  73, 170}, {182,  73, 255},
  1887.   {182, 109,   0}, {182, 109,  85}, {182, 109, 170}, {182, 109, 255},
  1888.   {182, 146,   0}, {182, 146,  85}, {182, 146, 170}, {182, 146, 255},
  1889.   {182, 182,   0}, {182, 182,  85}, {182, 182, 170}, {182, 182, 255},
  1890.   {182, 219,   0}, {182, 219,  85}, {182, 219, 170}, {182, 219, 255},
  1891.   {182, 255,   0}, {182, 255,  85}, {182, 255, 170}, {182, 255, 255},
  1892.   {219,   0,   0}, {219,   0,  85}, {219,   0, 170}, {219,   0, 255},
  1893.   {219,  36,   0}, {219,  36,  85}, {219,  36, 170}, {219,  36, 255},
  1894.   {219,  73,   0}, {219,  73,  85}, {219,  73, 170}, {219,  73, 255},
  1895.   {219, 109,   0}, {219, 109,  85}, {219, 109, 170}, {219, 109, 255},
  1896.   {219, 146,   0}, {219, 146,  85}, {219, 146, 170}, {219, 146, 255},
  1897.   {219, 182,   0}, {219, 182,  85}, {219, 182, 170}, {219, 182, 255},
  1898.   {219, 219,   0}, {219, 219,  85}, {219, 219, 170}, {219, 219, 255},
  1899.   {219, 255,   0}, {219, 255,  85}, {219, 255, 170}, {219, 255, 255},
  1900.   {255,   0,   0}, {255,   0,  85}, {255,   0, 170}, {255,   0, 255},
  1901.   {255,  36,   0}, {255,  36,  85}, {255,  36, 170}, {255,  36, 255},
  1902.   {255,  73,   0}, {255,  73,  85}, {255,  73, 170}, {255,  73, 255},
  1903.   {255, 109,   0}, {255, 109,  85}, {255, 109, 170}, {255, 109, 255},
  1904.   {255, 146,   0}, {255, 146,  85}, {255, 146, 170}, {255, 146, 255},
  1905.   {255, 182,   0}, {255, 182,  85}, {255, 182, 170}, {255, 182, 255},
  1906.   {255, 219,   0}, {255, 219,  85}, {255, 219, 170}, {255, 219, 255},
  1907.   {255, 255,   0}, {255, 255,  85}, {255, 255, 170}, {255, 255, 255}
  1908. };
  1909. // Define temporary vars as global, try to speedup...
  1910. int  TRed, TGreen, TBlue;
  1911. int  RedError, GreenError, BlueError;
  1912. BYTE PaletteIndex;
  1913. int  BlueOffset;
  1914. LPSTR PixelAddr;
  1915. LPSTR RPixelAddr;
  1916. LPSTR DPixelAddr;
  1917. // Dither a single row of image data
  1918. void DitherLine(WORD Width, LPSTR pLine1, LPSTR pLine2) 
  1919. {
  1920. for (register WORD Pixel=0; Pixel < Width; Pixel++) 
  1921. {
  1922. // Get the pixel of interest for the dither
  1923. PixelAddr = pLine1 + (Pixel * 3);
  1924. GetRGBPixel(PixelAddr, TRed, TGreen, TBlue);
  1925. // Determine which blue entry from palette to use
  1926. BlueOffset = (TBlue/85);
  1927. if ((TBlue - (BlueOffset * 85)) > 43)
  1928. BlueOffset += 1;
  1929. // Calculate palette entry address from color
  1930. // PaletteIndex = ((TRed/32)*32) + ((TGreen/32)*4) + BlueOffset;
  1931. // For speed we will calculate the color index as follows
  1932. PaletteIndex = (TRed & 0xE0) + ((TGreen >> 5) << 2) + BlueOffset;
  1933. // Store the palette back into the same buffer
  1934. *(pLine1 + Pixel) = PaletteIndex;
  1935. /*
  1936. Pixel is set, now distribute the error to adjacent pixels
  1937. using a modified version of the Floyd-Steinberg algorithm.
  1938. In this implementation the error is distributed as follows
  1939.    Pixel
  1940.   o 1/2->o
  1941.  1/4 |
  1942.  o   
  1943. The algorithm is modified to increase performance.
  1944. */
  1945. // Calculate errors between the desired color and color used
  1946. // for this pixel. Actual error / 4. Use  pointers for speed.
  1947. BYTE  *pColor = (BYTE  *) &DitherPalette[PaletteIndex];  // Ptr to color
  1948. RedError   = (TRed   - *(pColor))   >> 2;
  1949. GreenError = (TGreen - *(pColor+1)) >> 2;
  1950. BlueError  = (TBlue  - *(pColor+2)) >> 2;
  1951. // Do the pixel directly below target pixel
  1952. DPixelAddr  = pLine2 + (Pixel * 3);
  1953. GetRGBPixel(DPixelAddr, TRed, TGreen, TBlue);
  1954. TRed   += RedError;                // 1/4 error
  1955. TGreen += GreenError;
  1956. TBlue  += BlueError;
  1957. PutRGBPixel(DPixelAddr, TRed, TGreen, TBlue);
  1958. // Do the pixel directly to the right
  1959. if (Pixel != Width - 1)  
  1960. {
  1961. RPixelAddr  = PixelAddr + 3;
  1962. GetRGBPixel(RPixelAddr, TRed, TGreen, TBlue);
  1963. TRed   += RedError   + RedError;   // 1/2 error
  1964. TGreen += GreenError + GreenError;
  1965. TBlue  += BlueError  + BlueError;
  1966. PutRGBPixel(RPixelAddr, TRed, TGreen, TBlue);
  1967. }
  1968. }
  1969. }
  1970. // This function dithers the image contained in this object. It returns
  1971. // a handle to a global memory block containing the dithered data.
  1972. HGLOBAL DitherImage(LPSTR lpImageData, WORD Width, WORD Height) 
  1973. {
  1974. // Calculate width in bytes of a row of RGB data
  1975. WORD BytesPerLine = ALIGN_DWORD(Width * 3);   // Source 24 BPP image
  1976. // Calculate width in bytes of a row of palettized data
  1977. WORD BytesPerLineDest = ALIGN_DWORD(Width);   // Dest 8 BPP image
  1978. // Allocate two lines of RGB buffer for dithering
  1979. HLOCAL hLine1Buffer = LocalAlloc(LMEM_MOVEABLE, BytesPerLine);
  1980. if (!hLine1Buffer) 
  1981. return NULL;
  1982. HLOCAL hLine2Buffer = LocalAlloc(LMEM_MOVEABLE, BytesPerLine);
  1983. if (!hLine2Buffer) 
  1984. {
  1985. LocalFree(hLine1Buffer);
  1986. return NULL;
  1987. }
  1988. // Allocate the destination dither buffer
  1989. HGLOBAL hMem = GlobalAlloc(GHND, (DWORD) BytesPerLineDest * Height);
  1990. if (!hMem) 
  1991. {
  1992. LocalFree(hLine1Buffer);
  1993. LocalFree(hLine2Buffer);
  1994. return NULL;
  1995. }
  1996. // Now lock the pointers for access
  1997. LPSTR Line1Buffer = (LPSTR) LocalLock(hLine1Buffer);
  1998. LPSTR Line2Buffer = (LPSTR) LocalLock(hLine2Buffer);
  1999. LPSTR lpDitheredRasterData = (LPSTR) GlobalLock(hMem);
  2000. // Move the first two lines of the source image to dither buffers
  2001. memcpy(Line1Buffer, lpImageData, BytesPerLine);
  2002. memcpy(Line2Buffer, lpImageData + BytesPerLine, BytesPerLine);
  2003. for (register WORD Row = 2; Row < Height; Row++) 
  2004. {
  2005. DitherLine(Width, Line1Buffer, Line2Buffer);
  2006. // Copy the dithered data in Line1Buffer to destination
  2007. memcpy(lpDitheredRasterData  + ((Row-2) * (DWORD) BytesPerLineDest),
  2008. Line1Buffer, BytesPerLineDest);
  2009. // Copy Line2Buffer to Line1Buffer so it can be dithered
  2010. memcpy(Line1Buffer, Line2Buffer, BytesPerLine);
  2011. // Move new data to Line2Buffer
  2012. memcpy(Line2Buffer, lpImageData  + (Row * (DWORD) BytesPerLine),
  2013. BytesPerLine);
  2014. }
  2015. // Must complete the two rows in the line buffers
  2016. DitherLine(Width, Line1Buffer, Line2Buffer);
  2017. // Copy the dithered data in Line1Buffer to destination
  2018. memcpy(lpDitheredRasterData  + ((Height-2) * (DWORD) BytesPerLineDest),
  2019. Line1Buffer, BytesPerLineDest);
  2020. memcpy(Line1Buffer, Line2Buffer, BytesPerLine);
  2021. DitherLine(Width, Line1Buffer, Line2Buffer);
  2022. // Copy the dithered data in Line1Buffer to destination
  2023. memcpy(lpDitheredRasterData  + ((Height-1) * (DWORD) BytesPerLineDest),
  2024. Line1Buffer, BytesPerLineDest);
  2025. // Free the local line buffers
  2026. LocalUnlock(hLine1Buffer);
  2027. LocalFree(hLine1Buffer);
  2028. LocalUnlock(hLine2Buffer);
  2029. LocalFree(hLine2Buffer);
  2030. // Signal all is well
  2031. GlobalUnlock(hMem);             // Unlock the dithered raster data
  2032. return hMem;                    // Return the handle of the data
  2033. }
  2034. ///////////////////// local used only !!! /////////////////////////////
  2035. // create a dithered 8bpp DIB for 24bpp DIB in not true color device
  2036. HDIB CreateDither8BppDIB(HDIB hDIB)
  2037. {
  2038. WaitCursorBegin();
  2039. if (DIBBitCount(hDIB) <= 8)
  2040. {
  2041. WaitCursorEnd();
  2042. return CopyHandle(hDIB);
  2043. }
  2044.     // dithering DIB
  2045. LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
  2046. LPSTR lpBits = FindDIBBits(lpDIB);
  2047. WORD wWidth = (WORD)DIBWidth(lpDIB);
  2048. WORD wHeight = (WORD)DIBHeight(lpDIB);
  2049.     HGLOBAL hDitheredBits = DitherImage(lpBits, wWidth, wHeight);
  2050. GlobalUnlock(hDIB);
  2051. if (! hDitheredBits)
  2052. {
  2053. WaitCursorEnd();
  2054. return NULL;
  2055. }
  2056. // create a new 8bpp DIB
  2057. HDIB hNewDib = ChangeDIBFormat(hDIB, 8, BI_RGB);;
  2058. LPBITMAPINFO lpBmi = (LPBITMAPINFO)GlobalLock(hNewDib);
  2059. lpBmi->bmiHeader.biClrUsed = 256;
  2060.     
  2061. // set the entries of dither palette to DIB color table
  2062.     for (int Index=0; Index < 256; Index++)  
  2063. {
  2064. lpBmi->bmiColors[Index].rgbRed   = DitherPalette[Index].Red;
  2065. lpBmi->bmiColors[Index].rgbGreen = DitherPalette[Index].Green;
  2066. lpBmi->bmiColors[Index].rgbBlue  = DitherPalette[Index].Blue;
  2067. lpBmi->bmiColors[Index].rgbReserved = 0;
  2068.     }
  2069. // copy dithered image bits to hNewDib
  2070. DWORD dwSize = GlobalSize(hDitheredBits);
  2071. LPSTR lpDitheredBits = (LPSTR)GlobalLock(hDitheredBits);
  2072. LPSTR lpNewBits = FindDIBBits((LPSTR)lpBmi);
  2073. memcpy(lpNewBits, lpDitheredBits, dwSize);
  2074. // cleanup
  2075. GlobalUnlock(hDitheredBits);
  2076. GlobalFree(hDitheredBits);
  2077. GlobalUnlock(hNewDib);
  2078. // map dithered DIB to dither palette
  2079. HPALETTE hPal = CreateDitherPalette();
  2080. MapDIBColorsToPalette(hNewDib, hPal);
  2081. DeleteObject(hPal);
  2082. WaitCursorEnd();
  2083. return hNewDib;
  2084. }
  2085. // create dither palette for dithering
  2086. HPALETTE CreateDitherPalette()
  2087.     LPLOGPALETTE        lpPal;          // pointer to a logical palette 
  2088.     HANDLE              hLogPal;        // handle to a logical palette 
  2089.     HPALETTE            hPal = NULL;    // handle to a palette 
  2090.     HPALETTE            hPalette = NULL;    // handle to a palette 
  2091.     int                 i;  // loop index, number of colors in color table 
  2092.  
  2093.     // allocate memory block for logical palette 
  2094.     hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256);
  2095.     // if not enough memory, clean up and return NULL 
  2096.     if (!hLogPal) 
  2097.         return NULL; 
  2098.     // lock memory block and get pointer to it 
  2099.     lpPal = (LPLOGPALETTE)GlobalLock(hLogPal); 
  2100.     // set version and number of palette entries 
  2101.     lpPal->palVersion = PALVERSION; 
  2102.     lpPal->palNumEntries = 256;
  2103. // set dithered palette value  
  2104.     for (i = 0; i < 256; i++) 
  2105.     { 
  2106.         lpPal->palPalEntry[i].peRed   = DitherPalette[i].Red; 
  2107.         lpPal->palPalEntry[i].peGreen = DitherPalette[i].Green; 
  2108.         lpPal->palPalEntry[i].peBlue  = DitherPalette[i].Blue; 
  2109.         lpPal->palPalEntry[i].peFlags = 0; 
  2110.     } 
  2111.     // create the palette and get handle to it 
  2112.     hPal = CreatePalette(lpPal); 
  2113.     // if error getting handle to palette, clean up and return NULL 
  2114.     if (!hPal) 
  2115.     { 
  2116.         GlobalUnlock(hLogPal); 
  2117.         GlobalFree(hLogPal); 
  2118.         return NULL; 
  2119.     } 
  2120. // clean up  
  2121.  
  2122.     GlobalUnlock(hLogPal); 
  2123.     GlobalFree(hLogPal); 
  2124. // change palette to identify palette
  2125. hPalette = CreateIdentifyPalette(hPal);
  2126. // return idenify palette is it's ok
  2127. // else return the original one
  2128. if (hPalette)
  2129. {
  2130. DeleteObject(hPal);
  2131.       return hPalette; 
  2132. }
  2133. else
  2134.       return hPal; 
  2135. /************************************************************************* 
  2136.  * 
  2137.  * CreateOctreePalette() 
  2138.  * 
  2139.  * Parameters: 
  2140.  * 
  2141.  * HDIB hDIB        - Handle to source DIB 
  2142.  * UINT nMaxColors  - destination color number
  2143.  * UINT nColorBits  - destination color bits
  2144.  * 
  2145.  * Return Value: 
  2146.  * 
  2147.  * HPALETTE         - Handle to the result palette
  2148.  * 
  2149.  * Description: 
  2150.  * 
  2151.  * This function use Octree color quantization algorithm to get
  2152.  * optimal m kinds of color to represent total n kinds of color 
  2153.  * in a DIB, and use the m kinds of color to build a palette.
  2154.  * With the palette, we can display the DIB on reasonable accuracy.
  2155.  * 
  2156.  ************************************************************************/ 
  2157. HPALETTE CreateOctreePalette(HDIB hDIB, UINT nMaxColors, UINT nColorBits)
  2158. {
  2159. HANDLE hImage;
  2160. hImage = DIBToDIBSection(hDIB);
  2161. if (! hImage)
  2162. return NULL;
  2163. return BuildOctreePalette(hImage, nMaxColors, nColorBits);
  2164. }
  2165. /************************************************************************* 
  2166.  * 
  2167.  * CreateOctreePalette() 
  2168.  * 
  2169.  * Parameters: 
  2170.  * 
  2171.  * LPBYTE lpDIB     - Pointer to DIB data buffer
  2172.  * UINT nMaxColors  - destination color number
  2173.  * UINT nColorBits  - destination color bits
  2174.  * 
  2175.  * Return Value: 
  2176.  * 
  2177.  * HPALETTE         - Handle to the result palette
  2178.  * 
  2179.  * Description: 
  2180.  * 
  2181.  * This function use Octree color quantization algorithm to get
  2182.  * optimal m kinds of color to represent total n kinds of color 
  2183.  * in a DIB, and use the m kinds of color to build a palette.
  2184.  * With the palette, we can display the DIB on reasonable accuracy.
  2185.  * 
  2186.  ************************************************************************/ 
  2187. HPALETTE CreateOctreePalette(LPSTR lpDIB, UINT nMaxColors, UINT nColorBits)
  2188. {
  2189. HANDLE hImage;
  2190. hImage = DIBToDIBSection(lpDIB);
  2191. if (! hImage)
  2192. return NULL;
  2193. return BuildOctreePalette(hImage, nMaxColors, nColorBits);
  2194. }
  2195. // local function to build optimal palette from DIBSection
  2196. /*
  2197. HPALETTE CreateOctreePalette(HDIB hDIB, UINT nMaxColors, UINT nColorBits)
  2198. {
  2199.     DIBSECTION ds;
  2200.     int i, j, nPad;
  2201.     BYTE* pbBits;
  2202.     WORD* pwBits;
  2203.     DWORD* pdwBits;
  2204.     DWORD rmask, gmask, bmask;
  2205.     int rright, gright, bright;
  2206.     int rleft, gleft, bleft;
  2207.     BYTE r, g, b;
  2208.     WORD wColor;
  2209.     DWORD dwColor, dwSize;
  2210.     LOGPALETTE* plp;
  2211.     HPALETTE hPalette;
  2212.     NODE* pTree;
  2213.     UINT nLeafCount, nIndex;
  2214.     NODE* pReducibleNodes[9];
  2215.     HDC hdc;    
  2216. BYTE* pBuffer = NULL;    
  2217. BITMAPINFO bmi;
  2218.     // Initialize octree variables
  2219.     pTree = NULL;
  2220.     nLeafCount = 0;
  2221.     if (nColorBits > 8) // Just in case
  2222.         return NULL;
  2223.     for (i=0; i<=(int) nColorBits; i++)
  2224.         pReducibleNodes[i] = NULL;
  2225.     // Scan the DIB and build the octree
  2226.     GetObject (hImage, sizeof (ds), &ds);
  2227.     nPad = ds.dsBm.bmWidthBytes - (((ds.dsBmih.biWidth *
  2228.         ds.dsBmih.biBitCount) + 7) / 8);
  2229.     switch (ds.dsBmih.biBitCount) {
  2230.     case 1: // 1-bit DIB    
  2231. case 4: // 4-bit DIB    
  2232. case 8: // 8-bit DIB
  2233.         //        
  2234. // The strategy here is to use ::GetDIBits to convert the
  2235.         // image into a 24-bit DIB one scan line at a time. A pleasant
  2236.         // side effect of using ::GetDIBits in this manner is that RLE-
  2237.         // encoded 4-bit and 8-bit DIBs will be uncompressed.        //
  2238.         hdc = GetDC (NULL);        
  2239. pBuffer = new BYTE[ds.dsBmih.biWidth * 3];
  2240.         ZeroMemory (&bmi, sizeof (bmi));
  2241.         bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
  2242.         bmi.bmiHeader.biWidth = ds.dsBmih.biWidth;
  2243.         bmi.bmiHeader.biHeight = ds.dsBmih.biHeight;
  2244.         bmi.bmiHeader.biPlanes = 1;        
  2245. bmi.bmiHeader.biBitCount = 24;
  2246.         bmi.bmiHeader.biCompression = BI_RGB;
  2247.         for (i=0; i<ds.dsBmih.biHeight; i++) 
  2248. {
  2249.             GetDIBits (hdc, (HBITMAP) hImage, i, 1, pBuffer, &bmi,
  2250.                 DIB_RGB_COLORS);            
  2251. pbBits = pBuffer;
  2252.             for (j=0; j<ds.dsBmih.biWidth; j++) 
  2253. {                
  2254. b = *pbBits++;
  2255.                 g = *pbBits++;                
  2256. r = *pbBits++;
  2257.                 AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
  2258.                           pReducibleNodes);
  2259.                 while (nLeafCount > nMaxColors)
  2260.                     ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);            
  2261. }        
  2262. }
  2263. ReleaseDC (NULL, hdc);        
  2264. break;    
  2265. case 16: // One case for 16-bit DIBs
  2266.         if (ds.dsBmih.biCompression == BI_BITFIELDS) {
  2267.             rmask = ds.dsBitfields[0];
  2268.             gmask = ds.dsBitfields[1];
  2269.             bmask = ds.dsBitfields[2];
  2270.         }
  2271.         else {
  2272.             rmask = 0x7C00;
  2273.             gmask = 0x03E0;
  2274.             bmask = 0x001F;
  2275.         }
  2276.         rright = GetRightShiftCount (rmask);
  2277.         gright = GetRightShiftCount (gmask);
  2278.         bright = GetRightShiftCount (bmask);
  2279.         rleft = GetLeftShiftCount (rmask);
  2280.         gleft = GetLeftShiftCount (gmask);
  2281.         bleft = GetLeftShiftCount (bmask);
  2282.         pwBits = (WORD*) ds.dsBm.bmBits;
  2283.         for (i=0; i<ds.dsBmih.biHeight; i++) {
  2284.             for (j=0; j<ds.dsBmih.biWidth; j++) {
  2285.                 wColor = *pwBits++;
  2286.                 b = (BYTE) (((wColor & (WORD) bmask) >> bright) << bleft);
  2287.                 g = (BYTE) (((wColor & (WORD) gmask) >> gright) << gleft);
  2288.                 r = (BYTE) (((wColor & (WORD) rmask) >> rright) << rleft);
  2289.                 AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
  2290.                           pReducibleNodes);
  2291.                 while (nLeafCount > nMaxColors)
  2292.                     ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
  2293.             }
  2294.             pwBits = (WORD*) (((BYTE*) pwBits) + nPad);
  2295.         }
  2296.         break;
  2297.     case 24: // Another for 24-bit DIBs
  2298.         pbBits = (BYTE*) ds.dsBm.bmBits;
  2299.         for (i=0; i<ds.dsBmih.biHeight; i++) {
  2300.             for (j=0; j<ds.dsBmih.biWidth; j++) {
  2301.                 b = *pbBits++;
  2302.                 g = *pbBits++;
  2303.                 r = *pbBits++;
  2304.                 AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
  2305.                           pReducibleNodes);
  2306.                 while (nLeafCount > nMaxColors)
  2307.                     ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
  2308.             }
  2309.             pbBits += nPad;
  2310.         }
  2311.         break;
  2312.     case 32: // And another for 32-bit DIBs
  2313.         if (ds.dsBmih.biCompression == BI_BITFIELDS) {
  2314.             rmask = ds.dsBitfields[0];
  2315.             gmask = ds.dsBitfields[1];
  2316.             bmask = ds.dsBitfields[2];
  2317.         }
  2318.         else {
  2319.             rmask = 0x00FF0000;
  2320.             gmask = 0x0000FF00;
  2321.             bmask = 0x000000FF;
  2322.         }
  2323.         rright = GetRightShiftCount (rmask);
  2324.         gright = GetRightShiftCount (gmask);
  2325.         bright = GetRightShiftCount (bmask);
  2326.         pdwBits = (DWORD*) ds.dsBm.bmBits;
  2327.         for (i=0; i<ds.dsBmih.biHeight; i++) {
  2328.             for (j=0; j<ds.dsBmih.biWidth; j++) {
  2329.                 dwColor = *pdwBits++;
  2330.                 b = (BYTE) ((dwColor & bmask) >> bright);
  2331.                 g = (BYTE) ((dwColor & gmask) >> gright);
  2332.                 r = (BYTE) ((dwColor & rmask) >> rright);
  2333.                 AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
  2334.                           pReducibleNodes);
  2335.                 while (nLeafCount > nMaxColors)
  2336.                     ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
  2337.             }
  2338.             pdwBits = (DWORD*) (((BYTE*) pdwBits) + nPad);
  2339.         }
  2340.         break;
  2341.     default: // DIB must be 16, 24, or 32-bit!
  2342.         return NULL;
  2343.     }
  2344. // cleanup
  2345. //if (pBuffer)
  2346. // delete[] pBuffer;        
  2347.    if (nLeafCount > nMaxColors) 
  2348.    { // Sanity check
  2349.         DeleteTree (&pTree);
  2350.         return NULL;
  2351.     }
  2352.     // Create a logical palette from the colors in the octree
  2353.     dwSize = sizeof (LOGPALETTE) + ((nLeafCount - 1) * sizeof (PALETTEENTRY));
  2354.     if ((plp = (LOGPALETTE*) HeapAlloc (GetProcessHeap (), 0,
  2355.         dwSize)) == NULL) {
  2356.         DeleteTree (&pTree);
  2357.         return NULL;
  2358.     }
  2359.     plp->palVersion = 0x300;
  2360.     plp->palNumEntries = (WORD) nLeafCount;
  2361.     nIndex = 0;
  2362.     GetPaletteColors (pTree, plp->palPalEntry, &nIndex);
  2363.     hPalette = CreatePalette (plp);
  2364.     HeapFree (GetProcessHeap (), 0, plp);
  2365.     DeleteTree (&pTree);
  2366.     return hPalette;
  2367. }
  2368. */
  2369. HPALETTE BuildOctreePalette(HANDLE hImage, UINT nMaxColors, UINT nColorBits)
  2370. {
  2371.     DIBSECTION ds;
  2372.     int i, j, nPad;
  2373.     BYTE* pbBits;
  2374.     WORD* pwBits;
  2375.     DWORD* pdwBits;
  2376.     DWORD rmask, gmask, bmask;
  2377.     int rright, gright, bright;
  2378.     int rleft, gleft, bleft;
  2379.     BYTE r, g, b;
  2380.     WORD wColor;
  2381.     DWORD dwColor, dwSize;
  2382.     LOGPALETTE* plp;
  2383.     HPALETTE hPalette;
  2384.     NODE* pTree;
  2385.     UINT nLeafCount, nIndex;
  2386.     NODE* pReducibleNodes[9];
  2387.     HDC hdc;    
  2388. BYTE* pBuffer = NULL;    
  2389. BITMAPINFO bmi;
  2390.     // Initialize octree variables
  2391.     pTree = NULL;
  2392.     nLeafCount = 0;
  2393.     if (nColorBits > 8) // Just in case
  2394.         return NULL;
  2395.     for (i=0; i<=(int) nColorBits; i++)
  2396.         pReducibleNodes[i] = NULL;
  2397.     // Scan the DIB and build the octree
  2398.     GetObject (hImage, sizeof (ds), &ds);
  2399.     nPad = ds.dsBm.bmWidthBytes - (((ds.dsBmih.biWidth *
  2400.         ds.dsBmih.biBitCount) + 7) / 8);
  2401.     switch (ds.dsBmih.biBitCount) {
  2402.     case 1: // 1-bit DIB    
  2403. case 4: // 4-bit DIB    
  2404. case 8: // 8-bit DIB
  2405.         //        
  2406. // The strategy here is to use ::GetDIBits to convert the
  2407.         // image into a 24-bit DIB one scan line at a time. A pleasant
  2408.         // side effect of using ::GetDIBits in this manner is that RLE-
  2409.         // encoded 4-bit and 8-bit DIBs will be uncompressed.        //
  2410.         hdc = GetDC (NULL);        
  2411. pBuffer = new BYTE[ds.dsBmih.biWidth * 3];
  2412.         ZeroMemory (&bmi, sizeof (bmi));
  2413.         bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
  2414.         bmi.bmiHeader.biWidth = ds.dsBmih.biWidth;
  2415.         bmi.bmiHeader.biHeight = ds.dsBmih.biHeight;
  2416.         bmi.bmiHeader.biPlanes = 1;        
  2417. bmi.bmiHeader.biBitCount = 24;
  2418.         bmi.bmiHeader.biCompression = BI_RGB;
  2419.         for (i=0; i<ds.dsBmih.biHeight; i++) 
  2420. {
  2421.             GetDIBits (hdc, (HBITMAP) hImage, i, 1, pBuffer, &bmi,
  2422.                 DIB_RGB_COLORS);            
  2423. pbBits = pBuffer;
  2424.             for (j=0; j<ds.dsBmih.biWidth; j++) 
  2425. {                
  2426. b = *pbBits++;
  2427.                 g = *pbBits++;                
  2428. r = *pbBits++;
  2429.                 AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
  2430.                           pReducibleNodes);
  2431.                 while (nLeafCount > nMaxColors)
  2432.                     ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);            
  2433. }        
  2434. }
  2435. ReleaseDC (NULL, hdc);        
  2436. break;    
  2437. case 16: // One case for 16-bit DIBs
  2438.         if (ds.dsBmih.biCompression == BI_BITFIELDS) {
  2439.             rmask = ds.dsBitfields[0];
  2440.             gmask = ds.dsBitfields[1];
  2441.             bmask = ds.dsBitfields[2];
  2442.         }
  2443.         else {
  2444.             rmask = 0x7C00;
  2445.             gmask = 0x03E0;
  2446.             bmask = 0x001F;
  2447.         }
  2448.         rright = GetRightShiftCount (rmask);
  2449.         gright = GetRightShiftCount (gmask);
  2450.         bright = GetRightShiftCount (bmask);
  2451.         rleft = GetLeftShiftCount (rmask);
  2452.         gleft = GetLeftShiftCount (gmask);
  2453.         bleft = GetLeftShiftCount (bmask);
  2454.         pwBits = (WORD*) ds.dsBm.bmBits;
  2455.         for (i=0; i<ds.dsBmih.biHeight; i++) {
  2456.             for (j=0; j<ds.dsBmih.biWidth; j++) {
  2457.                 wColor = *pwBits++;
  2458.                 b = (BYTE) (((wColor & (WORD) bmask) >> bright) << bleft);
  2459.                 g = (BYTE) (((wColor & (WORD) gmask) >> gright) << gleft);
  2460.                 r = (BYTE) (((wColor & (WORD) rmask) >> rright) << rleft);
  2461.                 AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
  2462.                           pReducibleNodes);
  2463.                 while (nLeafCount > nMaxColors)
  2464.                     ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
  2465.             }
  2466.             pwBits = (WORD*) (((BYTE*) pwBits) + nPad);
  2467.         }
  2468.         break;
  2469.     case 24: // Another for 24-bit DIBs
  2470.         pbBits = (BYTE*) ds.dsBm.bmBits;
  2471.         for (i=0; i<ds.dsBmih.biHeight; i++) {
  2472.             for (j=0; j<ds.dsBmih.biWidth; j++) {
  2473.                 b = *pbBits++;
  2474.                 g = *pbBits++;
  2475.                 r = *pbBits++;
  2476.                 AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
  2477.                           pReducibleNodes);
  2478.                 while (nLeafCount > nMaxColors)
  2479.                     ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
  2480.             }
  2481.             pbBits += nPad;
  2482.         }
  2483.         break;
  2484.     case 32: // And another for 32-bit DIBs
  2485.         if (ds.dsBmih.biCompression == BI_BITFIELDS) {
  2486.             rmask = ds.dsBitfields[0];
  2487.             gmask = ds.dsBitfields[1];
  2488.             bmask = ds.dsBitfields[2];
  2489.         }
  2490.         else {
  2491.             rmask = 0x00FF0000;
  2492.             gmask = 0x0000FF00;
  2493.             bmask = 0x000000FF;
  2494.         }
  2495.         rright = GetRightShiftCount (rmask);
  2496.         gright = GetRightShiftCount (gmask);
  2497.         bright = GetRightShiftCount (bmask);
  2498.         pdwBits = (DWORD*) ds.dsBm.bmBits;
  2499.         for (i=0; i<ds.dsBmih.biHeight; i++) {
  2500.             for (j=0; j<ds.dsBmih.biWidth; j++) {
  2501.                 dwColor = *pdwBits++;
  2502.                 b = (BYTE) ((dwColor & bmask) >> bright);
  2503.                 g = (BYTE) ((dwColor & gmask) >> gright);
  2504.                 r = (BYTE) ((dwColor & rmask) >> rright);
  2505.                 AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
  2506.                           pReducibleNodes);
  2507.                 while (nLeafCount > nMaxColors)
  2508.                     ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
  2509.             }
  2510.             pdwBits = (DWORD*) (((BYTE*) pdwBits) + nPad);
  2511.         }
  2512.         break;
  2513.     default: // DIB must be 16, 24, or 32-bit!
  2514.         return NULL;
  2515.     }
  2516. // cleanup
  2517. //if (pBuffer)
  2518. // delete[] pBuffer;        
  2519.    if (nLeafCount > nMaxColors) 
  2520.    { // Sanity check
  2521.         DeleteTree (&pTree);
  2522.         return NULL;
  2523.     }
  2524.     // Create a logical palette from the colors in the octree
  2525.     dwSize = sizeof (LOGPALETTE) + ((nLeafCount - 1) * sizeof (PALETTEENTRY));
  2526.     if ((plp = (LOGPALETTE*) HeapAlloc (GetProcessHeap (), 0,
  2527.         dwSize)) == NULL) {
  2528.         DeleteTree (&pTree);
  2529.         return NULL;
  2530.     }
  2531.     plp->palVersion = 0x300;
  2532.     plp->palNumEntries = (WORD) nLeafCount;
  2533.     nIndex = 0;
  2534.     GetPaletteColors (pTree, plp->palPalEntry, &nIndex);
  2535.     hPalette = CreatePalette (plp);
  2536.     HeapFree (GetProcessHeap (), 0, plp);
  2537.     DeleteTree (&pTree);
  2538.     return hPalette;
  2539. }
  2540. /*************************************************************************
  2541. *
  2542. * PaintDIB()
  2543. *
  2544. * Parameters:
  2545. *
  2546. * HDC hDC          - DC to do output to
  2547. *
  2548. * LPRECT lpDCRect  - rectangle on DC to do output to
  2549. *
  2550. * HDIB hDIB        - handle to global memory with a DIB spec
  2551. *                    in it followed by the DIB bits
  2552. *
  2553. * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
  2554. *
  2555. * CPalette* pPal   - pointer to CPalette containing DIB's palette
  2556. *
  2557. * Return Value:
  2558. *
  2559. * BOOL             - TRUE if DIB was drawn, FALSE otherwise
  2560. *
  2561. * Description:
  2562. *   Painting routine for a DIB.  Calls StretchDIBits() or
  2563. *   SetDIBitsToDevice() to paint the DIB.  The DIB is
  2564. *   output to the specified DC, at the coordinates given
  2565. *   in lpDCRect.  The area of the DIB to be output is
  2566. *   given by lpDIBRect.
  2567. *
  2568. ************************************************************************/
  2569. BOOL WINAPI PaintDIB(HDC     hDC,
  2570.  LPRECT  lpDCRect,
  2571.  HDIB    hDIB,
  2572.  LPRECT  lpDIBRect,
  2573.  CPalette* pPal)
  2574. {
  2575. LPSTR    lpDIBHdr;            // Pointer to BITMAPINFOHEADER
  2576. LPSTR    lpDIBBits;           // Pointer to DIB bits
  2577. BOOL     bSuccess=FALSE;      // Success/fail flag
  2578. HPALETTE hPal=NULL;           // Our DIB's palette
  2579. HPALETTE hOldPal=NULL;        // Previous palette
  2580. /* Check for valid DIB handle */
  2581. if (hDIB == NULL)
  2582. return FALSE;
  2583. /* Lock down the DIB, and get a pointer to the beginning of the bit
  2584. *  buffer
  2585. */
  2586. lpDIBHdr  = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  2587. lpDIBBits = ::FindDIBBits(lpDIBHdr);
  2588. // Get the DIB's palette, then select it into DC
  2589. if (pPal != NULL)
  2590. {
  2591. hPal = (HPALETTE) pPal->m_hObject;
  2592. // Select as background since we have
  2593. // already realized in forground if needed
  2594. hOldPal = ::SelectPalette(hDC, hPal, TRUE);
  2595. }
  2596. /* Make sure to use the stretching mode best for color pictures */
  2597. ::SetStretchBltMode(hDC, COLORONCOLOR);
  2598. /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
  2599. if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDIBRect)) &&
  2600. (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
  2601. {
  2602. bSuccess = ::SetDIBitsToDevice(hDC,                    // hDC
  2603. lpDCRect->left,             // DestX
  2604. lpDCRect->top,              // DestY
  2605. RECTWIDTH(lpDCRect),        // nDestWidth
  2606. RECTHEIGHT(lpDCRect),       // nDestHeight
  2607. lpDIBRect->left,            // SrcX
  2608. //    (int)DIBHeight(lpDIBHdr) -
  2609. lpDIBRect->top,// -
  2610. //   RECTHEIGHT(lpDIBRect),   // SrcY
  2611. 0,                          // nStartScan
  2612. (WORD)abs(DIBHeight(lpDIBHdr)),  // nNumScans
  2613. lpDIBBits,                  // lpBits
  2614. (LPBITMAPINFO)lpDIBHdr,     // lpBitsInfo
  2615. DIB_RGB_COLORS);            // wUsage
  2616. }
  2617. else
  2618. {
  2619. bSuccess = ::StretchDIBits(hDC,                          // hDC
  2620. lpDCRect->left,                 // DestX
  2621. lpDCRect->top,                  // DestY
  2622. RECTWIDTH(lpDCRect),            // nDestWidth
  2623. RECTHEIGHT(lpDCRect),           // nDestHeight
  2624. lpDIBRect->left,                // SrcX
  2625. lpDIBRect->top,                 // SrcY
  2626. RECTWIDTH(lpDIBRect),           // wSrcWidth
  2627. RECTHEIGHT(lpDIBRect),          // wSrcHeight
  2628. lpDIBBits,                      // lpBits
  2629. (LPBITMAPINFO)lpDIBHdr,         // lpBitsInfo
  2630. DIB_RGB_COLORS,                 // wUsage
  2631. SRCCOPY);                       // dwROP
  2632. }
  2633. ::GlobalUnlock((HGLOBAL) hDIB);
  2634. /* Reselect old palette */
  2635. if (hOldPal != NULL)
  2636. {
  2637. ::SelectPalette(hDC, hOldPal, TRUE);
  2638. }
  2639. return bSuccess;
  2640. }
  2641. /*************************************************************************
  2642. *
  2643. * CreateDIBPalette()
  2644. *
  2645. * Parameter:
  2646. *
  2647. * HDIB hDIB        - specifies the DIB
  2648. *
  2649. * Return Value:
  2650. *
  2651. * HPALETTE         - specifies the palette
  2652. *
  2653. * Description:
  2654. *
  2655. * This function creates a palette from a DIB by allocating memory for the
  2656. * logical palette, reading and storing the colors from the DIB's color table
  2657. * into the logical palette, creating a palette from this logical palette,
  2658. * and then returning the palette's handle. This allows the DIB to be
  2659. * displayed using the best possible colors (important for DIBs with 256 or
  2660. * more colors).
  2661. *
  2662. ************************************************************************/
  2663. BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal)
  2664. {
  2665. LPLOGPALETTE lpPal;      // pointer to a logical palette
  2666. HANDLE hLogPal;          // handle to a logical palette
  2667. HPALETTE hPal = NULL;    // handle to a palette
  2668. int i;                   // loop index
  2669. WORD wNumColors;         // number of colors in color table
  2670. LPSTR lpbi;              // pointer to packed-DIB
  2671. LPBITMAPINFO lpbmi;      // pointer to BITMAPINFO structure (Win3.0)
  2672. LPBITMAPCOREINFO lpbmc;  // pointer to BITMAPCOREINFO structure (old)
  2673. BOOL bWinStyleDIB;       // flag which signifies whether this is a Win3.0 DIB
  2674. BOOL bResult = FALSE;
  2675. /* if handle to DIB is invalid, return FALSE */
  2676. if (hDIB == NULL)
  2677.  return FALSE;
  2678. lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  2679. /* get pointer to BITMAPINFO (Win 3.0) */
  2680. lpbmi = (LPBITMAPINFO)lpbi;
  2681. /* get pointer to BITMAPCOREINFO (old 1.x) */
  2682. lpbmc = (LPBITMAPCOREINFO)lpbi;
  2683. /* get the number of colors in the DIB */
  2684. wNumColors = ::DIBNumColors(lpbi);
  2685. if (wNumColors != 0)
  2686. {
  2687. /* allocate memory block for logical palette */
  2688. hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
  2689. + sizeof(PALETTEENTRY)
  2690. * wNumColors);
  2691. /* if not enough memory, clean up and return NULL */
  2692. if (hLogPal == 0)
  2693. {
  2694. ::GlobalUnlock((HGLOBAL) hDIB);
  2695. return FALSE;
  2696. }
  2697. lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
  2698. /* set version and number of palette entries */
  2699. lpPal->palVersion = PALVERSION;
  2700. lpPal->palNumEntries = (WORD)wNumColors;
  2701. /* is this a Win 3.0 DIB? */
  2702. bWinStyleDIB = IS_WIN30_DIB(lpbi);
  2703. for (i = 0; i < (int)wNumColors; i++)
  2704. {
  2705. if (bWinStyleDIB)
  2706. {
  2707. lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
  2708. lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
  2709. lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
  2710. lpPal->palPalEntry[i].peFlags = 0;
  2711. }
  2712. else
  2713. {
  2714. lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
  2715. lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
  2716. lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
  2717. lpPal->palPalEntry[i].peFlags = 0;
  2718. }
  2719. }
  2720. /* create the palette and get handle to it */
  2721. bResult = pPal->CreatePalette(lpPal);
  2722. ::GlobalUnlock((HGLOBAL) hLogPal);
  2723. ::GlobalFree((HGLOBAL) hLogPal);
  2724. }
  2725. ::GlobalUnlock((HGLOBAL) hDIB);
  2726. return bResult;
  2727. }
  2728. /*************************************************************************
  2729. *
  2730. * FindDIBBits()
  2731. *
  2732. * Parameter:
  2733. *
  2734. * LPSTR lpbi       - pointer to packed-DIB memory block
  2735. *
  2736. * Return Value:
  2737. *
  2738. * LPSTR            - pointer to the DIB bits
  2739. *
  2740. * Description:
  2741. *
  2742. * This function calculates the address of the DIB's bits and returns a
  2743. * pointer to the DIB bits.
  2744. *
  2745. ************************************************************************/
  2746. LPSTR WINAPI FindDIBBits(LPSTR lpbi)
  2747. {
  2748. return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi));
  2749. }
  2750. /*************************************************************************
  2751. *
  2752. * DIBWidth()
  2753. *
  2754. * Parameter:
  2755. *
  2756. * LPSTR lpbi       - pointer to packed-DIB memory block
  2757. *
  2758. * Return Value:
  2759. *
  2760. * DWORD            - width of the DIB
  2761. *
  2762. * Description:
  2763. *
  2764. * This function gets the width of the DIB from the BITMAPINFOHEADER
  2765. * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  2766. * width field if it is an other-style DIB.
  2767. *
  2768. ************************************************************************/
  2769. long WINAPI DIBWidth(LPSTR lpDIB)
  2770. {
  2771. LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
  2772. LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB
  2773. /* point to the header (whether Win 3.0 and old) */
  2774. lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  2775. lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  2776. /* return the DIB width if it is a Win 3.0 DIB */
  2777. if (IS_WIN30_DIB(lpDIB))
  2778. return lpbmi->biWidth;
  2779. else  /* it is an other-style DIB, so return its width */
  2780. return (long)lpbmc->bcWidth;
  2781. }
  2782. /*************************************************************************
  2783. *
  2784. * DIBHeight()
  2785. *
  2786. * Parameter:
  2787. *
  2788. * LPSTR lpbi       - pointer to packed-DIB memory block
  2789. *
  2790. * Return Value:
  2791. *
  2792. * DWORD            - height of the DIB
  2793. *
  2794. * Description:
  2795. *
  2796. * This function gets the height of the DIB from the BITMAPINFOHEADER
  2797. * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
  2798. * height field if it is an other-style DIB.
  2799. *
  2800. ************************************************************************/
  2801. long WINAPI DIBHeight(LPSTR lpDIB)
  2802. {
  2803. LPBITMAPINFOHEADER lpbmi;  // pointer to a Win 3.0-style DIB
  2804. LPBITMAPCOREHEADER lpbmc;  // pointer to an other-style DIB
  2805. /* point to the header (whether old or Win 3.0 */
  2806. lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  2807. lpbmc = (LPBITMAPCOREHEADER)lpDIB;
  2808. /* return the DIB height if it is a Win 3.0 DIB */
  2809. if (IS_WIN30_DIB(lpDIB))
  2810. return lpbmi->biHeight;
  2811. else  /* it is an other-style DIB, so return its height */
  2812. return (long)lpbmc->bcHeight;
  2813. }
  2814. /*************************************************************************
  2815. *
  2816. * PaletteSize()
  2817. *
  2818. * Parameter:
  2819. *
  2820. * LPSTR lpbi       - pointer to packed-DIB memory block
  2821. *
  2822. * Return Value:
  2823. *
  2824. * WORD             - size of the color palette of the DIB
  2825. *
  2826. * Description:
  2827. *
  2828. * This function gets the size required to store the DIB's palette by
  2829. * multiplying the number of colors by the size of an RGBQUAD (for a
  2830. * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an other-
  2831. * style DIB).
  2832. *
  2833. ************************************************************************/
  2834. WORD WINAPI PaletteSize(LPSTR lpbi)
  2835. {
  2836. /* calculate the size required by the palette */
  2837. if (IS_WIN30_DIB (lpbi))
  2838. return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
  2839. else
  2840. return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
  2841. }
  2842. /*************************************************************************
  2843. *
  2844. * DIBNumColors()
  2845. *
  2846. * Parameter:
  2847. *
  2848. * LPSTR lpbi       - pointer to packed-DIB memory block
  2849. *
  2850. * Return Value:
  2851. *
  2852. * WORD             - number of colors in the color table
  2853. *
  2854. * Description:
  2855. *
  2856. * This function calculates the number of colors in the DIB's color table
  2857. * by finding the bits per pixel for the DIB (whether Win3.0 or other-style
  2858. * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
  2859. * if 24, no colors in color table.
  2860. *
  2861. ************************************************************************/
  2862. WORD WINAPI DIBNumColors(LPSTR lpbi)
  2863. {
  2864. WORD wBitCount;  // DIB bit count
  2865.  /*  If this is a Windows-style DIB, the number of colors in the
  2866.  *  color table can be less than the number of bits per pixel
  2867.  *  allows for (i.e. lpbi->biClrUsed can be set to some value).
  2868.  *  If this is the case, return the appropriate value.
  2869. */
  2870. if (IS_WIN30_DIB(lpbi))
  2871. {
  2872. DWORD dwClrUsed;
  2873. dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
  2874. if (dwClrUsed != 0)
  2875. return (WORD)dwClrUsed;
  2876. }
  2877. /*  Calculate the number of colors in the color table based on
  2878. *  the number of bits per pixel for the DIB.
  2879. */
  2880. if (IS_WIN30_DIB(lpbi))
  2881. wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
  2882. else
  2883. wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
  2884. /* return number of colors based on bits per pixel */
  2885. switch (wBitCount)
  2886. {
  2887. case 1:
  2888. return 2;
  2889. case 4:
  2890. return 16;
  2891. case 8:
  2892. return 256;
  2893. default:
  2894. return 0;
  2895. }
  2896. }
  2897. //////////////////////////////////////////////////////////////////////////
  2898. //// Clipboard support
  2899. //---------------------------------------------------------------------
  2900. //
  2901. // Function:   CopyHandle (from SDK DibView sample clipbrd.c)
  2902. //
  2903. // Purpose:    Makes a copy of the given global memory block.  Returns
  2904. //             a handle to the new memory block (NULL on error).
  2905. //
  2906. //             Routine stolen verbatim out of ShowDIB.
  2907. //
  2908. // Parms:      h == Handle to global memory to duplicate.
  2909. //
  2910. // Returns:    Handle to new global memory block.
  2911. //
  2912. //---------------------------------------------------------------------
  2913. HGLOBAL WINAPI CopyHandle (HGLOBAL h)
  2914. {
  2915. if (h == NULL)
  2916. return NULL;
  2917. DWORD dwLen = ::GlobalSize((HGLOBAL) h);
  2918. HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen);
  2919. if (hCopy != NULL)
  2920. {
  2921. void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
  2922. void* lp     = ::GlobalLock((HGLOBAL) h);
  2923. memcpy(lpCopy, lp, dwLen);
  2924. ::GlobalUnlock(hCopy);
  2925. ::GlobalUnlock(h);
  2926. }
  2927. return hCopy;
  2928. }
  2929. //DIBFILEAPI
  2930. //  Source file for Device-Independent Bitmap (DIB) API.  Provides
  2931. //  the following functions:
  2932. //
  2933. //  SaveDIB()           - Saves the specified dib in a file
  2934. //  ReadDIBFile()       - Loads a DIB from a file
  2935. //
  2936. //
  2937. /*
  2938. * Dib Header Marker - used in writing DIBs to files
  2939. */
  2940. #define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')
  2941. /*************************************************************************
  2942. *
  2943. * SaveDIB()
  2944. *
  2945. * Saves the specified DIB into the specified CFile.  The CFile
  2946. * is opened and closed by the caller.
  2947. *
  2948. * Parameters:
  2949. *
  2950. * HDIB hDib - Handle to the dib to save
  2951. *
  2952. * CFile& file - open CFile used to save DIB
  2953. *
  2954. * Return value: TRUE if successful, else FALSE or CFileException
  2955. *
  2956. *************************************************************************/
  2957. BOOL WINAPI SaveDIB(HDIB hDib, CFile& file)
  2958. {
  2959. BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
  2960. LPBITMAPINFOHEADER lpBI;   // Pointer to DIB info structure
  2961. DWORD dwDIBSize;
  2962. if (hDib == NULL)
  2963. return FALSE;
  2964.  /*
  2965.  * Get a pointer to the DIB memory, the first of which contains
  2966.  * a BITMAPINFO structure
  2967. */
  2968. lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
  2969. if (lpBI == NULL)
  2970. return FALSE;
  2971. if (!IS_WIN30_DIB(lpBI))
  2972. {
  2973. ::GlobalUnlock((HGLOBAL) hDib);
  2974. return FALSE;       // It's an other-style DIB (save not supported)
  2975. }
  2976. /*
  2977. * Fill in the fields of the file header
  2978. */
  2979. /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
  2980. bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM"
  2981. // Calculating the size of the DIB is a bit tricky (if we want to
  2982. // do it right).  The easiest way to do this is to call GlobalSize()
  2983. // on our global handle, but since the size of our global memory may have
  2984. // been padded a few bytes, we may end up writing out a few too
  2985. // many bytes to the file (which may cause problems with some apps).
  2986. //
  2987. // So, instead let's calculate the size manually (if we can)
  2988. //
  2989. // First, find size of header plus size of color table.  Since the
  2990. // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
  2991. // the size of the structure, let's use this.
  2992. dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);  // Partial Calculation
  2993. // Now calculate the size of the image
  2994. if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
  2995. {
  2996. // It's an RLE bitmap, we can't calculate size, so trust the
  2997. // biSizeImage field
  2998. dwDIBSize += lpBI->biSizeImage;
  2999. }
  3000. else
  3001. {
  3002. DWORD dwBmBitsSize;  // Size of Bitmap Bits only
  3003. // It's not RLE, so size is Width (DWORD aligned) * Height
  3004. dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * abs(lpBI->biHeight);
  3005. dwDIBSize += dwBmBitsSize;
  3006. // Now, since we have calculated the correct size, why don't we
  3007. // fill in the biSizeImage field (this will fix any .BMP files which
  3008. // have this field incorrect).
  3009. lpBI->biSizeImage = dwBmBitsSize;
  3010. }
  3011. // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
  3012. bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
  3013. bmfHdr.bfReserved1 = 0;
  3014. bmfHdr.bfReserved2 = 0;
  3015. /*
  3016. * Now, calculate the offset the actual bitmap bits will be in
  3017. * the file -- It's the Bitmap file header plus the DIB header,
  3018. * plus the size of the color table.
  3019. */
  3020. bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize
  3021. + PaletteSize((LPSTR)lpBI);
  3022. TRY
  3023. {
  3024. // Write the file header
  3025. file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
  3026. //
  3027. // Write the DIB header and the bits
  3028. //
  3029. file.Write(lpBI, dwDIBSize);
  3030. }
  3031. CATCH (CFileException, e)
  3032. {
  3033. ::GlobalUnlock((HGLOBAL) hDib);
  3034. THROW_LAST();
  3035. }
  3036. END_CATCH
  3037. ::GlobalUnlock((HGLOBAL) hDib);
  3038. return TRUE;
  3039. }
  3040. /*************************************************************************
  3041. *
  3042. Function:  ReadDIBFile (CFile&)
  3043. Purpose:  Reads in the specified DIB file into a global chunk of
  3044. memory.
  3045. Returns:  A handle to a dib (hDIB) if successful.
  3046. NULL if an error occurs.
  3047. Comments:  BITMAPFILEHEADER is stripped off of the DIB.  Everything
  3048. from the end of the BITMAPFILEHEADER structure on is
  3049. returned in the global memory handle.
  3050. *
  3051. *************************************************************************/
  3052. HDIB WINAPI ReadDIBFile(CFile& file)
  3053. {
  3054. BITMAPFILEHEADER bmfHeader;
  3055. DWORD dwBitsSize;
  3056. HDIB hDIB;
  3057. LPSTR pDIB;
  3058. /*
  3059. * get length of DIB in bytes for use when reading
  3060. */
  3061. dwBitsSize = file.GetLength();
  3062. /*
  3063. * Go read the DIB file header and check if it's valid.
  3064. */
  3065. if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
  3066. return NULL;
  3067. if (bmfHeader.bfType != DIB_HEADER_MARKER)
  3068. return NULL;
  3069. /*
  3070. * Allocate memory for DIB
  3071. */
  3072. hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
  3073. if (hDIB == 0)
  3074. {
  3075. return NULL;
  3076. }
  3077. pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  3078. /*
  3079. * Go read the bits.
  3080. */
  3081. if (file.Read(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
  3082. dwBitsSize - sizeof(BITMAPFILEHEADER) )
  3083. {
  3084. ::GlobalUnlock((HGLOBAL) hDIB);
  3085. ::GlobalFree((HGLOBAL) hDIB);
  3086. return NULL;
  3087. }
  3088. ::GlobalUnlock((HGLOBAL) hDIB);
  3089. return hDIB;
  3090. }
  3091. //My Add
  3092. ////*************************************/////////////
  3093. HDIB WINAPI ShowJPEG(int iWidth,int iHeight,const BYTE* pByte)
  3094. {
  3095. ASSERT(NULL != pByte);
  3096. HDIB hDIB = NULL;
  3097. DWORD iSize = iWidth;
  3098. // iWidth = (iWidth + 3) / 4 * 4;
  3099. int iDiff = iWidth - iSize;
  3100. iSize = abs(iWidth * iHeight)*3;
  3101. hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
  3102. iSize + sizeof(BITMAPINFOHEADER));
  3103. if(hDIB==NULL)
  3104. {
  3105. CString szMsg("DIB is too large!");
  3106. // szMsg.LoadString(IDS_DIB_TOO_BIG);
  3107. MessageBox(NULL, szMsg, NULL, MB_ICONINFORMATION | MB_OK);
  3108. return NULL;
  3109. }
  3110. BYTE *pDIB = (BYTE*)GlobalLock(hDIB);
  3111. LPBITMAPINFO lpbi = (LPBITMAPINFO)pDIB;
  3112. //intialize bitmapheader
  3113. lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  3114. lpbi->bmiHeader.biWidth = iWidth;
  3115. lpbi->bmiHeader.biHeight = iHeight;
  3116. lpbi->bmiHeader.biPlanes = 1;
  3117. lpbi->bmiHeader.biBitCount= 24;
  3118. lpbi->bmiHeader.biCompression = BI_RGB;
  3119. lpbi->bmiHeader.biSizeImage = 0;
  3120.     lpbi->bmiHeader.biXPelsPerMeter = 0;
  3121.     lpbi->bmiHeader.biYPelsPerMeter = 0;
  3122. lpbi->bmiHeader.biClrUsed = 0;
  3123. lpbi->bmiHeader.biClrImportant = 0;
  3124. pDIB += (sizeof(BITMAPINFOHEADER));
  3125. // if(iDiff == 0)
  3126. {
  3127. memcpy(pDIB,pByte,iSize);
  3128. }
  3129. // else
  3130. // {
  3131. // iDiff = (iWidth - iDiff)*3;
  3132. // iWidth *= 3;
  3133. // for(i=0; i<abs(iHeight); i++)
  3134. // {
  3135. // memcpy(pDIB , pByte,iDiff);
  3136. // pDIB += iWidth;
  3137. // pByte += iDiff;
  3138. // }
  3139. // }
  3140. //
  3141. GlobalUnlock(hDIB);
  3142. return hDIB;
  3143. }
  3144. HDIB WINAPI GenBmp(int iWidth,int iHeight,int iBits, const BYTE* pByte)
  3145. {
  3146. ASSERT(NULL != pByte);
  3147. HDIB hDIB=NULL;
  3148. DWORD iSize = iWidth;
  3149. iWidth = (iWidth + 3) / 4 * 4;
  3150. int iDiff = iWidth - iSize;
  3151. iSize = abs(iWidth * iHeight);
  3152. int iColors = (int)pow(2, iBits);
  3153. if(iBits < 24)
  3154. {
  3155. hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
  3156. iSize + sizeof(BITMAPINFOHEADER) + iColors * sizeof(RGBQUAD));
  3157. }
  3158. else
  3159. {
  3160. hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, iSize);
  3161. }
  3162. if(hDIB==NULL)
  3163. {
  3164. CString szMsg("DIB is too large!");
  3165. // szMsg.LoadString(IDS_DIB_TOO_BIG);
  3166. MessageBox(NULL, szMsg, NULL, MB_ICONINFORMATION | MB_OK);
  3167. return NULL;
  3168. }
  3169. BYTE *pDIB = (BYTE*)GlobalLock(hDIB);
  3170. LPBITMAPINFO lpbi = (LPBITMAPINFO)pDIB;
  3171. //intialize bitmapheader
  3172. lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  3173. lpbi->bmiHeader.biWidth = iWidth;
  3174. lpbi->bmiHeader.biHeight = iHeight;
  3175. lpbi->bmiHeader.biPlanes = 1;
  3176. lpbi->bmiHeader.biBitCount = iBits;
  3177. lpbi->bmiHeader.biCompression = BI_RGB;
  3178. lpbi->bmiHeader.biSizeImage = iSize;
  3179.     lpbi->bmiHeader.biXPelsPerMeter = 0;
  3180.     lpbi->bmiHeader.biYPelsPerMeter = 0;
  3181. lpbi->bmiHeader.biClrUsed = 0;
  3182. lpbi->bmiHeader.biClrImportant = 0;
  3183. //fill in the color table
  3184. int  i;
  3185. if(iBits < 24)
  3186. {
  3187. for(i = 0; i < iColors; i++)
  3188. {
  3189. lpbi->bmiColors[i].rgbRed=(BYTE)i;
  3190. lpbi->bmiColors[i].rgbGreen=(BYTE)i;
  3191. lpbi->bmiColors[i].rgbBlue=(BYTE)i;
  3192. lpbi->bmiColors[i].rgbReserved=0;
  3193. }
  3194. pDIB += (sizeof(BITMAPINFOHEADER) + iColors * sizeof(RGBQUAD));
  3195. }
  3196. if(iDiff == 0)
  3197. {
  3198. memcpy(pDIB, pByte, int(iSize * (double)iBits / 8.0));
  3199. }
  3200. else
  3201. {
  3202. iDiff = int((iWidth - iDiff) * (double)iBits / 8.0);
  3203. iWidth = (int)(iWidth * (double)iBits / 8.0);
  3204. for(i = 0; i < abs(iHeight); i++)
  3205. {
  3206. memcpy(pDIB , pByte, iDiff);
  3207. pDIB += iWidth;
  3208. pByte += iDiff;
  3209. }
  3210. }
  3211. GlobalUnlock(hDIB);
  3212. return hDIB;
  3213. }
  3214. HDIB WINAPI ShowColorBytes(int iWidth,int iHeight, const BYTE* pByte)
  3215. {
  3216. ASSERT(NULL != pByte);
  3217. DWORD iSize = iWidth;
  3218. iWidth = (iWidth + 3) / 4 * 4;
  3219. int iDiff = iWidth - iSize;
  3220. iSize = abs(iWidth * iHeight);
  3221. HDIB hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
  3222. iSize + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
  3223. if(hDIB == NULL)
  3224. {
  3225. CString szMsg("DIB is too large!");
  3226. // szMsg.LoadString(IDS_DIB_TOO_BIG);
  3227. MessageBox(NULL, szMsg, NULL, MB_ICONINFORMATION | MB_OK);
  3228. return NULL;
  3229. }
  3230. BYTE *pDIB = (BYTE*)GlobalLock(hDIB);
  3231. LPBITMAPINFO lpbi = (LPBITMAPINFO)pDIB;
  3232. //intialize bitmapheader
  3233. lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  3234. lpbi->bmiHeader.biWidth = iWidth;
  3235. lpbi->bmiHeader.biHeight = iHeight;
  3236. lpbi->bmiHeader.biPlanes = 1;
  3237. lpbi->bmiHeader.biBitCount = 8;
  3238. lpbi->bmiHeader.biCompression = BI_RGB;
  3239. lpbi->bmiHeader.biSizeImage = iSize;
  3240.     lpbi->bmiHeader.biXPelsPerMeter = 0;
  3241.     lpbi->bmiHeader.biYPelsPerMeter = 0;
  3242. lpbi->bmiHeader.biClrUsed = 0;
  3243. lpbi->bmiHeader.biClrImportant = 0;
  3244. //fill in the color table
  3245. for(int i = 0; i < 1; i++)
  3246. {
  3247. lpbi->bmiColors[i].rgbRed =12;
  3248. lpbi->bmiColors[i].rgbGreen = (BYTE)(100);
  3249. lpbi->bmiColors[i].rgbBlue = (BYTE)(240);
  3250. lpbi->bmiColors[i].rgbReserved = 0;
  3251. }
  3252. for(i = 1; i < 25; i++)
  3253. {
  3254. lpbi->bmiColors[i].rgbRed = i/2;
  3255. lpbi->bmiColors[i].rgbGreen = 9*(i-1)+30;
  3256. lpbi->bmiColors[i].rgbBlue = i;
  3257. lpbi->bmiColors[i].rgbReserved = 0;
  3258. }
  3259. for(i=25;i<100;i++)
  3260. {
  3261. lpbi->bmiColors[i].rgbRed = BYTE((i-25)+i*1.7);
  3262. lpbi->bmiColors[i].rgbGreen = BYTE((i-25)+i*1.7);
  3263. lpbi->bmiColors[i].rgbBlue = 0;
  3264. lpbi->bmiColors[i].rgbReserved = 0;
  3265. }
  3266. for(i=100;i<255;i++)
  3267. {
  3268. lpbi->bmiColors[i].rgbRed = BYTE(i/2+(i-100)*0.8);
  3269. lpbi->bmiColors[i].rgbGreen = BYTE(i/2+(i-100)*0.8);
  3270. lpbi->bmiColors[i].rgbBlue = BYTE(i/2+(i-100)*0.8);
  3271. lpbi->bmiColors[i].rgbReserved = 0;
  3272. } pDIB += (sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
  3273. if(iDiff == 0)
  3274. {
  3275. memcpy(pDIB, pByte, iSize);
  3276. }
  3277. else
  3278. {
  3279. iDiff = iWidth - iDiff;
  3280. for(i = 0; i < abs(iHeight); i++)
  3281. {
  3282. memcpy(pDIB , pByte, iDiff);
  3283. pDIB += iWidth;
  3284. pByte += iDiff;
  3285. }
  3286. }
  3287. GlobalUnlock(hDIB);
  3288. return hDIB;
  3289. }
  3290. BOOL WINAPI DIBToPCX256(LPSTR lpDIB, LPCTSTR lpszPathName)
  3291. {
  3292. CFile file;
  3293. if(!file.Open(lpszPathName, CFile::modeWrite | CFile::modeCreate | CFile::shareExclusive))
  3294. {
  3295. AfxMessageBox("打开指定PCX文件时失败!", MB_ICONINFORMATION | MB_OK);
  3296. return FALSE;
  3297. }
  3298. // 循环变量
  3299. LONG i;
  3300. LONG j;
  3301. // DIB高度
  3302. WORD wHeight;
  3303. // DIB宽度
  3304. WORD wWidth;
  3305. // 中间变量
  3306. BYTE bChar1;
  3307. BYTE bChar2;
  3308. // 指向源图像象素的指针
  3309. BYTE * lpSrc;
  3310. // 指向编码后图像数据的指针
  3311. BYTE * lpDst;
  3312. // 图像每行的字节数
  3313. LONG lLineBytes;
  3314. // 重复像素计数
  3315. int iCount;
  3316. // 缓冲区已使用的字节数
  3317. DWORD dwBuffUsed;
  3318. // 指向DIB象素指针
  3319. LPSTR   lpDIBBits;
  3320. // 获取DIB高度
  3321. wHeight = (WORD) DIBHeight(lpDIB);
  3322. // 获取DIB宽度
  3323. wWidth  = (WORD) DIBWidth(lpDIB);
  3324. // 找到DIB图像象素起始位置
  3325. lpDIBBits = FindDIBBits(lpDIB);
  3326. // 计算图像每行的字节数
  3327. lLineBytes = WIDTHBYTES(wWidth * 8);
  3328. //*************************************************************************
  3329. // PCX文件头
  3330. PCXHEADER pcxHdr;
  3331. // 给文件头赋值
  3332. // PCX标识码
  3333. pcxHdr.bManufacturer = 0x0A;
  3334. // PCX版本号
  3335. pcxHdr.bVersion = 5;
  3336. // PCX编码方式(1表示RLE编码)
  3337. pcxHdr.bEncoding = 1;
  3338. // 像素位数(256色为8位)
  3339. pcxHdr.bBpp = 8;
  3340. // 图像相对于屏幕的左上角X坐标(以像素为单位)
  3341. pcxHdr.wLeft = 0;
  3342. // 图像相对于屏幕的左上角Y坐标(以像素为单位)
  3343. pcxHdr.wTop = 0;
  3344. // 图像相对于屏幕的右下角X坐标(以像素为单位)
  3345. pcxHdr.wRight = wWidth - 1;
  3346. // 图像相对于屏幕的右下角Y坐标(以像素为单位)
  3347. pcxHdr.wBottom = wHeight - 1;
  3348. // 图像的水平分辨率
  3349. pcxHdr.wXResolution = wWidth;
  3350. // 图像的垂直分辨率
  3351. pcxHdr.wYResolution = wHeight;
  3352. // 调色板数据(对于256色PCX无意义,直接赋值为0)
  3353. for (i = 0; i < 48; i ++)
  3354. {
  3355. pcxHdr.bPalette[i] = 0;
  3356. }
  3357. // 保留域,设定为0。
  3358. pcxHdr.bReserved = 0;
  3359. // 图像色彩平面数目(对于256色PCX设定为1)。
  3360. pcxHdr.bPlanes = 1;
  3361. // 图像的宽度(字节为单位),必须为偶数。
  3362. // if ((wWidth & 1) == 0)
  3363. // {
  3364. pcxHdr.wLineBytes = wWidth;
  3365. // }
  3366. // else
  3367. // {
  3368. // pcxHdr.wLineBytes = wWidth + 1;
  3369. // }
  3370. // 图像调色板的类型,1表示彩色或者单色图像,2表示图像是灰度图。
  3371. pcxHdr.wPaletteType = 1;
  3372. // 制作该图像的屏幕宽度(像素为单位)
  3373. pcxHdr.wSrcWidth = 0;
  3374. // 制作该图像的屏幕高度(像素为单位)
  3375. pcxHdr.wSrcDepth = 0;
  3376. // 保留域,取值设定为0。
  3377. for (i = 0; i < 54; i ++)
  3378. {
  3379. pcxHdr.bFiller[i] = 0;
  3380. }
  3381. // 写入文件头
  3382. file.Write((LPSTR)&pcxHdr, sizeof(PCXHEADER));
  3383. //*******************************************************************************
  3384. // 开始编码
  3385. // 开辟一片缓冲区(2被原始图像大小)以保存编码结果
  3386. lpDst = new BYTE[wHeight * wWidth * 2];
  3387. // 指明当前已经用了多少缓冲区(字节数)
  3388. dwBuffUsed = 0;
  3389. // 每行
  3390. for (i = 0; i < wHeight; i++)
  3391. {
  3392. // 指向DIB第i行,第0个象素的指针
  3393. lpSrc = (BYTE *)lpDIBBits + lLineBytes * (wHeight - 1 - i);
  3394. // 给bChar1赋值
  3395. bChar1 = *lpSrc;
  3396. // 设置iCount为1
  3397. iCount = 1;
  3398. // 剩余列
  3399. for (j = 1; j < wWidth; j ++)
  3400. {
  3401. // 指向DIB第i行,第j个象素的指针
  3402. lpSrc++;
  3403. // 读取下一个像素
  3404. bChar2 = *lpSrc;
  3405. // 判断是否和bChar1相同并且iCount < 63
  3406. if ((bChar1 == bChar2) && (iCount < 63))
  3407. {
  3408. // 相同,计数加1
  3409. iCount ++;
  3410. // 继续读下一个
  3411. }
  3412. else
  3413. {
  3414. // 不同,或者iCount = 63
  3415. // 写入缓冲区
  3416. if ((iCount > 1) || (bChar1 >= 0xC0))
  3417. {
  3418. // 保存码长信息
  3419. lpDst[dwBuffUsed] = iCount | 0xC0;
  3420. // 保存bChar1
  3421. lpDst[dwBuffUsed + 1] = bChar1;
  3422. // 更新dwBuffUsed
  3423. dwBuffUsed += 2;
  3424. }
  3425. else
  3426. {
  3427. // 直接保存该值
  3428. lpDst[dwBuffUsed] = bChar1;
  3429. // 更新dwBuffUsed
  3430. dwBuffUsed ++;
  3431. }
  3432. // 重新给bChar1赋值
  3433. bChar1 = bChar2;
  3434. // 设置iCount为1
  3435. iCount = 1;
  3436. }
  3437. }
  3438. // 保存每行最后一部分编码
  3439. if ((iCount > 1) || (bChar1 >= 0xC0))
  3440. {
  3441. // 保存码长信息
  3442. lpDst[dwBuffUsed] = iCount | 0xC0;
  3443. // 保存bChar1
  3444. lpDst[dwBuffUsed + 1] = bChar1;
  3445. // 更新dwBuffUsed
  3446. dwBuffUsed += 2;
  3447. }
  3448. else
  3449. {
  3450. // 直接保存该值
  3451. lpDst[dwBuffUsed] = bChar1;
  3452. // 更新dwBuffUsed
  3453. dwBuffUsed ++;
  3454. }
  3455. }
  3456. // 写入编码结果
  3457. file.WriteHuge((LPSTR)lpDst, dwBuffUsed);
  3458. // 释放内存
  3459. delete lpDst;
  3460. //**************************************************************************
  3461. // 写入调色板信息
  3462. // 指向BITMAPINFO结构的指针(Win3.0)
  3463. LPBITMAPINFO lpbmi;
  3464. // 指向BITMAPCOREINFO结构的指针
  3465. LPBITMAPCOREINFO lpbmc;
  3466. // 表明是否是Win3.0 DIB的标记
  3467. BOOL bWinStyleDIB;
  3468. // 开辟一片缓冲区以保存调色板
  3469. lpDst = new BYTE[769];
  3470. // 调色板起始字节
  3471. * lpDst = 0x0C;
  3472. // 获取指向BITMAPINFO结构的指针(Win3.0)
  3473. lpbmi = (LPBITMAPINFO)lpDIB;
  3474. // 获取指向BITMAPCOREINFO结构的指针
  3475. lpbmc = (LPBITMAPCOREINFO)lpDIB;
  3476. // 判断是否是WIN3.0的DIB
  3477. bWinStyleDIB = IS_WIN30_DIB(lpDIB);
  3478. // 读取当前DIB调色板
  3479. for (i = 0; i < 256; i ++)
  3480. {
  3481. if (bWinStyleDIB)
  3482. {
  3483. // 读取DIB调色板红色分量
  3484. lpDst[i * 3 + 1] = lpbmi->bmiColors[i].rgbRed;
  3485. // 读取DIB调色板绿色分量
  3486. lpDst[i * 3 + 2] = lpbmi->bmiColors[i].rgbGreen;
  3487. // 读取DIB调色板蓝色分量
  3488. lpDst[i * 3 + 3] = lpbmi->bmiColors[i].rgbBlue;
  3489. }
  3490. else
  3491. {
  3492. // 读取DIB调色板红色分量
  3493. lpDst[i * 3 + 1] = lpbmc->bmciColors[i].rgbtRed;
  3494. // 读取DIB调色板绿色分量
  3495. lpDst[i * 3 + 2] = lpbmc->bmciColors[i].rgbtGreen;
  3496. // 读取DIB调色板蓝色分量
  3497. lpDst[i * 3 + 3] = lpbmc->bmciColors[i].rgbtBlue;
  3498. }
  3499. }
  3500. // 写入调色板信息
  3501. file.Write((LPSTR)lpDst, 769);
  3502. delete lpDst;
  3503. file.Close();
  3504. // 返回
  3505. return TRUE;
  3506. }
  3507. /*************************************************************************
  3508.  *
  3509.  * 函数名称:
  3510.  *   ReadPCX256()
  3511.  *
  3512.  * 参数:
  3513.  *   CFile& file        - 要读取的文件
  3514.  *
  3515.  * 返回值:
  3516.  *   HDIB               - 成功返回DIB的句柄,否则返回NULL。
  3517.  *
  3518.  * 说明:
  3519.  *   该函数将读取指定的256色PCX文件。将读取的结果保存在一个未压缩
  3520.  * 编码的DIB对象中。
  3521.  *
  3522.  *************************************************************************/
  3523. HDIB WINAPI ReadPCX256(LPCTSTR lpszPathName)
  3524. {
  3525. CFile file;
  3526. if(!file.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite))
  3527. {
  3528. AfxMessageBox("打开指定PCX文件时失败!", MB_ICONINFORMATION | MB_OK);
  3529. return NULL;
  3530. }
  3531. // PCX文件头
  3532. PCXHEADER pcxHdr;
  3533. // DIB大小(字节数)
  3534. DWORD dwDIBSize;
  3535. // DIB句柄
  3536. HDIB hDIB;
  3537. // DIB指针
  3538. LPSTR pDIB;
  3539. // 循环变量
  3540. LONG i;
  3541. LONG j;
  3542. // 重复像素计数
  3543. int iCount;
  3544. // DIB高度
  3545. WORD wHeight;
  3546. // DIB宽度
  3547. WORD wWidth;
  3548. // 图像每行的字节数
  3549. LONG lLineBytes;
  3550. // 中间变量
  3551. BYTE bChar;
  3552. // 指向源图像象素的指针
  3553. BYTE * lpSrc;
  3554. // 指向编码后图像数据的指针
  3555. BYTE * lpDst;
  3556. // 临时指针
  3557. BYTE * lpTemp;
  3558. // 尝试读取PCX文件头
  3559. if (file.Read((LPSTR)&pcxHdr, sizeof(PCXHEADER)) != sizeof(PCXHEADER))
  3560. {
  3561. // 大小不对,返回NULL。
  3562. file.Close();
  3563. return NULL;
  3564. }
  3565. // 判断是否是256色PCX文件,检查第一个字节是否是0x0A,
  3566. if ((pcxHdr.bManufacturer != 0x0A) || (pcxHdr.bBpp != 8) || (pcxHdr.bPlanes != 1))
  3567. {
  3568. // 非256色PCX文件,返回NULL。
  3569. file.Close();
  3570. return NULL;
  3571. }
  3572. // 获取图像高度
  3573. wHeight = pcxHdr.wBottom - pcxHdr.wTop + 1;
  3574. // 获取图像宽度
  3575. wWidth  = pcxHdr.wRight - pcxHdr.wLeft + 1;
  3576. // 计算图像每行的字节数
  3577. lLineBytes = WIDTHBYTES(wWidth * 8);
  3578. // 计算DIB长度(字节)
  3579. dwDIBSize = sizeof(BITMAPINFOHEADER) + 1024 + wHeight * lLineBytes;
  3580. // 为DIB分配内存
  3581. hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIBSize);
  3582. if (hDIB == 0)
  3583. {
  3584. file.Close();
  3585. // 内存分配失败,返回NULL。
  3586. return NULL;
  3587. }
  3588. // 锁定
  3589. pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
  3590. // 指向BITMAPINFOHEADER的指针
  3591. LPBITMAPINFOHEADER lpBI;
  3592. // 赋值
  3593. lpBI = (LPBITMAPINFOHEADER) pDIB;
  3594. // 给lpBI成员赋值
  3595. lpBI->biSize = 40;
  3596. lpBI->biWidth = wWidth;
  3597. lpBI->biHeight = wHeight;
  3598. lpBI->biPlanes = 1;
  3599. lpBI->biBitCount = 8;
  3600. lpBI->biCompression = BI_RGB;
  3601. lpBI->biSizeImage = wHeight * lLineBytes;
  3602. lpBI->biXPelsPerMeter = pcxHdr.wXResolution;
  3603. lpBI->biYPelsPerMeter = pcxHdr.wYResolution;
  3604. lpBI->biClrUsed = 0;
  3605. lpBI->biClrImportant = 0;
  3606. // 分配内存以读取编码后的象素
  3607. lpSrc = new BYTE[file.GetLength() - sizeof(PCXHEADER) - 769];
  3608. lpTemp = lpSrc;
  3609. // 读取编码后的象素
  3610. if (file.ReadHuge(lpSrc, file.GetLength() - sizeof(PCXHEADER) - 769) !=
  3611. file.GetLength() - sizeof(PCXHEADER) - 769 )
  3612. {
  3613. // 大小不对。
  3614. // 解除锁定
  3615. ::GlobalUnlock((HGLOBAL) hDIB);
  3616. // 释放内存
  3617. ::GlobalFree((HGLOBAL) hDIB);
  3618. // 返回NULL。
  3619. file.Close();
  3620. return NULL;
  3621. }
  3622. // 计算DIB中像素位置
  3623. lpDst = (BYTE *) FindDIBBits(pDIB);
  3624. // 一行一行解码
  3625. for (j = 0; j <wHeight; j++)
  3626. {
  3627. i = 0;
  3628. while (i < wWidth)
  3629. {
  3630. // 读取一个字节
  3631. bChar = *lpTemp;
  3632. lpTemp++;
  3633. if ((bChar & 0xC0) == 0xC0)
  3634. {
  3635. // 行程
  3636. iCount = bChar & 0x3F;
  3637. // 读取下一个字节
  3638. bChar = *lpTemp;
  3639. lpTemp++;
  3640. // bChar重复iCount次保存
  3641. memset(&lpDst[(wHeight - j - 1) * lLineBytes + i], bChar, iCount);
  3642. // 已经读取像素的个数加iCount
  3643. i += iCount;
  3644. }
  3645. else
  3646. {
  3647. // 保存当前字节
  3648. lpDst[(wHeight - j - 1) * lLineBytes + i] = bChar;
  3649. // 已经读取像素的个数加1
  3650. i += 1;
  3651. }
  3652. }
  3653. }
  3654. // 释放内存
  3655. delete lpSrc;
  3656. //*************************************************************
  3657. // 调色板
  3658. // 读调色板标志位
  3659. file.Read(&bChar, 1);
  3660. if (bChar != 0x0C)
  3661. {
  3662. // 出错
  3663. // 解除锁定
  3664. ::GlobalUnlock((HGLOBAL) hDIB);
  3665. // 释放内存
  3666. ::GlobalFree((HGLOBAL) hDIB);
  3667. // 返回NULL。
  3668. file.Close();
  3669. return NULL;
  3670. }
  3671. // 分配内存以读取编码后的象素
  3672. lpSrc = new BYTE[768];
  3673. // 计算DIB中调色板的位置
  3674. lpDst = (BYTE *) pDIB + sizeof(BITMAPINFOHEADER);
  3675. // 读取调色板
  3676. if (file.Read(lpSrc, 768) != 768)
  3677. {
  3678. // 大小不对。
  3679. // 解除锁定
  3680. ::GlobalUnlock((HGLOBAL) hDIB);
  3681. // 释放内存
  3682. ::GlobalFree((HGLOBAL) hDIB);
  3683. // 返回NULL。
  3684. file.Close();
  3685. return NULL;
  3686. }
  3687. // 给调色板赋值
  3688. for (i = 0; i < 256; i++)
  3689. {
  3690. lpDst[i * 4] = lpSrc[i * 3 + 2];
  3691. lpDst[i * 4 + 1] = lpSrc[i * 3 + 1];
  3692. lpDst[i * 4 + 2] = lpSrc[i * 3];
  3693. lpDst[i * 4 + 3] = 0;
  3694. }
  3695. // 释放内存
  3696. delete lpSrc;
  3697. // 解除锁定
  3698. ::GlobalUnlock((HGLOBAL) hDIB);
  3699. file.Close();
  3700. // 返回DIB句柄
  3701. return hDIB;
  3702. }