home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / include / Image.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-11  |  9.2 KB  |  415 lines

  1. #pragma once
  2.  
  3. //-----------------------------------------------------------------------------------//
  4. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  5. //                             ISBN  0-13-086985-6                                   //
  6. //                                                                                   //
  7. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  8. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  9. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  10. //                                                                                   //
  11. //  FileName   : image.h                                                             //
  12. //  Description: Generic image processing algorithms and classes                     //
  13. //  Version    : 1.00.000, May 31, 2000                                              //
  14. //-----------------------------------------------------------------------------------//
  15.  
  16. #include <math.h>
  17. #include "Color.h"
  18.  
  19. // Abstract class for mapping single pixel and scan line
  20. class KPixelMapper
  21. {
  22.     BYTE * m_pColor;    // point to color table BGR...
  23.     int    m_nSize;        // size of an entry in the table 3 or 4
  24.     int       m_nCount;    // number of entries in the table
  25.  
  26.     // return true if data changed
  27.     virtual bool MapRGB(BYTE & red, BYTE & green, BYTE & blue) = 0;
  28.  
  29.     // return true if data changed
  30.     virtual bool MapIndex(BYTE & index)
  31.     {
  32.         MapRGB(m_pColor[index*m_nSize+2], 
  33.                m_pColor[index*m_nSize+1], 
  34.                m_pColor[index*m_nSize]);
  35.  
  36.         return false;
  37.     }
  38.  
  39. public:
  40.  
  41.     KPixelMapper(void)
  42.     {
  43.         m_pColor = NULL;
  44.         m_nSize  = 0;
  45.         m_nCount = 0;
  46.     }
  47.  
  48.     virtual ~ KPixelMapper()
  49.     {
  50.     }
  51.  
  52.     void SetColorTable(BYTE * pColor, int nEntrySize, int nCount)
  53.     {
  54.         m_pColor = pColor;
  55.         m_nSize  = nEntrySize;
  56.         m_nCount = nCount;
  57.     }
  58.  
  59.     virtual bool StartLine(int line)
  60.     {
  61.         return true;
  62.     }
  63.  
  64.     virtual void Map1bpp(BYTE * pBuffer, int width);
  65.     virtual void Map2bpp(BYTE * pBuffer, int width);
  66.     virtual void Map4bpp(BYTE * pBuffer, int width);
  67.     virtual void Map8bpp(BYTE * pBuffer, int width);
  68.     virtual void  Map555(BYTE * pBuffer, int width);
  69.     virtual void  Map565(BYTE * pBuffer, int width);
  70.     virtual void Map24bpp(BYTE * pBuffer, int width);
  71.     virtual void Map32bpp(BYTE * pBuffer, int width);
  72.  
  73. };
  74.  
  75. typedef BYTE (* Operator)(BYTE red, BYTE green, BYTE blue);
  76.  
  77. class KDIB;
  78. class KImage;
  79.  
  80. // Generic channel splitting class derived from CPixelMapper
  81. // Controled by an operator function passed to CChannel::Split
  82. class KChannel : public KPixelMapper
  83. {
  84.     Operator  m_Operator;
  85.     int          m_nBPS;
  86.     
  87.     BYTE * m_pBits;
  88.     BYTE * m_pPixel;
  89.  
  90.     // return true if data changed
  91.     virtual bool MapRGB(BYTE & red, BYTE & green, BYTE & blue)
  92.     {
  93.         * m_pPixel ++ = m_Operator(red, green, blue);
  94.  
  95.         return false;
  96.     }
  97.  
  98.     virtual bool StartLine(int line)
  99.     {
  100.         m_pPixel = m_pBits + line * m_nBPS; // first pixel of a scanline
  101.  
  102.         return true;
  103.     }
  104.  
  105. public:
  106.  
  107.     BITMAPINFO * Split(KImage & dib, Operator oper);
  108. };
  109.  
  110.  
  111. // RGB channel splitting operators
  112.  
  113. inline BYTE TakeRed(BYTE red, BYTE green, BYTE blue)
  114. {
  115.     return red;
  116. }
  117.  
  118. inline BYTE TakeGreen(BYTE red, BYTE green, BYTE blue)
  119. {
  120.     return green;
  121. }
  122.  
  123. inline BYTE TakeBlue(BYTE red, BYTE green, BYTE blue)
  124. {
  125.     return blue;
  126. }
  127.  
  128. // KCMY channel splitting operators
  129. inline BYTE TakeK(BYTE red, BYTE green, BYTE blue)
  130. {
  131.     // min ( 255-red, 255-green, 255-blue)
  132.     if ( red < green )
  133.         if ( green < blue )
  134.             return 255 - blue;
  135.         else
  136.             return 255 - green;
  137.     else
  138.         return 255 - red;
  139. }
  140.  
  141. inline BYTE TakeC(BYTE red, BYTE green, BYTE blue)
  142. {
  143.     return 255 - red; // - TakeK(red, green, blue);
  144. }
  145.  
  146. inline BYTE TakeM(BYTE red, BYTE green, BYTE blue)
  147. {
  148.     return 255 - green; //  - TakeK(red, green, blue);
  149. }
  150.  
  151. inline BYTE TakeY(BYTE red, BYTE green, BYTE blue)
  152. {
  153.     return 255 - blue; //  - TakeK(red, green, blue);
  154. }
  155.  
  156. // HLS channel splitting operators
  157. inline BYTE TakeH(BYTE red, BYTE green, BYTE blue)
  158. {
  159.     KColor color(red, green, blue);
  160.     color.ToHLS();
  161.  
  162.     return (BYTE) (color.hue * 255 / 360);
  163. }
  164.  
  165. inline BYTE TakeL(BYTE red, BYTE green, BYTE blue)
  166. {
  167.     KColor color(red, green, blue);
  168.     color.ToHLS();
  169.  
  170.     return (BYTE) (color.lightness * 255);
  171. }
  172.  
  173. inline BYTE TakeS(BYTE red, BYTE green, BYTE blue)
  174. {
  175.     KColor color(red, green, blue);
  176.     color.ToHLS();
  177.  
  178.     return (BYTE) (color.saturation * 255);
  179. }
  180.  
  181.  
  182. // 0.299 * red + 0.587 * green + 0.114 * blue 
  183. inline void MaptoGray(BYTE & red, BYTE & green, BYTE & blue)
  184. {
  185.     red   = ( red * 77 + green * 150 + blue * 29 + 128 ) / 256;
  186.     green = red;
  187.     blue  = red;
  188. }
  189.  
  190. inline void LightenColor(BYTE & red, BYTE & green, BYTE & blue)
  191. {
  192.     KColor color( red, green, blue );
  193.     color.ToHLS();
  194.  
  195.     color.lightness = sqrt(color.lightness);
  196.     color.ToRGB();
  197.  
  198.     red   = color.red;
  199.     green = color.green;
  200.     blue  = color.blue;
  201. }
  202.  
  203.  
  204. // RGB Histogram class derived from CPixelMapper
  205. class KHistogram : public KPixelMapper
  206. {
  207.     int          m_FreqRed[256];
  208.     int          m_FreqGreen[256];
  209.     int          m_FreqBlue[256];
  210.     int          m_FreqGray[256];
  211.  
  212.     // return true if data changed
  213.     virtual bool MapRGB(BYTE & red, BYTE & green, BYTE & blue)
  214.     {
  215.         m_FreqRed[red]     ++;
  216.         m_FreqGreen[green] ++;
  217.         m_FreqBlue[blue]   ++;
  218.         m_FreqGray[(red * 77 + green * 150 + blue * 29 + 128 ) / 256] ++;
  219.  
  220.         return false;
  221.     }
  222.  
  223. public:
  224.  
  225.     void Sample(KImage & dib);
  226. };
  227.  
  228.  
  229. // Abstract class for image convolution for single pixel and scan line
  230. class KFilter
  231. {
  232.     int    m_nHalf;
  233.  
  234.     virtual BYTE Kernel(BYTE * pPixel, int dx, int dy) = 0;
  235.  
  236. public:
  237.  
  238.     int GetHalf(void) const
  239.     {
  240.         return m_nHalf;
  241.     }
  242.  
  243.     KFilter(void)
  244.     {
  245.         m_nHalf = 1;
  246.     }
  247.  
  248.     virtual ~ KFilter()
  249.     {
  250.     }
  251.  
  252.     virtual void DescribeFilter(HDC hDC, int x, int y)
  253.     {
  254.     }
  255.  
  256.     virtual void  Filter8bpp(BYTE * pDest, BYTE * pSource, int nWidth, int dy);
  257.     virtual void Filter24bpp(BYTE * pDest, BYTE * pSource, int nWidth, int dy);
  258.     virtual void Filter32bpp(BYTE * pDest, BYTE * pSource, int nWidth, int dy);
  259. };
  260.  
  261.  
  262. void Describe33Filter(HDC hDC, int x, int y, const int * matrix, TCHAR * name, int weight, int add);
  263.  
  264. template <int k00, int k01, int k02, int k10, int k11, int k12, int k20, int k21, int k22, 
  265.           int weight, int add, bool checkbound, TCHAR * name>
  266. class K33Filter : public KFilter
  267. {
  268.     virtual BYTE Kernel(BYTE * pPixel, int dx, int dy)
  269.     {
  270.         int rslt = ( pPixel[-dy-dx] * k00 + pPixel[-dy] * k01 + pPixel[-dy+dx] * k02 +
  271.                      pPixel[   -dx] * k10 + pPixel[0]   * k11 + pPixel[   +dx] * k12 +
  272.                      pPixel[ dy-dx] * k20 + pPixel[dy]  * k21 + pPixel[ dy+dx] * k22 ) / weight + add;
  273.  
  274.         if ( checkbound )
  275.             if ( rslt < 0 )
  276.                 return 0;
  277.             else if ( rslt > 255 )
  278.                 return 255;
  279.  
  280.         return rslt;
  281.     }
  282.  
  283.     void DescribeFilter(HDC hDC, int x, int y)
  284.     {
  285.         const int matrix[] = { k00, k01, k02, k10, k11, k12, k20, k21, k22 };
  286.     
  287.         Describe33Filter(hDC, x, y, matrix, name, weight, add);
  288.     }
  289. };
  290.  
  291.  
  292. // Mimimum to grow the darker region
  293. class KErosion : public KFilter
  294. {
  295.     inline void smaller(BYTE &x, BYTE y)
  296.     {
  297.         if ( y < x ) x = y;
  298.     }
  299.  
  300.     BYTE Kernel(BYTE * pPixel, int dx, int dy)
  301.     {
  302.         BYTE m = pPixel[-dy-dx];
  303.  
  304.         smaller(m, pPixel[-dy]);
  305.         smaller(m, pPixel[-dy+dx]);
  306.         smaller(m, pPixel[   -dx]);
  307.         smaller(m, pPixel[   +dx]);
  308.         smaller(m, pPixel[ dy-dx]);
  309.         smaller(m, pPixel[dy]);
  310.         smaller(m, pPixel[ dy+dx]);
  311.         
  312.         return min(pPixel[0], m); // /2;
  313.     }
  314.  
  315.     void DescribeFilter(HDC hDC, int x, int y)
  316.     {
  317.         Describe33Filter(hDC, x, y, NULL, _T("Erosion"), 0, 0);
  318.     }
  319. };
  320.  
  321. // Maximum to grow the light region
  322. class KDilation : public KFilter
  323. {
  324.     inline void bigger(BYTE &x, BYTE y)
  325.     {
  326.         if ( y > x ) x = y;
  327.     }
  328.  
  329.     BYTE Kernel(BYTE * pPixel, int dx, int dy)
  330.     {
  331.         BYTE m = pPixel[-dy-dx];
  332.  
  333.         bigger(m, pPixel[-dy]);
  334.         bigger(m, pPixel[-dy+dx]);
  335.         bigger(m, pPixel[   -dx]);
  336.         bigger(m, pPixel[   +dx]);
  337.         bigger(m, pPixel[ dy-dx]);
  338.         bigger(m, pPixel[dy]);
  339.         bigger(m, pPixel[ dy+dx]);
  340.         
  341.         return max( pPixel[0], m ); // /2;
  342.     }
  343.  
  344.     void DescribeFilter(HDC hDC, int x, int y)
  345.     {
  346.         Describe33Filter(hDC, x, y, NULL, _T("Dilation"), 0, 0);
  347.     }
  348. };
  349.  
  350.  
  351. // Maximum to grow the light region, then substract
  352. class KOutline : public KFilter
  353. {
  354.     inline void bigger(BYTE &x, BYTE y)
  355.     {
  356.         if ( y > x ) x = y;
  357.     }
  358.  
  359.     BYTE Kernel(BYTE * pPixel, int dx, int dy)
  360.     {
  361.         BYTE m = pPixel[0];
  362.         
  363.         bigger(m, pPixel[-dy-dx]);
  364.         bigger(m, pPixel[-dy]);
  365.         bigger(m, pPixel[-dy+dx]);
  366.         bigger(m, pPixel[   -dx]);
  367.         bigger(m, pPixel[   +dx]);
  368.         bigger(m, pPixel[ dy-dx]);
  369.         bigger(m, pPixel[dy]);
  370.         bigger(m, pPixel[ dy+dx]);
  371.         
  372.         return m - pPixel[0];
  373.     }
  374.  
  375.     void DescribeFilter(HDC hDC, int x, int y)
  376.     {
  377.         Describe33Filter(hDC, x, y, NULL, _T("Outline"), 0, 0);
  378.     }
  379. };
  380.  
  381.  
  382. typedef enum
  383. {
  384.     FILTER_IDENTITY,
  385.  
  386.     FILTER_SMOOTH,
  387.     FILTER_GUASSIANSMOOTH,
  388.     FILTER_SHARPENING,
  389.     FILTER_LAPLASION,
  390.     FILTER_EMBOSS135,
  391.     FILTER_EMBOSS90,
  392.     FILTER_DILATION,
  393.     FILTER_EROSION,
  394.     FILTER_OUTLINE,
  395.     
  396.     FILTER_LAST = FILTER_OUTLINE
  397. };
  398.  
  399. KFilter * StockFilters[];
  400.  
  401.  
  402. class KImage : public KDIB
  403. {
  404. public:
  405.     bool ToGreyScale(void);
  406.     bool Lighten(void);
  407.     bool GammaCorrect(double redgamma, double greengamma, double bluegamma);
  408.  
  409.     BITMAPINFO * SplitChannel(Operator oper);
  410.  
  411.     bool    PixelTransform(KPixelMapper & map);
  412.     bool    Convolution(KFilter * pFilter);
  413. };
  414.  
  415.