FHistogram.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Copyright (C) =USTC= Fu Li
  3. *
  4. * Author : Fu Li
  5. * Create : 2003-12-23
  6. * Home : http://www.crazy-bit.com/
  7. * Mail : crazybit@263.net
  8. * History :
  9. */
  10. #ifndef __PCL_HISTOGRAM__2003_12_23__H__
  11. #define __PCL_HISTOGRAM__2003_12_23__H__
  12. #include "ObjImage.h"
  13. //=============================================================================
  14. /**
  15. * Calculate histogram of image.
  16. */
  17. class FCHistogram
  18. {
  19. public:
  20. /// Calculate img's histogram, img's bpp >= 24.
  21. FCHistogram (const FCObjImage& img) ;
  22. /// Analyze image (only 24bpp or 32bpp image can be analyzed).
  23. void AnalyzeImage (const FCObjImage& img) ;
  24. /**
  25. * @name Get/Set histogram Stat. range.
  26. */
  27. //@{
  28. /// Get start position.
  29. int GetStart() const {return m_nStart;}
  30. /// Get end position.
  31. int GetEnd() const {return m_nEnd;}
  32. /// Set start position.
  33. void SetStart (int nStart) {m_nStart = FClamp0255(nStart);}
  34. /// Set end position.
  35. void SetEnd (int nEnd) {m_nEnd = FClamp0255(nEnd);}
  36. //@}
  37. /**
  38. * @name Query attributes.
  39. * nChannel can be CHANNEL_GRAY, CHANNEL_RED, CHANNEL_GREEN, CHANNEL_BLUE
  40. */
  41. //@{
  42. /// Get pixel count of Stat. image.
  43. int GetPixelNumber() const {return m_nPixelNum;}
  44. /// Pixel count of selected region (nChannel).
  45. int GetCount (IMAGE_CHANNEL nChannel = CHANNEL_GRAY) const ;
  46. /// Pixel count of nValue position (nChannel).
  47. int GetValueCount (int nValue, IMAGE_CHANNEL nChannel = CHANNEL_GRAY) const ;
  48. /// Pixel average of selected region (nChannel).
  49. int GetAverage (IMAGE_CHANNEL nChannel = CHANNEL_GRAY) const ;
  50. /// Get max count in selected region (nChannel).
  51. int GetMaxCount (IMAGE_CHANNEL nChannel = CHANNEL_GRAY) const ;
  52. /// Received img is 24bpp, size is (256,nHeight)
  53. void GetHistogramImage (int nHeight, FCObjImage* img, IMAGE_CHANNEL nChannel = CHANNEL_GRAY) const ;
  54. //@}
  55. private:
  56. const PCL_array<int>& GetChannelHistogram (IMAGE_CHANNEL nChannel) const
  57. {
  58. switch (nChannel)
  59. {
  60. case CHANNEL_RED : return m_HisRed ;
  61. case CHANNEL_GREEN : return m_HisGreen ;
  62. case CHANNEL_BLUE : return m_HisBlue ;
  63. }
  64. return m_HisGray ;
  65. }
  66. private:
  67. PCL_array<int> m_HisGray, m_HisRed, m_HisGreen, m_HisBlue ;
  68. int m_nStart ;
  69. int m_nEnd ;
  70. int m_nPixelNum ;
  71. };
  72. //=============================================================================
  73. // inline Implement
  74. //=============================================================================
  75. inline FCHistogram::FCHistogram (const FCObjImage& img) : m_HisGray(256), m_HisRed(256), m_HisGreen(256), m_HisBlue(256)
  76. {
  77. m_nStart = 0 ;
  78. m_nEnd = 255 ;
  79. m_nPixelNum = 0 ;
  80. AnalyzeImage (img) ;
  81. }
  82. //-----------------------------------------------------------------------------
  83. inline void FCHistogram::AnalyzeImage (const FCObjImage& img)
  84. {
  85. if (!img.IsValidImage() || (img.ColorBits() < 24))
  86. {assert(false); return;}
  87. for (int i=0 ; i < 256 ; i++)
  88. {
  89. m_HisGray[i] = m_HisRed[i] = m_HisGreen[i] = m_HisBlue[i] = 0 ;
  90. }
  91. m_nPixelNum = img.Width()*img.Height() ;
  92. for (int y=0 ; y < img.Height() ; y++)
  93. for (int x=0 ; x <img.Width() ; x++)
  94. {
  95. BYTE * p = img.GetBits(x,y) ;
  96. m_HisBlue[PCL_B(p)]++ ;
  97. m_HisGreen[PCL_G(p)]++ ;
  98. m_HisRed[PCL_R(p)]++ ;
  99. m_HisGray[FCColor::GetGrayscale(p)]++ ;
  100. }
  101. }
  102. //-----------------------------------------------------------------------------
  103. inline int FCHistogram::GetCount (IMAGE_CHANNEL nChannel) const
  104. {
  105. int nCount = 0 ;
  106. for (int i=m_nStart ; i <= m_nEnd ; i++)
  107. nCount += GetChannelHistogram(nChannel)[i] ;
  108. return nCount ;
  109. }
  110. //-----------------------------------------------------------------------------
  111. inline int FCHistogram::GetValueCount (int nValue, IMAGE_CHANNEL nChannel) const
  112. {
  113. return GetChannelHistogram(nChannel)[FClamp0255(nValue)] ;
  114. }
  115. //-----------------------------------------------------------------------------
  116. inline int FCHistogram::GetAverage (IMAGE_CHANNEL nChannel) const
  117. {
  118. double fAverage = 0 ;
  119. int nCount = 0 ;
  120. for (int i=m_nStart ; i <= m_nEnd ; i++)
  121. {
  122. int n = GetChannelHistogram(nChannel)[i] ;
  123. nCount += n ;
  124. fAverage = fAverage + n * i ;
  125. }
  126. return nCount ? (int)(fAverage/nCount) : 0 ;
  127. }
  128. //-----------------------------------------------------------------------------
  129. inline int FCHistogram::GetMaxCount (IMAGE_CHANNEL nChannel) const
  130. {
  131. int nMaxCount = 0 ;
  132. for (int i=m_nStart ; i <= m_nEnd ; i++)
  133. {
  134. int n = GetChannelHistogram(nChannel)[i] ;
  135. if (n > nMaxCount)
  136. nMaxCount = n ;
  137. }
  138. return nMaxCount ;
  139. }
  140. //-----------------------------------------------------------------------------
  141. inline void FCHistogram::GetHistogramImage (int nHeight, FCObjImage* img, IMAGE_CHANNEL nChannel) const
  142. {
  143. if (!img || !img->Create (256, nHeight, 24))
  144. return ;
  145. // fill white back
  146. memset (img->GetMemStart(), 0xFF, img->GetPitch() * img->Height()) ;
  147. int nMaxCount = GetMaxCount(nChannel) ;
  148. if (nMaxCount == 0)
  149. return ;
  150. for (int x=0 ; x < img->Width() ; x++)
  151. {
  152. int nFill = FClamp (GetChannelHistogram(nChannel)[x]*img->Height()/nMaxCount, 0, img->Height()) ;
  153. for (int i=0 ; i < nFill ; i++)
  154. {
  155. BYTE * p = img->GetBits(x, img->Height() - 1 - i) ;
  156. PCL_R(p) = PCL_G(p) = PCL_B(p) = 0 ;
  157. }
  158. }
  159. }
  160. #endif