IP.cpp
Upload User: hbtiangong
Upload Date: 2009-03-29
Package Size: 255k
Code Size: 50k
Category:

Windows Develop

Development Platform:

Visual C++

  1. #include "stdafx.h"
  2. #include <math.h>
  3. #include "dibapi.h"
  4. // Definitions required for convolution image filtering
  5. #define KERNELCOLS 3
  6. #define KERNELROWS 3
  7. #define KERNELELEMENTS (KERNELCOLS * KERNELROWS)
  8. // struct for convolute kernel 
  9. typedef struct 
  10. {
  11.   int Element[KERNELELEMENTS];
  12.   int Divisor;
  13. } KERNEL;
  14. // The following kernel definitions are for convolution filtering.
  15. // Kernel entries are specified with a divisor to get around the
  16. // requirement for floating point numbers in the low pass filters. 
  17. KERNEL HP1 = {                    // HP filter #1
  18.   {-1, -1, -1,
  19.    -1,  9, -1,
  20.    -1, -1, -1},
  21.     1                             // Divisor = 1
  22. };
  23. KERNEL HP2 = {                    // HP filter #2
  24.   { 0, -1,  0,
  25.    -1,  5, -1,
  26.     0, -1,  0},
  27.     1                             // Divisor = 1
  28. };
  29. KERNEL HP3 = {                    // HP filter #3
  30.   { 1, -2,  1,
  31.    -2,  5, -2,
  32.     1, -2,  1},
  33.     1                             // Divisor = 1
  34. };
  35. KERNEL LP1 = {                    // LP filter #1
  36.   { 1,  1,  1,
  37.     1,  1,  1,
  38.     1,  1,  1},
  39.     9                             // Divisor = 9
  40. };
  41. KERNEL LP2 = {                    // LP filter #2
  42.   { 1,  1,  1,
  43.     1,  2,  1,
  44.     1,  1,  1},
  45.     10                            // Divisor = 10
  46. };
  47. KERNEL LP3 = {                    // LP filter #3
  48.   { 1,  2,  1,
  49.     2,  4,  2,
  50.     1,  2,  1},
  51.     16                            // Divisor = 16
  52. };
  53. KERNEL VertEdge = {              // Vertical edge
  54.   { 0,  0,  0,
  55.     -1, 1,  0,
  56.     0,  0,  0},
  57.     1                             // Divisor = 1
  58. };
  59. KERNEL HorzEdge = {              // Horizontal edge
  60.   { 0,  -1,  0,
  61.     0,  1,  0,
  62.     0,  0,  0},
  63.     1                             // Divisor = 1
  64. };
  65. KERNEL VertHorzEdge = {           // Vertical Horizontal edge
  66.   { -1, 0,  0,
  67.     0,  1,  0,
  68.     0,  0,  0},
  69.     1                             // Divisor = 1
  70. };
  71. KERNEL EdgeNorth = {              // North gradient
  72.   { 1,  1,  1,
  73.     1, -2,  1,
  74.    -1, -1, -1},
  75.     1                             // Divisor = 1
  76. };
  77. KERNEL EdgeNorthEast = {          // North East gradient
  78.   { 1,  1,  1,
  79.    -1, -2,  1,
  80.    -1, -1,  1},
  81.     1                             // Divisor = 1
  82. };
  83. KERNEL EdgeEast = {               // East gradient
  84.   {-1,  1,  1,
  85.    -1, -2,  1,
  86.    -1,  1,  1},
  87.     1                             // Divisor = 1
  88. };
  89. KERNEL EdgeSouthEast = {          // South East gradient
  90.   {-1, -1,  1,
  91.    -1, -2,  1,
  92.     1,  1,  1},
  93.     1                             // Divisor = 1
  94. };
  95. KERNEL EdgeSouth = {              // South gadient
  96.   {-1, -1, -1,
  97.     1, -2,  1,
  98.     1,  1,  1},
  99.     1                             // Divisor = 1
  100. };
  101. KERNEL EdgeSouthWest = {          // South West gradient
  102.   { 1, -1, -1,
  103.     1, -2, -1,
  104.     1,  1,  1},
  105.     1                             // Divisor = 1
  106. };
  107. KERNEL EdgeWest = {               // West gradient
  108.   { 1,  1, -1,
  109.     1, -2, -1,
  110.     1,  1, -1},
  111.     1                             // Divisor = 1
  112. };
  113. KERNEL EdgeNorthWest = {          // North West gradient
  114.   { 1,  1,  1,
  115.     1, -2, -1,
  116.     1, -1, -1},
  117.     1                             // Divisor = 1
  118. };
  119. KERNEL Lap1 = {   // Laplace filter 1
  120.   { 0,  1,  0,
  121.     1, -4,  1,
  122.     0,  1,  0},
  123.     1                             // Divisor = 1
  124. };
  125. KERNEL Lap2 = {   // Laplace filter 2
  126.   { -1, -1, -1,
  127.     -1,  8, -1,
  128.     -1, -1, -1},
  129.     1                             // Divisor = 1
  130. };
  131. KERNEL Lap3 = {   // Laplace filter 3
  132.   { -1, -1, -1,
  133.     -1,  9, -1,
  134.     -1, -1, -1},
  135.     1                             // Divisor = 1
  136. };
  137. KERNEL Lap4 = {   // Laplace filter 4
  138.   { 1, -2, 1,
  139.     -2, 4, -2,
  140.     1, -2, 1},
  141.     1                             // Divisor = 1
  142. };
  143. KERNEL Sobel[4] = {
  144. {                    // Sobel1
  145. {-1, 0, 1,
  146.  -2, 0, 2,
  147.  -1, 0, 1},
  148. 1                             // Divisor = 1
  149. },
  150. {                    // Sobel2
  151. {-1, -2, -1,
  152.   0,  0,  0,
  153.   1,  2,  1},
  154. 1                             // Divisor = 1
  155. },
  156. {                    // Sobel3
  157. {-2, -1, 0,
  158.  -1,  0, 1,
  159.   0,  1, 2},
  160. 1                             // Divisor = 1
  161. },
  162. {                    // Sobel4
  163. {0, -1, -2,
  164.  1,  0, -1,
  165.  2,  1, 0},
  166. 1                             // Divisor = 1
  167. }
  168. };
  169. KERNEL Hough[4] = {
  170. {                    // Hough1
  171. {-1, 0, 1,
  172.  -1, 0, 1,
  173.  -1, 0, 1},
  174. 1                             // Divisor = 1
  175. },
  176. {                    // Hough2
  177. {-1, -1, 0,
  178.  -1,  0, 1,
  179.   0,  1, 1},
  180. 1                             // Divisor = 1
  181. },
  182. {                    // Hough3
  183. {-1, -1, -1,
  184.   0,  0, 0,
  185.   1,  1, 1},
  186. 1                             // Divisor = 1
  187. },
  188. {                    // Hough4
  189. {0, -1, -1,
  190.  1,  0, -1,
  191.  1,  1, 0},
  192. 1                             // Divisor = 1
  193. }
  194. };
  195. // local use macro
  196. #define PIXEL_OFFSET(i, j, nWidthBytes)
  197. (LONG)((LONG)(i)*(LONG)(nWidthBytes) + (LONG)(j)*3)
  198. // local function prototype
  199. int compare(const void *e1, const void *e2);
  200. void DoMedianFilterDIB(int *red, int *green, int *blue, int i, int j, 
  201. WORD wBytesPerLine, LPBYTE lpDIBits);
  202. void DoConvoluteDIB(int *red, int *green, int *blue, int i, int j, 
  203. WORD wBytesPerLine, LPBYTE lpDIBits, KERNEL *lpKernel);
  204. BOOL ConvoluteDIB(HDIB hDib, KERNEL *lpKernel, int Strength, int nKernelNum=1);
  205. // function body
  206. /************************************************************************* 
  207.  * 
  208.  * HighPassDIB() 
  209.  * 
  210.  * Parameters: 
  211.  * 
  212.  * HDIB hDib        - objective DIB handle
  213.  * int nAlgorithm   - specify the filter to use
  214.  * int Strength     - operation strength set to the convolute
  215.  * 
  216.  * Return Value: 
  217.  * 
  218.  * BOOL             - True is success, else False
  219.  * 
  220.  * Description: 
  221.  * 
  222.  * High pass filtering to sharp DIB
  223.  * 
  224.  ************************************************************************/ 
  225. BOOL HighPassDIB(HDIB hDib, int Strength, int nAlgorithm) 
  226. {
  227. switch (nAlgorithm)
  228. {
  229. case FILTER1:
  230. return ConvoluteDIB(hDib, &HP1, Strength);
  231. case FILTER2:
  232. return ConvoluteDIB(hDib, &HP2, Strength);
  233. case FILTER3:
  234. return ConvoluteDIB(hDib, &HP3, Strength);
  235. }
  236. return FALSE;
  237. }
  238. /************************************************************************* 
  239.  * 
  240.  * LowPassDIB() 
  241.  * 
  242.  * Parameters: 
  243.  * 
  244.  * HDIB hDib        - objective DIB handle
  245.  * int nAlgorithm   - specify the filter to use
  246.  * int Strength     - operation strength set to the convolute
  247.  * 
  248.  * Return Value: 
  249.  * 
  250.  * BOOL             - True is success, else False
  251.  * 
  252.  * Description: 
  253.  * 
  254.  * Low pass filtering to blur DIB
  255.  * 
  256.  ************************************************************************/ 
  257. BOOL LowPassDIB(HDIB hDib, int Strength, int nAlgorithm) 
  258. {
  259. switch (nAlgorithm)
  260. {
  261. case FILTER1:
  262. return ConvoluteDIB(hDib, &LP1, Strength);
  263. case FILTER2:
  264. return ConvoluteDIB(hDib, &LP2, Strength);
  265. case FILTER3:
  266. return ConvoluteDIB(hDib, &LP3, Strength);
  267. }
  268. return FALSE;
  269. }
  270. /************************************************************************* 
  271.  * 
  272.  * EdgeEnhanceDIB() 
  273.  * 
  274.  * Parameters: 
  275.  * 
  276.  * HDIB hDib        - objective DIB handle
  277.  * int nAlgorithm   - specify the filter to use
  278.  * int Strength     - operation strength set to the convolute
  279.  * 
  280.  * Return Value: 
  281.  * 
  282.  * BOOL             - True is success, else False
  283.  * 
  284.  * Description: 
  285.  * 
  286.  * Edge enhance DIB
  287.  * 
  288.  ************************************************************************/ 
  289. BOOL EdgeEnhanceDIB(HDIB hDib, int Strength, int nAlgorithm)
  290. {
  291. switch (nAlgorithm)
  292. {
  293. case VERT:
  294. return ConvoluteDIB(hDib, &VertEdge, Strength);
  295. case HORZ:
  296. return ConvoluteDIB(hDib, &HorzEdge, Strength);
  297. case VERTHORZ:
  298. return ConvoluteDIB(hDib, &VertHorzEdge, Strength);
  299. case NORTH:
  300. return ConvoluteDIB(hDib, &EdgeNorth, Strength);
  301. case NORTHEAST:
  302. return ConvoluteDIB(hDib, &EdgeNorthEast, Strength);
  303. case EAST:
  304. return ConvoluteDIB(hDib, &EdgeEast, Strength);
  305. case SOUTH:
  306. return ConvoluteDIB(hDib, &EdgeSouth, Strength);
  307. case SOUTHEAST:
  308. return ConvoluteDIB(hDib, &EdgeSouthEast, Strength);
  309. case SOUTHWEST:
  310. return ConvoluteDIB(hDib, &EdgeSouthWest, Strength);
  311. case WEST:
  312. return ConvoluteDIB(hDib, &EdgeWest, Strength);
  313. case NORTHWEST:
  314. return ConvoluteDIB(hDib, &EdgeNorthWest, Strength);
  315. case LAP1:
  316. return ConvoluteDIB(hDib, &Lap1, Strength);
  317. case LAP2:
  318. return ConvoluteDIB(hDib, &Lap2, Strength);
  319. case LAP3:
  320. return ConvoluteDIB(hDib, &Lap3, Strength);
  321. case LAP4:
  322. return ConvoluteDIB(hDib, &Lap4, Strength);
  323. case SOBEL:
  324. return ConvoluteDIB(hDib, Sobel, Strength, 4);
  325. case HOUGH:
  326. return ConvoluteDIB(hDib, Hough, Strength, 4);
  327. }
  328. return FALSE;
  329. }
  330. /************************************************************************* 
  331.  * 
  332.  * MedianFilterDIB() 
  333.  * 
  334.  * Parameters: 
  335.  * 
  336.  * HDIB hDib        - objective DIB handle
  337.  * 
  338.  * Return Value: 
  339.  * 
  340.  * BOOL             - True is success, else False
  341.  * 
  342.  * Description: 
  343.  * 
  344.  * This is the media filtering function to DIB
  345.  * 
  346.  ************************************************************************/ 
  347. BOOL MedianFilterDIB(HDIB hDib) 
  348. {
  349. WaitCursorBegin();
  350. HDIB hNewDib = NULL;
  351. // we only convolute 24bpp DIB, so first convert DIB to 24bpp
  352. WORD wBitCount = DIBBitCount(hDib);
  353. if (wBitCount != 24)
  354. hNewDib = ConvertDIBFormat(hDib, 24, NULL);
  355. else
  356. hNewDib = CopyHandle(hDib);
  357. if (! hNewDib)
  358. {
  359. WaitCursorEnd();
  360. return FALSE;
  361. }
  362. // new DIB attributes
  363. WORD wDIBWidth = (WORD)DIBWidth(hNewDib);
  364. WORD wDIBHeight = (WORD)DIBHeight(hNewDib);
  365. WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib);
  366. DWORD dwImageSize = wBytesPerLine * wDIBHeight;
  367. // Allocate and lock memory for filtered image data
  368. HGLOBAL hFilteredBits = GlobalAlloc(GHND, dwImageSize);
  369. if (!hFilteredBits) 
  370. {
  371. WaitCursorEnd();
  372. return FALSE;
  373. }
  374. LPBYTE lpDestImage = (LPBYTE)GlobalLock(hFilteredBits);
  375. // get bits address in DIB
  376. LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib);
  377. LPBYTE lpDIBits = FindDIBBits(lpDIB);
  378. // convolute...
  379. for (int i=1; i<wDIBHeight-1; i++) 
  380. for (int j=1; j<wDIBWidth-1; j++) 
  381. {
  382. int  red=0, green=0, blue=0; 
  383. DoMedianFilterDIB(&red, &green, &blue, i, j, wBytesPerLine, lpDIBits);
  384. LONG lOffset= PIXEL_OFFSET(i,j, wBytesPerLine);
  385. *(lpDestImage + lOffset++) = BOUND(blue, 0, 255);
  386. *(lpDestImage + lOffset++) = BOUND(green, 0, 255);
  387. *(lpDestImage + lOffset)   = BOUND(red, 0, 255);
  388. }
  389. // a filtered image is available in lpDestImage
  390. // copy it to DIB bits
  391. memcpy(lpDIBits, lpDestImage, dwImageSize);
  392. // cleanup temp buffers
  393. GlobalUnlock(hFilteredBits);
  394. GlobalFree(hFilteredBits);
  395. GlobalUnlock(hNewDib);
  396. // rebuild hDib
  397. HDIB hTmp = NULL;
  398. if (wBitCount != 24)
  399. hTmp = ConvertDIBFormat(hNewDib, wBitCount, NULL);
  400. else
  401. hTmp = CopyHandle(hNewDib);
  402. GlobalFree(hNewDib);
  403. DWORD dwSize = GlobalSize(hTmp);
  404. memcpy((LPBYTE)GlobalLock(hDib), (LPBYTE)GlobalLock(hTmp), dwSize);
  405. GlobalUnlock(hTmp);
  406. GlobalFree(hTmp);
  407. GlobalUnlock(hDib);
  408. WaitCursorEnd();
  409. return TRUE;
  410. }
  411. /************************************************************************* 
  412.  * 
  413.  * ConvoluteDIB() 
  414.  * 
  415.  * Parameters: 
  416.  * 
  417.  * HDIB hDib        - objective DIB handle
  418.  * KERNEL *lpKernel - pointer of kernel used to convolute with DIB
  419.  * int Strength     - operation strength set to the convolute
  420.  * int nKernelNum   - kernel number used to convolute
  421.  * 
  422.  * Return Value: 
  423.  * 
  424.  * BOOL             - True is success, else False
  425.  * 
  426.  * Description: 
  427.  * 
  428.  * This is the generic convolute function to DIB
  429.  * 
  430.  ************************************************************************/ 
  431. BOOL ConvoluteDIB(HDIB hDib, KERNEL *lpKernel, int Strength, int nKernelNum) 
  432. {
  433. WaitCursorBegin();
  434. HDIB hNewDib = NULL;
  435. // we only convolute 24bpp DIB, so first convert DIB to 24bpp
  436. WORD wBitCount = DIBBitCount(hDib);
  437. if (wBitCount != 24)
  438. hNewDib = ConvertDIBFormat(hDib, 24, NULL);
  439. else
  440. hNewDib = CopyHandle(hDib);
  441. if (! hNewDib)
  442. {
  443. WaitCursorEnd();
  444. return FALSE;
  445. }
  446. // new DIB attributes
  447. WORD wDIBWidth = (WORD)DIBWidth(hNewDib);
  448. WORD wDIBHeight = (WORD)DIBHeight(hNewDib);
  449. WORD wBytesPerLine = (WORD)BytesPerLine(hNewDib);
  450. DWORD dwImageSize = wBytesPerLine * wDIBHeight;
  451. // Allocate and lock memory for filtered image data
  452. HGLOBAL hFilteredBits = GlobalAlloc(GHND, dwImageSize);
  453. if (!hFilteredBits) 
  454. {
  455. WaitCursorEnd();
  456. return FALSE;
  457. }
  458. LPBYTE lpDestImage = (LPBYTE)GlobalLock(hFilteredBits);
  459. // get bits address in DIB
  460. LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib);
  461. LPBYTE lpDIBits = FindDIBBits(lpDIB);
  462. // convolute...
  463. for (int i=1; i<wDIBHeight-1; i++) 
  464. for (int j=1; j<wDIBWidth-1; j++) 
  465. {
  466. int  red=0, green=0, blue=0; 
  467. for (int k=0; k<nKernelNum; ++k)
  468. {
  469. int r=0, g=0, b=0; 
  470. DoConvoluteDIB(&r, &g, &b, i, j, 
  471. wBytesPerLine, lpDIBits, lpKernel+k);
  472. if (r > red)
  473. red = r;
  474. if (g > green)
  475. green = g;
  476. if (b > blue)
  477. blue = b;
  478. //red += r; green += g; blue += b;
  479. }
  480. // original RGB value in center pixel  (j, i)
  481. LONG lOffset= PIXEL_OFFSET(i,j, wBytesPerLine);
  482. BYTE OldB = *(lpDIBits + lOffset++);
  483. BYTE OldG = *(lpDIBits + lOffset++);
  484. BYTE OldR = *(lpDIBits + lOffset);
  485. // When we get here, red, green and blue have the new RGB value.
  486. if (Strength != 10) 
  487. {
  488. // Interpolate pixel data
  489. red   = OldR + (((red - OldR) * Strength) / 10);
  490. green = OldG + (((green - OldG) * Strength) / 10);
  491. blue  = OldB + (((blue - OldB) * Strength) / 10);
  492. }
  493. lOffset= PIXEL_OFFSET(i,j, wBytesPerLine);
  494. *(lpDestImage + lOffset++) = BOUND(blue, 0, 255);
  495. *(lpDestImage + lOffset++) = BOUND(green, 0, 255);
  496. *(lpDestImage + lOffset)   = BOUND(red, 0, 255);
  497. }
  498. // a filtered image is available in lpDestImage
  499. // copy it to DIB bits
  500. memcpy(lpDIBits, lpDestImage, dwImageSize);
  501. // cleanup temp buffers
  502. GlobalUnlock(hFilteredBits);
  503. GlobalFree(hFilteredBits);
  504. GlobalUnlock(hNewDib);
  505. // rebuild hDib
  506. HDIB hTmp = NULL;
  507. if (wBitCount != 24)
  508. hTmp = ConvertDIBFormat(hNewDib, wBitCount, NULL);
  509. else
  510. hTmp = CopyHandle(hNewDib);
  511. GlobalFree(hNewDib);
  512. DWORD dwSize = GlobalSize(hTmp);
  513. memcpy((LPBYTE)GlobalLock(hDib), (LPBYTE)GlobalLock(hTmp), dwSize);
  514. GlobalUnlock(hTmp);
  515. GlobalFree(hTmp);
  516. GlobalUnlock(hDib);
  517. WaitCursorEnd();
  518. return TRUE;
  519. }
  520. // local function: perform convolution to DIB with a kernel
  521. void DoConvoluteDIB(int *red, int *green, int *blue, int i, int j, 
  522. WORD wBytesPerLine, LPBYTE lpDIBits, KERNEL *lpKernel)
  523. {
  524. BYTE b[9], g[9], r[9];
  525. LONG lOffset;
  526. lOffset= PIXEL_OFFSET(i-1,j-1, wBytesPerLine);
  527. b[0] = *(lpDIBits + lOffset++);
  528. g[0] = *(lpDIBits + lOffset++);
  529. r[0] = *(lpDIBits + lOffset);
  530. lOffset= PIXEL_OFFSET(i-1,j, wBytesPerLine);
  531. b[1] = *(lpDIBits + lOffset++);
  532. g[1] = *(lpDIBits + lOffset++);
  533. r[1] = *(lpDIBits + lOffset);
  534. lOffset= PIXEL_OFFSET(i-1,j+1, wBytesPerLine);
  535. b[2] = *(lpDIBits + lOffset++);
  536. g[2] = *(lpDIBits + lOffset++);
  537. r[2] = *(lpDIBits + lOffset);
  538. lOffset= PIXEL_OFFSET(i,j-1, wBytesPerLine);
  539. b[3] = *(lpDIBits + lOffset++);
  540. g[3] = *(lpDIBits + lOffset++);
  541. r[3] = *(lpDIBits + lOffset);
  542. lOffset= PIXEL_OFFSET(i,j, wBytesPerLine);
  543. b[4] = *(lpDIBits + lOffset++);
  544. g[4] = *(lpDIBits + lOffset++);
  545. r[4] = *(lpDIBits + lOffset);
  546. lOffset= PIXEL_OFFSET(i,j+1, wBytesPerLine);
  547. b[5] = *(lpDIBits + lOffset++);
  548. g[5] = *(lpDIBits + lOffset++);
  549. r[5] = *(lpDIBits + lOffset);
  550. lOffset= PIXEL_OFFSET(i+1,j-1, wBytesPerLine);
  551. b[6] = *(lpDIBits + lOffset++);
  552. g[6] = *(lpDIBits + lOffset++);
  553. r[6] = *(lpDIBits + lOffset);
  554. lOffset= PIXEL_OFFSET(i+1,j, wBytesPerLine);
  555. b[7] = *(lpDIBits + lOffset++);
  556. g[7] = *(lpDIBits + lOffset++);
  557. r[7] = *(lpDIBits + lOffset);
  558. lOffset= PIXEL_OFFSET(i+1,j+1, wBytesPerLine);
  559. b[8] = *(lpDIBits + lOffset++);
  560. g[8] = *(lpDIBits + lOffset++);
  561. r[8] = *(lpDIBits + lOffset);
  562. *red = *green = *blue = 0;
  563. for (int k=0; k<8; ++k)
  564. {
  565. *red   += lpKernel->Element[k]*r[k];
  566. *green += lpKernel->Element[k]*g[k];
  567. *blue  += lpKernel->Element[k]*b[k];
  568. }
  569. if (lpKernel->Divisor != 1) 
  570. {
  571. *red   /= lpKernel->Divisor;
  572. *green /= lpKernel->Divisor;
  573. *blue  /= lpKernel->Divisor;
  574. }
  575. // getoff opposite
  576. *red   = abs(*red);
  577. *green = abs(*green);
  578. *blue  = abs(*blue);
  579. }
  580. // local function: perform median filter to DIB
  581. void DoMedianFilterDIB(int *red, int *green, int *blue, int i, int j, 
  582. WORD wBytesPerLine, LPBYTE lpDIBits)
  583. {
  584. BYTE b[9], g[9], r[9];
  585. LONG lOffset;
  586. lOffset= PIXEL_OFFSET(i-1,j-1, wBytesPerLine);
  587. b[0] = *(lpDIBits + lOffset++);
  588. g[0] = *(lpDIBits + lOffset++);
  589. r[0] = *(lpDIBits + lOffset);
  590. lOffset= PIXEL_OFFSET(i-1,j, wBytesPerLine);
  591. b[1] = *(lpDIBits + lOffset++);
  592. g[1] = *(lpDIBits + lOffset++);
  593. r[1] = *(lpDIBits + lOffset);
  594. lOffset= PIXEL_OFFSET(i-1,j+1, wBytesPerLine);
  595. b[2] = *(lpDIBits + lOffset++);
  596. g[2] = *(lpDIBits + lOffset++);
  597. r[2] = *(lpDIBits + lOffset);
  598. lOffset= PIXEL_OFFSET(i,j-1, wBytesPerLine);
  599. b[3] = *(lpDIBits + lOffset++);
  600. g[3] = *(lpDIBits + lOffset++);
  601. r[3] = *(lpDIBits + lOffset);
  602. lOffset= PIXEL_OFFSET(i,j, wBytesPerLine);
  603. b[4] = *(lpDIBits + lOffset++);
  604. g[4] = *(lpDIBits + lOffset++);
  605. r[4] = *(lpDIBits + lOffset);
  606. lOffset= PIXEL_OFFSET(i,j+1, wBytesPerLine);
  607. b[5] = *(lpDIBits + lOffset++);
  608. g[5] = *(lpDIBits + lOffset++);
  609. r[5] = *(lpDIBits + lOffset);
  610. lOffset= PIXEL_OFFSET(i+1,j-1, wBytesPerLine);
  611. b[6] = *(lpDIBits + lOffset++);
  612. g[6] = *(lpDIBits + lOffset++);
  613. r[6] = *(lpDIBits + lOffset);
  614. lOffset= PIXEL_OFFSET(i+1,j, wBytesPerLine);
  615. b[7] = *(lpDIBits + lOffset++);
  616. g[7] = *(lpDIBits + lOffset++);
  617. r[7] = *(lpDIBits + lOffset);
  618. lOffset= PIXEL_OFFSET(i+1,j+1, wBytesPerLine);
  619. b[8] = *(lpDIBits + lOffset++);
  620. g[8] = *(lpDIBits + lOffset++);
  621. r[8] = *(lpDIBits + lOffset);
  622.     qsort(r, 9, 1, compare);
  623.     qsort(g, 9, 1, compare);
  624.     qsort(b, 9, 1, compare);
  625. *red   = r[0];
  626. *green = g[0];
  627. *blue  = b[0];
  628. }
  629. // function used to sort in the call of qsort
  630. int compare(const void *e1, const void *e2)
  631. {
  632. if (*(BYTE *)e1 < *(BYTE *)e2)
  633. return -1;
  634. if (*(BYTE *)e1 > *(BYTE *)e2)
  635. return 1;
  636. return 0;
  637. }
  638. /************************************************************************* 
  639.  * 
  640.  * ReverseDIB() 
  641.  * 
  642.  * Parameters: 
  643.  * 
  644.  * HDIB hDib        - objective DIB handle
  645.  * 
  646.  * Return Value: 
  647.  * 
  648.  * BOOL             - True is success, else False
  649.  * 
  650.  * Description: 
  651.  * 
  652.  * This function reverse DIB
  653.  * 
  654.  ************************************************************************/ 
  655. BOOL ReverseDIB(HDIB hDib) 
  656. {
  657. WaitCursorBegin();
  658. HDIB hNewDib = NULL;
  659. // only support 256 grayscale image
  660. WORD wBitCount = DIBBitCount(hDib);
  661. if (wBitCount != 8)
  662. {
  663. WaitCursorEnd();
  664. return FALSE;
  665. }
  666. // the maxium pixel value
  667. int  nMaxValue = 256;
  668. // source pixel data
  669.     LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDib);
  670. if (! lpSrcDIB)
  671. {
  672. WaitCursorBegin();
  673. return FALSE;
  674. }
  675. // new DIB attributes
  676. LPSTR lpPtr;
  677. LONG lHeight = DIBHeight(lpSrcDIB);
  678. LONG lWidth = DIBWidth(lpSrcDIB);
  679. DWORD dwBufferSize = GlobalSize(lpSrcDIB);
  680. int nLineBytes = BytesPerLine(lpSrcDIB);
  681. // convolute...
  682. for (long i=0; i<lHeight; i++) 
  683. for (long j=0; j<lWidth; j++) 
  684. {
  685. lpPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-i*nLineBytes)+j;
  686. *lpPtr = nMaxValue - *lpPtr;
  687. }
  688. // cleanup
  689. GlobalUnlock(hDib);
  690. WaitCursorEnd();
  691. return TRUE;
  692. }
  693. /************************************************************************* 
  694.  * 
  695.  * ErosionDIB() 
  696.  * 
  697.  * Parameters: 
  698.  * 
  699.  * HDIB hDib        - objective DIB handle
  700.  * BOOL bHori     - erosion direction
  701.  * 
  702.  * Return Value: 
  703.  * 
  704.  * BOOL             - True is success, else False
  705.  * 
  706.  * Description: 
  707.  * 
  708.  * This function do erosion with the specified direction
  709.  * 
  710.  ************************************************************************/ 
  711. BOOL ErosionDIB(HDIB hDib, BOOL bHori)
  712. {
  713. // start wait cursor
  714. WaitCursorBegin();
  715.     // Old DIB buffer
  716. if (hDib == NULL)
  717. {
  718. WaitCursorEnd();
  719.         return FALSE;
  720. }
  721. // only support 256 color image
  722. WORD wBitCount = DIBBitCount(hDib);
  723. if (wBitCount != 8)
  724. {
  725. WaitCursorEnd();
  726.         return FALSE;
  727. }
  728. // new DIB
  729. HDIB hNewDIB = CopyHandle(hDib);
  730. if (! hNewDIB)
  731. {
  732. WaitCursorEnd();
  733.         return FALSE;
  734. }
  735. // source dib buffer
  736.     LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDib);
  737. if (! lpSrcDIB)
  738. {
  739. WaitCursorBegin();
  740. return FALSE;
  741. }
  742.     // New DIB buffer
  743.     LPBITMAPINFO lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB);
  744. if (! lpbmi)
  745. {
  746. WaitCursorBegin();
  747. return FALSE;
  748. }
  749. // start erosion...
  750. LPSTR lpPtr;
  751. LPSTR lpTempPtr;
  752. LONG  x,y;
  753. BYTE  num, num0;
  754. int   i;
  755. LONG lHeight = DIBHeight(lpSrcDIB);
  756. LONG lWidth = DIBWidth(lpSrcDIB);
  757. DWORD dwBufferSize = GlobalSize(lpSrcDIB);
  758. int nLineBytes = BytesPerLine(lpSrcDIB);
  759. if(bHori)
  760. {
  761. for (y=0; y<lHeight; y++)
  762. {
  763. lpPtr=(char *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes)+1;
  764. lpTempPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes)+1;
  765. for (x=1; x<lWidth-1; x++)
  766. {
  767. num0 = num = 0 ;
  768. for(i=0;i<3;i++)
  769. {
  770. num=(unsigned char)*(lpPtr+i-1);
  771. if(num > num0)
  772. num0 = num;
  773. }
  774. *lpTempPtr=(unsigned char)num0;
  775. /*
  776. num=(unsigned char)*lpPtr;
  777. if (num==0)
  778. {
  779. *lpTempPtr=(unsigned char)0;
  780. for(i=0;i<3;i++)
  781. {
  782. num=(unsigned char)*(lpPtr+i-1);
  783. if(num==255)
  784. {
  785. *lpTempPtr=(unsigned char)255;
  786. break;
  787. }
  788. }
  789. }
  790. else 
  791. *lpTempPtr=(unsigned char)255;
  792. */
  793. lpPtr++;
  794. lpTempPtr++;
  795. }
  796. }
  797. }
  798. else // Vertical
  799. {
  800. for (y=1; y<lHeight-1; y++)
  801. {
  802. lpPtr=(char *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes);
  803. lpTempPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes);
  804. for (x=0; x<lWidth; x++)
  805. {
  806. num0 = num = 0 ;
  807. for(i=0;i<3;i++)
  808. {
  809. num=(unsigned char)*(lpPtr+i-1);
  810. if(num > num0)
  811. num0 = num;
  812. }
  813. *lpTempPtr=(unsigned char)num0;
  814. /*
  815. num=(unsigned char)*lpPtr;
  816. if (num==0)
  817. {
  818. *lpTempPtr=(unsigned char)0;
  819. for(i=0;i<3;i++)
  820. {
  821. num=(unsigned char)*(lpPtr+(i-1)*nLineBytes);
  822. if(num==255)
  823. {
  824. *lpTempPtr=(unsigned char)255;
  825. break;
  826. }
  827. }
  828. }
  829. else 
  830. *lpTempPtr=(unsigned char)255;
  831. */
  832. lpPtr++;
  833. lpTempPtr++;
  834. }
  835. }
  836. }
  837. // cleanup
  838. GlobalUnlock(hDib);
  839. GlobalUnlock(hNewDIB);
  840. GlobalFree(hNewDIB);
  841. WaitCursorEnd();
  842. return TRUE;
  843. }
  844. /************************************************************************* 
  845.  * 
  846.  * DilationDIB() 
  847.  * 
  848.  * Parameters: 
  849.  * 
  850.  * HDIB hDib        - objective DIB handle
  851.  * BOOL bHori     - dilation direction
  852.  * 
  853.  * Return Value: 
  854.  * 
  855.  * BOOL             - True is success, else False
  856.  * 
  857.  * Description: 
  858.  * 
  859.  * This function do dilation with the specified direction
  860.  * 
  861.  ************************************************************************/ 
  862. BOOL DilationDIB(HDIB hDib, BOOL bHori)
  863. {
  864. // start wait cursor
  865. WaitCursorBegin();
  866.     // Old DIB buffer
  867. if (hDib == NULL)
  868. {
  869. WaitCursorEnd();
  870.         return FALSE;
  871. }
  872. // only support 256 color image
  873. WORD wBitCount = DIBBitCount(hDib);
  874. if (wBitCount != 8)
  875. {
  876. WaitCursorEnd();
  877.         return FALSE;
  878. }
  879. // new DIB
  880. HDIB hNewDIB = CopyHandle(hDib);
  881. if (! hNewDIB)
  882. {
  883. WaitCursorEnd();
  884.         return FALSE;
  885. }
  886. // source dib buffer
  887.     LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDib);
  888. if (! lpSrcDIB)
  889. {
  890. WaitCursorBegin();
  891. return FALSE;
  892. }
  893.     // New DIB buffer
  894.     LPBITMAPINFO lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB);
  895. if (! lpbmi)
  896. {
  897. WaitCursorBegin();
  898. return FALSE;
  899. }
  900. // start erosion...
  901. LPSTR lpPtr;
  902. LPSTR lpTempPtr;
  903. LONG  x,y;
  904. BYTE  num, num0;
  905. int   i;
  906. LONG lHeight = DIBHeight(lpSrcDIB);
  907. LONG lWidth = DIBWidth(lpSrcDIB);
  908. DWORD dwBufferSize = GlobalSize(lpSrcDIB);
  909. int nLineBytes = BytesPerLine(lpSrcDIB);
  910. if(bHori)
  911. {
  912. for(y=0;y<lHeight;y++)
  913. {
  914. lpPtr=(char *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes)+1;
  915. lpTempPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes)+1;
  916. for(x=1;x<lWidth-1;x++)
  917. {
  918. num0 = num = 255;
  919. for(i=0;i<3;i++)
  920. {
  921. num=(unsigned char)*(lpPtr+i-1);
  922. if(num < num0)
  923. num0 = num;
  924. }
  925. *lpTempPtr=(unsigned char)num0;
  926. /*
  927. num=(unsigned char)*lpPtr;
  928. if (num==255)
  929. {
  930. *lpTempPtr=(unsigned char)255;
  931. for(i=0;i<3;i++)
  932. {
  933. num=(unsigned char)*(lpPtr+i-1);
  934. if(num==0)
  935. {
  936. *lpTempPtr=(unsigned char)0;
  937. break;
  938. }
  939. }
  940. }
  941. else 
  942. *lpTempPtr=(unsigned char)0;
  943. */
  944. lpPtr++;
  945. lpTempPtr++;
  946. }
  947. }
  948. }
  949. else
  950. {
  951. for(y=1;y<lHeight-1;y++)
  952. {
  953. lpPtr=(char *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes);
  954. lpTempPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes);
  955. for(x=0;x<lWidth;x++)
  956. {
  957. num0 = num = 255;
  958. for(i=0;i<3;i++)
  959. {
  960. num=(unsigned char)*(lpPtr+i-1);
  961. if(num < num0)
  962. num0 = num;
  963. }
  964. *lpTempPtr=(unsigned char)num0;
  965. /*
  966. num=(unsigned char)*lpPtr;
  967. if (num==255)
  968. {
  969. *lpTempPtr=(unsigned char)255;
  970. for(i=0;i<3;i++)
  971. {
  972. num=(unsigned char)*(lpPtr+(i-1)*nLineBytes);
  973. if(num==0)
  974. {
  975. *lpTempPtr=(unsigned char)0;
  976. break;
  977. }
  978. }
  979. }
  980. else 
  981. *lpTempPtr=(unsigned char)0;
  982. */
  983. lpPtr++;
  984. lpTempPtr++;
  985. }
  986. }
  987. }
  988. // cleanup
  989. GlobalUnlock(hDib);
  990. GlobalUnlock(hNewDIB);
  991. GlobalFree(hNewDIB);
  992. WaitCursorEnd();
  993. return TRUE;
  994. }
  995. /************************************************************************* 
  996.  * 
  997.  * MorphOpenDIB() 
  998.  * 
  999.  * Parameters: 
  1000.  * 
  1001.  * HDIB hDib        - objective DIB handle
  1002.  * BOOL bHori     - open direction
  1003.  * 
  1004.  * Return Value: 
  1005.  * 
  1006.  * BOOL             - True is success, else False
  1007.  * 
  1008.  * Description: 
  1009.  * 
  1010.  * This function do open with the specified direction
  1011.  * 
  1012.  ************************************************************************/ 
  1013. BOOL MorphOpenDIB(HDIB hDib, BOOL bHori)
  1014. {
  1015. // Step 1: erosion
  1016. if (! ErosionDIB(hDib, bHori))
  1017. return FALSE;
  1018. // Step 2: dilation
  1019. if (! DilationDIB(hDib, bHori))
  1020. return FALSE;
  1021. return TRUE;
  1022. }
  1023. /************************************************************************* 
  1024.  * 
  1025.  * MorphCloseDIB() 
  1026.  * 
  1027.  * Parameters: 
  1028.  * 
  1029.  * HDIB hDib        - objective DIB handle
  1030.  * BOOL bHori     - close direction
  1031.  * 
  1032.  * Return Value: 
  1033.  * 
  1034.  * BOOL             - True is success, else False
  1035.  * 
  1036.  * Description: 
  1037.  * 
  1038.  * This function do close with the specified direction
  1039.  * 
  1040.  ************************************************************************/ 
  1041. BOOL MorphCloseDIB(HDIB hDib, BOOL bHori)
  1042. {
  1043. // Step 1: dilation
  1044. if (! DilationDIB(hDib, bHori))
  1045. return FALSE;
  1046. // Step 2: erosion
  1047. if (! ErosionDIB(hDib, bHori))
  1048. return FALSE;
  1049. return TRUE;
  1050. }
  1051. /************************************************************************* 
  1052.  * 
  1053.  * ContourDIB() 
  1054.  * 
  1055.  * Parameters: 
  1056.  * 
  1057.  * HDIB hDib        - objective DIB handle
  1058.  * BOOL bHori     - open direction
  1059.  * 
  1060.  * Return Value: 
  1061.  * 
  1062.  * BOOL             - True is success, else False
  1063.  * 
  1064.  * Description: 
  1065.  * 
  1066.  * This function contour DIB with the specified direction
  1067.  * 
  1068.  ************************************************************************/ 
  1069. BOOL ContourDIB(HDIB hDib, BOOL bHori)
  1070. {
  1071. // start wait cursor
  1072. WaitCursorBegin();
  1073.     // Old DIB buffer
  1074. if (hDib == NULL)
  1075. {
  1076. WaitCursorEnd();
  1077.         return FALSE;
  1078. }
  1079. // only support 256 color image
  1080. WORD wBitCount = DIBBitCount(hDib);
  1081. if (wBitCount != 8)
  1082. {
  1083. WaitCursorEnd();
  1084.         return FALSE;
  1085. }
  1086. // new DIB
  1087. HDIB hNewDIB = CopyHandle(hDib);
  1088. if (! hNewDIB)
  1089. {
  1090. WaitCursorEnd();
  1091.         return FALSE;
  1092. }
  1093. // source dib buffer
  1094.     LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDib);
  1095. if (! lpSrcDIB)
  1096. {
  1097. WaitCursorBegin();
  1098. return FALSE;
  1099. }
  1100.     // New DIB buffer
  1101.     LPBITMAPINFO lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB);
  1102. if (! lpbmi)
  1103. {
  1104. WaitCursorBegin();
  1105. return FALSE;
  1106. }
  1107. // start erosion...
  1108. LPBYTE lpPtr;
  1109. LPBYTE lpTempPtr;
  1110. LONG  x,y;
  1111. BYTE  num, num0;
  1112. int   i;
  1113. LONG lHeight = DIBHeight(lpSrcDIB);
  1114. LONG lWidth = DIBWidth(lpSrcDIB);
  1115. DWORD dwBufferSize = GlobalSize(lpSrcDIB);
  1116. int nLineBytes = BytesPerLine(lpSrcDIB);
  1117. // Step 1: erosion
  1118. if(bHori)
  1119. {
  1120. for (y=0; y<lHeight; y++)
  1121. {
  1122. lpPtr=(BYTE *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes)+1;
  1123. lpTempPtr=(BYTE *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes)+1;
  1124. for (x=1; x<lWidth-1; x++)
  1125. {
  1126. num0 = num = 0 ;
  1127. for(i=0;i<3;i++)
  1128. {
  1129. num=(unsigned char)*(lpPtr+i-1);
  1130. if(num > num0)
  1131. num0 = num;
  1132. }
  1133. *lpTempPtr=(unsigned char)num0;
  1134. /*
  1135. num=(unsigned char)*lpPtr;
  1136. if (num==0)
  1137. {
  1138. *lpTempPtr=(unsigned char)0;
  1139. for(i=0;i<3;i++)
  1140. {
  1141. num=(unsigned char)*(lpPtr+i-1);
  1142. if(num==255)
  1143. {
  1144. *lpTempPtr=(unsigned char)255;
  1145. break;
  1146. }
  1147. }
  1148. }
  1149. else 
  1150. *lpTempPtr=(unsigned char)255;
  1151. */
  1152. lpPtr++;
  1153. lpTempPtr++;
  1154. }
  1155. }
  1156. }
  1157. else // Vertical
  1158. {
  1159. for (y=1; y<lHeight-1; y++)
  1160. {
  1161. lpPtr=(BYTE *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes);
  1162. lpTempPtr=(BYTE *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes);
  1163. for (x=0; x<lWidth; x++)
  1164. {
  1165. num0 = num = 0 ;
  1166. for(i=0;i<3;i++)
  1167. {
  1168. num=(unsigned char)*(lpPtr+i-1);
  1169. if(num > num0)
  1170. num0 = num;
  1171. }
  1172. *lpTempPtr=(unsigned char)num0;
  1173. /*
  1174. num=(unsigned char)*lpPtr;
  1175. if (num==0)
  1176. {
  1177. *lpTempPtr=(unsigned char)0;
  1178. for(i=0;i<3;i++)
  1179. {
  1180. num=(unsigned char)*(lpPtr+(i-1)*nLineBytes);
  1181. if(num==255)
  1182. {
  1183. *lpTempPtr=(unsigned char)255;
  1184. break;
  1185. }
  1186. }
  1187. }
  1188. else 
  1189. *lpTempPtr=(unsigned char)255;
  1190. */
  1191. lpPtr++;
  1192. lpTempPtr++;
  1193. }
  1194. }
  1195. }
  1196. // Step 2: original image minues dilation image
  1197. if(bHori)
  1198. {
  1199. for(y=0;y<lHeight;y++)
  1200. {
  1201. lpPtr=(BYTE *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes)+1;
  1202. lpTempPtr=(BYTE *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes)+1;
  1203. for(x=1;x<lWidth-1;x++)
  1204. {
  1205. if (*lpTempPtr == *lpPtr)
  1206. *lpTempPtr = (BYTE)255;
  1207. else
  1208. *lpTempPtr = *lpTempPtr - *lpPtr;
  1209. lpPtr++;
  1210. lpTempPtr++;
  1211. }
  1212. }
  1213. }
  1214. else
  1215. {
  1216. for(y=1;y<lHeight-1;y++)
  1217. {
  1218. lpPtr=(BYTE *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes);
  1219. lpTempPtr=(BYTE *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes);
  1220. for(x=0;x<lWidth;x++)
  1221. {
  1222. if (*lpTempPtr == *lpPtr)
  1223. *lpTempPtr = (BYTE)255;
  1224. else
  1225. *lpTempPtr = *lpTempPtr - *lpPtr;
  1226. lpPtr++;
  1227. lpTempPtr++;
  1228. }
  1229. }
  1230. }
  1231. // cleanup
  1232. GlobalUnlock(hDib);
  1233. GlobalUnlock(hNewDIB);
  1234. GlobalFree(hNewDIB);
  1235. return TRUE;
  1236. }
  1237. /************************************************************************* 
  1238.  * 
  1239.  * ThinningDIB() 
  1240.  * 
  1241.  * Parameters: 
  1242.  * 
  1243.  * HDIB hDib        - objective DIB handle
  1244.  * 
  1245.  * Return Value: 
  1246.  * 
  1247.  * BOOL             - True is success, else False
  1248.  * 
  1249.  * Description: 
  1250.  * 
  1251.  * This function thins a DIB
  1252.  * 
  1253.  ************************************************************************/ 
  1254. BOOL ThinningDIB(HDIB hDib)
  1255. {
  1256. static int erasetable[256]=
  1257. {
  1258. 0,0,1,1,0,0,1,1,
  1259. 1,1,0,1,1,1,0,1,
  1260. 1,1,0,0,1,1,1,1,
  1261. 0,0,0,0,0,0,0,1,
  1262. 0,0,1,1,0,0,1,1,
  1263. 1,1,0,1,1,1,0,1,
  1264. 1,1,0,0,1,1,1,1,
  1265. 0,0,0,0,0,0,0,1,
  1266. 1,1,0,0,1,1,0,0,
  1267. 0,0,0,0,0,0,0,0,
  1268. 0,0,0,0,0,0,0,0,
  1269. 0,0,0,0,0,0,0,0,
  1270. 1,1,0,0,1,1,0,0,
  1271. 1,1,0,1,1,1,0,1,
  1272. 0,0,0,0,0,0,0,0,
  1273. 0,0,0,0,0,0,0,0,
  1274. 0,0,1,1,0,0,1,1,
  1275. 1,1,0,1,1,1,0,1,
  1276. 1,1,0,0,1,1,1,1,
  1277. 0,0,0,0,0,0,0,1,
  1278. 0,0,1,1,0,0,1,1,
  1279. 1,1,0,1,1,1,0,1,
  1280. 1,1,0,0,1,1,1,1,
  1281. 0,0,0,0,0,0,0,0,
  1282. 1,1,0,0,1,1,0,0,
  1283. 0,0,0,0,0,0,0,0,
  1284. 1,1,0,0,1,1,1,1,
  1285. 0,0,0,0,0,0,0,0,
  1286. 1,1,0,0,1,1,0,0,
  1287. 1,1,0,1,1,1,0,0,
  1288. 1,1,0,0,1,1,1,0,
  1289. 1,1,0,0,1,0,0,0
  1290. };
  1291. // start wait cursor
  1292. WaitCursorBegin();
  1293.     // Old DIB buffer
  1294. if (hDib == NULL)
  1295. {
  1296. WaitCursorEnd();
  1297.         return FALSE;
  1298. }
  1299. // only support 256 color image
  1300. WORD wBitCount = DIBBitCount(hDib);
  1301. if (wBitCount != 8)
  1302. {
  1303. WaitCursorEnd();
  1304.         return FALSE;
  1305. }
  1306. // new DIB
  1307. HDIB hNewDIB = CopyHandle(hDib);
  1308. if (! hNewDIB)
  1309. {
  1310. WaitCursorEnd();
  1311.         return FALSE;
  1312. }
  1313. // source dib buffer
  1314.     LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDib);
  1315. if (! lpSrcDIB)
  1316. {
  1317. WaitCursorBegin();
  1318. return FALSE;
  1319. }
  1320.     // New DIB buffer
  1321.     LPBITMAPINFO lpbmi = (LPBITMAPINFO)GlobalLock(hNewDIB);
  1322. if (! lpbmi)
  1323. {
  1324. WaitCursorBegin();
  1325. return FALSE;
  1326. }
  1327. // start erosion...
  1328. LPSTR lpPtr;
  1329. LPSTR lpTempPtr;
  1330. LONG  x,y;
  1331. BYTE  num;
  1332. LONG lHeight = DIBHeight(lpSrcDIB);
  1333. LONG lWidth = DIBWidth(lpSrcDIB);
  1334. DWORD dwBufferSize = GlobalSize(lpSrcDIB);
  1335. int nLineBytes = BytesPerLine(lpSrcDIB);
  1336. int nw,n,ne,w,e,sw,s,se;
  1337. BOOL Finished=FALSE;
  1338.     while(!Finished)
  1339. {
  1340.      Finished=TRUE;
  1341. for (y=1;y<lHeight-1;y++)
  1342. lpPtr=(char *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes);
  1343. lpTempPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes);
  1344. x=1; 
  1345. while(x<lWidth-1)
  1346. {
  1347. if(*(lpPtr+x)==0)
  1348. {
  1349. w=(unsigned char)*(lpPtr+x-1);
  1350. e=(unsigned char)*(lpPtr+x+1);
  1351. if( (w==255)|| (e==255))
  1352. {
  1353. nw=(unsigned char)*(lpPtr+x+nLineBytes-1);
  1354. n=(unsigned char)*(lpPtr+x+nLineBytes);
  1355. ne=(unsigned char)*(lpPtr+x+nLineBytes+1);
  1356. sw=(unsigned char)*(lpPtr+x-nLineBytes-1);
  1357. s=(unsigned char)*(lpPtr+x-nLineBytes);
  1358. se=(unsigned char)*(lpPtr+x-nLineBytes+1);
  1359. num=nw/255+n/255*2+ne/255*4+w/255*8+e/255*16+sw/255*32+s/255*64+se/255*128;
  1360. if(erasetable[num]==1)
  1361. {
  1362. *(lpPtr+x)=(BYTE)255;
  1363. *(lpTempPtr+x)=(BYTE)255;
  1364. Finished=FALSE;
  1365. x++;
  1366. }
  1367. }
  1368. }
  1369. x++;
  1370. }
  1371. }
  1372. for (x=1;x<lWidth-1;x++)
  1373. y=1;
  1374. while(y<lHeight-1)
  1375. {
  1376. lpPtr=(char *)lpbmi+(dwBufferSize-nLineBytes-y*nLineBytes);
  1377. lpTempPtr=(char *)lpSrcDIB+(dwBufferSize-nLineBytes-y*nLineBytes);
  1378. if(*(lpPtr+x)==0)
  1379. {
  1380. n=(unsigned char)*(lpPtr+x+nLineBytes);
  1381. s=(unsigned char)*(lpPtr+x-nLineBytes);
  1382. if( (n==255)|| (s==255))
  1383. {
  1384. nw=(unsigned char)*(lpPtr+x+nLineBytes-1);
  1385. ne=(unsigned char)*(lpPtr+x+nLineBytes+1);
  1386. w=(unsigned char)*(lpPtr+x-1);
  1387. e=(unsigned char)*(lpPtr+x+1);
  1388. sw=(unsigned char)*(lpPtr+x-nLineBytes-1);
  1389. se=(unsigned char)*(lpPtr+x-nLineBytes+1);
  1390. num=nw/255+n/255*2+ne/255*4+w/255*8+e/255*16+sw/255*32+s/255*64+se/255*128;
  1391. if(erasetable[num]==1)
  1392. {
  1393. *(lpPtr+x)=(BYTE)255;
  1394. *(lpTempPtr+x)=(BYTE)255;
  1395. Finished=FALSE;
  1396. y++;
  1397. }
  1398. }
  1399. }
  1400. y++;
  1401. }
  1402. }
  1403. // cleanup
  1404. GlobalUnlock(hDib);
  1405. GlobalUnlock(hNewDIB);
  1406. GlobalFree(hNewDIB);
  1407. return TRUE;
  1408. }
  1409. //////////////////////////////////////////////////////////
  1410. // internal definitions
  1411. #define PI (double)3.14159265359
  1412. /*complex number*/
  1413. typedef struct
  1414. {
  1415. double re;
  1416. double im;
  1417. }COMPLEX;
  1418. /*complex add*/
  1419. COMPLEX Add(COMPLEX c1, COMPLEX c2)
  1420. {
  1421. COMPLEX c;
  1422. c.re=c1.re+c2.re;
  1423. c.im=c1.im+c2.im;
  1424. return c;
  1425. }
  1426. /*complex substract*/
  1427. COMPLEX Sub(COMPLEX c1, COMPLEX c2)
  1428. {
  1429. COMPLEX c;
  1430. c.re=c1.re-c2.re;
  1431. c.im=c1.im-c2.im;
  1432. return c;
  1433. }
  1434. /*complex multiple*/
  1435. COMPLEX Mul(COMPLEX c1, COMPLEX c2)
  1436. {
  1437. COMPLEX c;
  1438. c.re=c1.re*c2.re-c1.im*c2.im;
  1439. c.im=c1.re*c2.im+c2.re*c1.im;
  1440. return c;
  1441. }
  1442. //////////////////////////////////////////////////////////
  1443. /*
  1444. void FFT(COMPLEX * TD, COMPLEX * FD, int power);
  1445. void IFFT(COMPLEX * FD, COMPLEX * TD, int power);
  1446. void DCT(double *f, double *F, int power);
  1447. void IDCT(double *F, double *f, int power);
  1448. void WALh(double *f, double *W, int power);
  1449. void IWALh(double *W, double *f, int power);
  1450. */
  1451. /****************************************************
  1452. FFT()
  1453. 参数:
  1454. TD为时域值
  1455. FD为频域值
  1456. power为2的幂数
  1457. 返回值:
  1458. 说明:
  1459. 本函数实现快速傅立叶变换
  1460. ****************************************************/
  1461. void FFT(COMPLEX * TD, COMPLEX * FD, int power)
  1462. {
  1463. int count;
  1464. int i,j,k,bfsize,p;
  1465. double angle;
  1466. COMPLEX *W,*X1,*X2,*X;
  1467. /*计算傅立叶变换点数*/
  1468. count=1<<power;
  1469. /*分配运算所需存储器*/
  1470. W=(COMPLEX *)malloc(sizeof(COMPLEX)*count/2);
  1471. X1=(COMPLEX *)malloc(sizeof(COMPLEX)*count);
  1472. X2=(COMPLEX *)malloc(sizeof(COMPLEX)*count);
  1473. /*计算加权系数*/
  1474. for(i=0;i<count/2;i++)
  1475. {
  1476. angle=-i*PI*2/count;
  1477. W[i].re=cos(angle);
  1478. W[i].im=sin(angle);
  1479. }
  1480. /*将时域点写入存储器*/
  1481. memcpy(X1,TD,sizeof(COMPLEX)*count);
  1482. /*蝶形运算*/
  1483. for(k=0;k<power;k++)
  1484. {
  1485. for(j=0;j<1<<k;j++)
  1486. {
  1487. bfsize=1<<(power-k);
  1488. for(i=0;i<bfsize/2;i++)
  1489. {
  1490. p=j*bfsize;
  1491. X2[i+p]=Add(X1[i+p],X1[i+p+bfsize/2]);
  1492. X2[i+p+bfsize/2]=Mul(Sub(X1[i+p],X1[i+p+bfsize/2]),W[i*(1<<k)]);
  1493. }
  1494. }
  1495. X=X1;
  1496. X1=X2;
  1497. X2=X;
  1498. }
  1499. /*重新排序*/
  1500. for(j=0;j<count;j++)
  1501. {
  1502. p=0;
  1503. for(i=0;i<power;i++)
  1504. {
  1505. if (j&(1<<i)) p+=1<<(power-i-1);
  1506. }
  1507. FD[j]=X1[p];
  1508. }
  1509. /*释放存储器*/
  1510. free(W);
  1511. free(X1);
  1512. free(X2);
  1513. }
  1514. /****************************************************
  1515. IFFT()
  1516. 参数:
  1517. FD为频域值
  1518. TD为时域值
  1519. power为2的幂数
  1520. 返回值:
  1521. 说明:
  1522. 本函数利用快速傅立叶变换实现傅立叶反变换
  1523. ****************************************************/
  1524. void IFFT(COMPLEX * FD, COMPLEX * TD, int power)
  1525. {
  1526. int i, count;
  1527. COMPLEX *x;
  1528. /*计算傅立叶反变换点数*/
  1529. count=1<<power;
  1530. /*分配运算所需存储器*/
  1531. x=(COMPLEX *)malloc(sizeof(COMPLEX)*count);
  1532. /*将频域点写入存储器*/
  1533. memcpy(x,FD,sizeof(COMPLEX)*count);
  1534. /*求频域点的共轭*/
  1535. for(i=0;i<count;i++)
  1536. x[i].im = -x[i].im;
  1537. /*调用FFT*/
  1538. FFT(x, TD, power);
  1539. /*求时域点的共轭*/
  1540. for(i=0;i<count;i++)
  1541. {
  1542. TD[i].re /= count;
  1543. TD[i].im = -TD[i].im / count;
  1544. }
  1545. /*释放存储器*/
  1546. free(x);
  1547. }
  1548. /*******************************************************
  1549. DCT()
  1550. 参数:
  1551. f为时域值
  1552. F为频域值
  1553. power为2的幂数
  1554. 返回值:
  1555. 说明:
  1556. 本函数利用快速傅立叶变换实现快速离散余弦变换
  1557. ********************************************************/
  1558. void DCT(double *f, double *F, int power)
  1559. {
  1560. int i,count;
  1561. COMPLEX *X;
  1562. double s;
  1563. /*计算离散余弦变换点数*/
  1564. count=1<<power;
  1565. /*分配运算所需存储器*/
  1566. X=(COMPLEX *)malloc(sizeof(COMPLEX)*count*2);
  1567. /*延拓*/
  1568. memset(X,0,sizeof(COMPLEX)*count*2);
  1569. /*将时域点写入存储器*/
  1570. for(i=0;i<count;i++)
  1571. {
  1572. X[i].re=f[i];
  1573. }
  1574. /*调用快速傅立叶变换*/
  1575. FFT(X,X,power+1);
  1576. /*调整系数*/
  1577. s=1/sqrt(count);
  1578. F[0]=X[0].re*s;
  1579. s*=sqrt(2);
  1580. for(i=1;i<count;i++)
  1581. {
  1582. F[i]=(X[i].re*cos(i*PI/(count*2))+X[i].im*sin(i*PI/(count*2)))*s;
  1583. }
  1584. /*释放存储器*/
  1585. free(X);
  1586. }
  1587. /************************************************************
  1588. IDCT()
  1589. 参数:
  1590. F为频域值
  1591. f为时域值
  1592. power为2的幂数
  1593. 返回值:
  1594. 说明:
  1595. 本函数利用快速傅立叶反变换实现快速离散反余弦变换
  1596. *************************************************************/
  1597. void IDCT(double *F, double *f, int power)
  1598. {
  1599. int i,count;
  1600. COMPLEX *X;
  1601. double s;
  1602. /*计算离散反余弦变换点数*/
  1603. count=1<<power;
  1604. /*分配运算所需存储器*/
  1605. X=(COMPLEX *)malloc(sizeof(COMPLEX)*count*2);
  1606. /*延拓*/
  1607. memset(X,0,sizeof(COMPLEX)*count*2);
  1608. /*调整频域点,写入存储器*/
  1609. for(i=0;i<count;i++)
  1610. {
  1611. X[i].re=F[i]*cos(i*PI/(count*2));
  1612. X[i].im=F[i]*sin(i*PI/(count*2));
  1613. }
  1614. /*调用快速傅立叶反变换*/
  1615. IFFT(X,X,power+1);
  1616. /*调整系数*/
  1617. s=1/sqrt(count);
  1618. for(i=1;i<count;i++)
  1619. {
  1620. f[i]=(1-sqrt(2))*s*F[0]+sqrt(2)*s*X[i].re*count*2;
  1621. }
  1622. /*释放存储器*/
  1623. free(X);
  1624. }
  1625. /**********************************************************
  1626. WALh()
  1627. 参数:
  1628. f为时域值
  1629. W为频域值
  1630. power为2的幂数
  1631. 返回值:
  1632. 说明:
  1633. 本函数利用快速傅立叶变换实现快速沃尔什-哈达玛变换
  1634. *************************************************************/
  1635. void WALh(double *f, double *W, int power)
  1636. {
  1637. int count;
  1638. int i,j,k,bfsize,p;
  1639. double *X1,*X2,*X;
  1640. /*计算快速沃尔什变换点数*/
  1641. count=1<<power;
  1642. /*分配运算所需存储器*/
  1643. X1=(double *)malloc(sizeof(double)*count);
  1644. X2=(double *)malloc(sizeof(double)*count);
  1645. /*将时域点写入存储器*/
  1646. memcpy(X1,f,sizeof(double)*count);
  1647. /*蝶形运算*/
  1648. for(k=0;k<power;k++)
  1649. {
  1650. for(j=0;j<1<<k;j++)
  1651. {
  1652. bfsize=1<<(power-k);
  1653. for(i=0;i<bfsize/2;i++)
  1654. {
  1655. p=j*bfsize;
  1656. X2[i+p]=X1[i+p]+X1[i+p+bfsize/2];
  1657. X2[i+p+bfsize/2]=X1[i+p]-X1[i+p+bfsize/2];
  1658. }
  1659. }
  1660. X=X1;
  1661. X1=X2;
  1662. X2=X;
  1663. }
  1664. /*调整系数*/
  1665. // for(i=0;i<count;i++)
  1666. // {
  1667. // W[i]=X1[i]/count;
  1668. // }
  1669. for(j=0;j<count;j++)
  1670. {
  1671. p=0;
  1672. for(i=0;i<power;i++)
  1673. {
  1674. if (j&(1<<i)) p+=1<<(power-i-1);
  1675. }
  1676. W[j]=X1[p]/count;
  1677. }
  1678. /*释放存储器*/
  1679. free(X1);
  1680. free(X2);
  1681. }
  1682. /*********************************************************************
  1683. IWALh()
  1684. 参数:
  1685. W为频域值
  1686. f为时域值
  1687. power为2的幂数
  1688. 返回值:
  1689. 说明:
  1690. 本函数利用快速沃尔什-哈达玛变换实现快速沃尔什-哈达玛反变换
  1691. **********************************************************************/
  1692. void IWALh(double *W, double *f, int power)
  1693. {
  1694. int i, count;
  1695. /*计算快速沃尔什反变换点数*/
  1696. count=1<<power;
  1697. /*调用快速沃尔什-哈达玛变换*/
  1698. WALh(W, f, power);
  1699. /*调整系数*/
  1700. for(i=0;i<count;i++)
  1701. {
  1702. f[i] *= count;
  1703. }
  1704. }
  1705. //////////////////////////////////////////////////////////////////////////////////
  1706. // internal functions
  1707. #define Point(x,y) lpPoints[(x)+(y)*nWidth]
  1708. void GetPoints(int nWidth,int nHeight,BYTE *lpBits,BYTE *lpPoints)
  1709. {
  1710. int x,y,p;
  1711. int nByteWidth = WIDTHBYTES(nWidth*24); //nWidth*3;
  1712. //if (nByteWidth%4) nByteWidth+=4-(nByteWidth%4);
  1713. for(y=0;y<nHeight;y++)
  1714. {
  1715. for(x=0;x<nWidth;x++)
  1716. {
  1717. p=x*3+y*nByteWidth;
  1718. lpPoints[x+y*nWidth]=(BYTE)(0.299*(float)lpBits[p+2]+0.587*(float)lpBits[p+1]+0.114*(float)lpBits[p]+0.1);
  1719. }
  1720. }
  1721. }
  1722. void PutPoints(int nWidth,int nHeight,BYTE *lpBits,BYTE *lpPoints)
  1723. {
  1724. int x,y,p,p1;
  1725. int nByteWidth = WIDTHBYTES(nWidth*24); //nWidth*3;
  1726. //if (nByteWidth%4) nByteWidth+=4-(nByteWidth%4);
  1727. for(y=0;y<nHeight;y++)
  1728. {
  1729. for(x=0;x<nWidth;x++)
  1730. {
  1731. p=x*3+y*nByteWidth;
  1732. p1=x+y*nWidth;
  1733. lpBits[p]=lpPoints[p1];
  1734. lpBits[p+1]=lpPoints[p1];
  1735. lpBits[p+2]=lpPoints[p1];
  1736. }
  1737. }
  1738. }
  1739. //////////////////////////////////////////////////////////////////////////////
  1740. /****************************************************
  1741. FFTDIB()
  1742. 参数:
  1743. hDIB为输入的DIB句柄
  1744. 返回值:
  1745. 成功为TRUE;失败为FALSE
  1746. 说明:
  1747. 本函数实现DIB位图的快速傅立叶变换
  1748. ****************************************************/
  1749. BOOL FFTDIB(HDIB hDIB)
  1750. {
  1751. if (hDIB == NULL)
  1752. return FALSE;
  1753. // start wait cursor
  1754. WaitCursorBegin();
  1755. HDIB hDib = NULL;
  1756. HDIB hNewDib = NULL;
  1757. // we only convolute 24bpp DIB, so first convert DIB to 24bpp
  1758. WORD wBitCount = DIBBitCount(hDIB);
  1759. if (wBitCount != 24)
  1760. {
  1761. hNewDib = ConvertDIBFormat(hDIB, 24, NULL);
  1762. hDib = CopyHandle(hNewDib);
  1763. }
  1764. else
  1765. {
  1766. hNewDib = CopyHandle(hDIB);
  1767. hDib = CopyHandle(hDIB);
  1768. }
  1769. if (hNewDib == NULL && hDib == NULL)
  1770. {
  1771. WaitCursorEnd();
  1772. return FALSE;
  1773. }
  1774. // process!
  1775. LPBYTE lpSrcDIB = (LPBYTE)GlobalLock(hDib);
  1776. LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib);
  1777. LPBYTE lpInput = FindDIBBits(lpSrcDIB);
  1778. LPBYTE lpOutput = FindDIBBits(lpDIB);
  1779. int nWidth = DIBWidth(lpSrcDIB);
  1780. int nHeight = DIBHeight(lpSrcDIB);
  1781. int w=1,h=1,wp=0,hp=0;
  1782. while(w*2<=nWidth)
  1783. {
  1784. w*=2;
  1785. wp++;
  1786. }
  1787. while(h*2<=nHeight)
  1788. {
  1789. h*=2;
  1790. hp++;
  1791. }
  1792. int x,y;
  1793. BYTE *lpPoints=new BYTE[nWidth*nHeight];
  1794. GetPoints(nWidth,nHeight,lpInput,lpPoints);
  1795. COMPLEX *TD=new COMPLEX[w*h];
  1796. COMPLEX *FD=new COMPLEX[w*h];
  1797. for(y=0;y<h;y++)
  1798. {
  1799. for(x=0;x<w;x++)
  1800. {
  1801. TD[x+w*y].re=Point(x,y);
  1802. TD[x+w*y].im=0;
  1803. }
  1804. }
  1805. for(y=0;y<h;y++)
  1806. {
  1807. FFT(&TD[w*y],&FD[w*y],wp);
  1808. }
  1809. for(y=0;y<h;y++)
  1810. {
  1811. for(x=0;x<w;x++)
  1812. {
  1813. TD[y+h*x]=FD[x+w*y];
  1814. // TD[x+w*y]=FD[x*h+y];
  1815. }
  1816. }
  1817. for(x=0;x<w;x++)
  1818. {
  1819. FFT(&TD[x*h],&FD[x*h],hp);
  1820. }
  1821. memset(lpPoints,0,nWidth*nHeight);
  1822. double m;
  1823. for(y=0;y<h;y++)
  1824. {
  1825. for(x=0;x<w;x++)
  1826. {
  1827. m=sqrt(FD[x*h+y].re*FD[x*h+y].re+FD[x*h+y].im*FD[x*h+y].im)/100;
  1828. if (m>255) m=255;
  1829. Point((x<w/2?x+w/2:x-w/2),nHeight-1-(y<h/2?y+h/2:y-h/2))=(BYTE)(m);
  1830. }
  1831. }
  1832. delete TD;
  1833. delete FD;
  1834. PutPoints(nWidth,nHeight,lpOutput,lpPoints);
  1835. delete lpPoints;
  1836. // recover
  1837. DWORD dwSize = GlobalSize(hDib);
  1838. memcpy(lpSrcDIB, lpDIB, dwSize);
  1839. GlobalUnlock(hDib);
  1840. GlobalUnlock(hNewDib);
  1841. if (wBitCount != 24)
  1842. {
  1843. hNewDib = ConvertDIBFormat(hDib, wBitCount, NULL);
  1844. lpSrcDIB = (LPBYTE)GlobalLock(hDIB);
  1845. lpDIB = (LPBYTE)GlobalLock(hNewDib);
  1846. dwSize = GlobalSize(hNewDib);
  1847. memcpy(lpSrcDIB, lpDIB, dwSize);
  1848. GlobalUnlock(hDIB);
  1849. GlobalUnlock(hNewDib);
  1850. }
  1851. else
  1852. {
  1853. lpSrcDIB = (LPBYTE)GlobalLock(hDIB);
  1854. lpDIB = (LPBYTE)GlobalLock(hDib);
  1855. dwSize = GlobalSize(hDib);
  1856. memcpy(lpSrcDIB, lpDIB, dwSize);
  1857. GlobalUnlock(hDIB);
  1858. GlobalUnlock(hDib);
  1859. }
  1860. // cleanup
  1861. GlobalFree(hDib);
  1862. GlobalFree(hNewDib);
  1863. // return
  1864. WaitCursorEnd();
  1865. return TRUE;
  1866. }
  1867. /****************************************************
  1868. DCTDIB()
  1869. 参数:
  1870. hDIB为输入的DIB句柄
  1871. 返回值:
  1872. 成功为TRUE;失败为FALSE
  1873. 说明:
  1874. 本函数实现DIB位图的快速余弦变换
  1875. ****************************************************/
  1876. BOOL DCTDIB(HDIB hDIB)
  1877. {
  1878. if (hDIB == NULL)
  1879. return FALSE;
  1880. // start wait cursor
  1881. WaitCursorBegin();
  1882. HDIB hDib = NULL;
  1883. HDIB hNewDib = NULL;
  1884. // we only convolute 24bpp DIB, so first convert DIB to 24bpp
  1885. WORD wBitCount = DIBBitCount(hDIB);
  1886. if (wBitCount != 24)
  1887. {
  1888. hNewDib = ConvertDIBFormat(hDIB, 24, NULL);
  1889. hDib = CopyHandle(hNewDib);
  1890. }
  1891. else
  1892. {
  1893. hNewDib = CopyHandle(hDIB);
  1894. hDib = CopyHandle(hDIB);
  1895. }
  1896. if (hNewDib == NULL && hDib == NULL)
  1897. {
  1898. WaitCursorEnd();
  1899. return FALSE;
  1900. }
  1901. // process!
  1902. LPBYTE lpSrcDIB = (LPBYTE)GlobalLock(hDib);
  1903. LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib);
  1904. LPBYTE lpInput = FindDIBBits(lpSrcDIB);
  1905. LPBYTE lpOutput = FindDIBBits(lpDIB);
  1906. int nWidth = DIBWidth(lpSrcDIB);
  1907. int nHeight = DIBHeight(lpSrcDIB);
  1908. int w=1,h=1,wp=0,hp=0;
  1909. while(w*2<=nWidth)
  1910. {
  1911. w*=2;
  1912. wp++;
  1913. }
  1914. while(h*2<=nHeight)
  1915. {
  1916. h*=2;
  1917. hp++;
  1918. }
  1919. int x,y;
  1920. BYTE *lpPoints=new BYTE[nWidth*nHeight];
  1921. GetPoints(nWidth,nHeight,lpInput,lpPoints);
  1922. double *f=new double[w*h];
  1923. double *W=new double[w*h];
  1924. for(y=0;y<h;y++)
  1925. {
  1926. for(x=0;x<w;x++)
  1927. {
  1928. f[x+y*w]=Point(x,y);
  1929. }
  1930. }
  1931. for(y=0;y<h;y++)
  1932. {
  1933. DCT(&f[w*y],&W[w*y],wp);
  1934. }
  1935. for(y=0;y<h;y++)
  1936. {
  1937. for(x=0;x<w;x++)
  1938. {
  1939. f[x*h+y]=W[x+w*y];
  1940. }
  1941. }
  1942. for(x=0;x<w;x++)
  1943. {
  1944. DCT(&f[x*h],&W[x*h],hp);
  1945. }
  1946. double a;
  1947. memset(lpPoints,0,nWidth*nHeight);
  1948. for(y=0;y<h;y++)
  1949. {
  1950. for(x=0;x<w;x++)
  1951. {
  1952. a=fabs(W[x*h+y]);
  1953. if (a>255) a=255;
  1954. Point(x,nHeight-y-1)=(BYTE)(a);
  1955. }
  1956. }
  1957. delete f;
  1958. delete W;
  1959. PutPoints(nWidth,nHeight,lpOutput,lpPoints);
  1960. delete lpPoints;
  1961. // recover
  1962. DWORD dwSize = GlobalSize(hDib);
  1963. memcpy(lpSrcDIB, lpDIB, dwSize);
  1964. GlobalUnlock(hDib);
  1965. GlobalUnlock(hNewDib);
  1966. if (wBitCount != 24)
  1967. {
  1968. hNewDib = ConvertDIBFormat(hDib, wBitCount, NULL);
  1969. lpSrcDIB = (LPBYTE)GlobalLock(hDIB);
  1970. lpDIB = (LPBYTE)GlobalLock(hNewDib);
  1971. dwSize = GlobalSize(hNewDib);
  1972. memcpy(lpSrcDIB, lpDIB, dwSize);
  1973. GlobalUnlock(hDIB);
  1974. GlobalUnlock(hNewDib);
  1975. }
  1976. else
  1977. {
  1978. lpSrcDIB = (LPBYTE)GlobalLock(hDIB);
  1979. lpDIB = (LPBYTE)GlobalLock(hDib);
  1980. dwSize = GlobalSize(hDib);
  1981. memcpy(lpSrcDIB, lpDIB, dwSize);
  1982. GlobalUnlock(hDIB);
  1983. GlobalUnlock(hDib);
  1984. }
  1985. // cleanup
  1986. GlobalFree(hDib);
  1987. GlobalFree(hNewDib);
  1988. // return
  1989. WaitCursorEnd();
  1990. return TRUE;
  1991. }
  1992. /****************************************************
  1993. WALhDIB()
  1994. 参数:
  1995. hDIB为输入的DIB句柄
  1996. 返回值:
  1997. 成功为TRUE;失败为FALSE
  1998. 说明:
  1999. 本函数实现DIB位图的快速沃尔什-哈达玛变换
  2000. ****************************************************/
  2001. BOOL WALhDIB(HDIB hDIB)
  2002. {
  2003. if (hDIB == NULL)
  2004. return FALSE;
  2005. // start wait cursor
  2006. WaitCursorBegin();
  2007. HDIB hDib = NULL;
  2008. HDIB hNewDib = NULL;
  2009. // we only convolute 24bpp DIB, so first convert DIB to 24bpp
  2010. WORD wBitCount = DIBBitCount(hDIB);
  2011. if (wBitCount != 24)
  2012. {
  2013. hNewDib = ConvertDIBFormat(hDIB, 24, NULL);
  2014. hDib = CopyHandle(hNewDib);
  2015. }
  2016. else
  2017. {
  2018. hNewDib = CopyHandle(hDIB);
  2019. hDib = CopyHandle(hDIB);
  2020. }
  2021. if (hNewDib == NULL && hDib == NULL)
  2022. {
  2023. WaitCursorEnd();
  2024. return FALSE;
  2025. }
  2026. // process!
  2027. LPBYTE lpSrcDIB = (LPBYTE)GlobalLock(hDib);
  2028. LPBYTE lpDIB = (LPBYTE)GlobalLock(hNewDib);
  2029. LPBYTE lpInput = FindDIBBits(lpSrcDIB);
  2030. LPBYTE lpOutput = FindDIBBits(lpDIB);
  2031. int nWidth = DIBWidth(lpSrcDIB);
  2032. int nHeight = DIBHeight(lpSrcDIB);
  2033. int w=1,h=1,wp=0,hp=0;
  2034. while(w*2<=nWidth)
  2035. {
  2036. w*=2;
  2037. wp++;
  2038. }
  2039. while(h*2<=nHeight)
  2040. {
  2041. h*=2;
  2042. hp++;
  2043. }
  2044. int x,y;
  2045. BYTE *lpPoints=new BYTE[nWidth*nHeight];
  2046. GetPoints(nWidth,nHeight,lpInput,lpPoints);
  2047. double *f=new double[w*h];
  2048. double *W=new double[w*h];
  2049. for(y=0;y<h;y++)
  2050. {
  2051. for(x=0;x<w;x++)
  2052. {
  2053. f[x+y*w]=Point(x,y);
  2054. }
  2055. }
  2056. for(y=0;y<h;y++)
  2057. {
  2058. WALh(f+w*y,W+w*y,wp);
  2059. }
  2060. for(y=0;y<h;y++)
  2061. {
  2062. for(x=0;x<w;x++)
  2063. {
  2064. f[x*h+y]=W[x+w*y];
  2065. }
  2066. }
  2067. for(x=0;x<w;x++)
  2068. {
  2069. WALh(f+x*h,W+x*h,hp);
  2070. }
  2071. double a;
  2072. memset(lpPoints,0,nWidth*nHeight);
  2073. for(y=0;y<h;y++)
  2074. {
  2075. for(x=0;x<w;x++)
  2076. {
  2077. a=fabs(W[x*h+y]*1000);
  2078. if (a>255) a=255;
  2079. Point(x,nHeight-y-1)=(BYTE)a;
  2080. }
  2081. }
  2082. delete f;
  2083. delete W;
  2084. PutPoints(nWidth,nHeight,lpOutput,lpPoints);
  2085. delete lpPoints;
  2086. // recover
  2087. DWORD dwSize = GlobalSize(hDib);
  2088. memcpy(lpSrcDIB, lpDIB, dwSize);
  2089. GlobalUnlock(hDib);
  2090. GlobalUnlock(hNewDib);
  2091. if (wBitCount != 24)
  2092. {
  2093. hNewDib = ConvertDIBFormat(hDib, wBitCount, NULL);
  2094. lpSrcDIB = (LPBYTE)GlobalLock(hDIB);
  2095. lpDIB = (LPBYTE)GlobalLock(hNewDib);
  2096. dwSize = GlobalSize(hNewDib);
  2097. memcpy(lpSrcDIB, lpDIB, dwSize);
  2098. GlobalUnlock(hDIB);
  2099. GlobalUnlock(hNewDib);
  2100. }
  2101. else
  2102. {
  2103. lpSrcDIB = (LPBYTE)GlobalLock(hDIB);
  2104. lpDIB = (LPBYTE)GlobalLock(hDib);
  2105. dwSize = GlobalSize(hDib);
  2106. memcpy(lpSrcDIB, lpDIB, dwSize);
  2107. GlobalUnlock(hDIB);
  2108. GlobalUnlock(hDib);
  2109. }
  2110. // cleanup
  2111. GlobalFree(hDib);
  2112. GlobalFree(hNewDib);
  2113. // return
  2114. WaitCursorEnd();
  2115. return TRUE;
  2116. }