/WPFImage/AForge.Imaging/Filters/Color Filters/ContrastStretch.cs

# · C# · 172 lines · 85 code · 26 blank · 61 comment · 14 complexity · 74206c7cc54b0e94ff3e306c40adc3f8 MD5 · raw file

  1. // AForge Image Processing Library
  2. // AForge.NET framework
  3. //
  4. // Copyright Š
  5. // Andrew Kirillov (andrew.kirillov@aforgenet.com),
  6. // Mladen Prajdic (spirit1_fe@yahoo.com)
  7. // 2005-2009
  8. //
  9. namespace AForge.Imaging.Filters
  10. {
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Drawing;
  14. using System.Drawing.Imaging;
  15. /// <summary>
  16. /// Contrast stretching filter.
  17. /// </summary>
  18. ///
  19. /// <remarks><para>Contrast stretching (or as it is often called normalization) is a simple image enhancement
  20. /// technique that attempts to improve the contrast in an image by 'stretching' the range of intensity values
  21. /// it contains to span a desired range of values, e.g. the the full range of pixel values that the image type
  22. /// concerned allows. It differs from the more sophisticated <seealso cref="HistogramEqualization">histogram equalization</seealso>
  23. /// in that it can only apply a linear scaling function to the image pixel values.</para>
  24. ///
  25. /// <para>The result of this filter may be achieved by using <see cref="ImageStatistics"/> class, which allows to
  26. /// get pixels' intensities histogram, and <see cref="LevelsLinear"/> filter, which does linear correction
  27. /// of pixel's intensities.</para>
  28. ///
  29. /// <para>The filter accepts 8 bpp grayscale and 24 bpp color images.</para>
  30. ///
  31. /// <para>Sample usage:</para>
  32. /// <code>
  33. /// // create filter
  34. /// ContrastStretch filter = new ContrastStretch( );
  35. /// // process image
  36. /// filter.ApplyInPlace( sourceImage );
  37. /// </code>
  38. ///
  39. /// <para><b>Source image:</b></para>
  40. /// <img src="img/imaging/sample5.jpg" width="480" height="387" />
  41. /// <para><b>Result image:</b></para>
  42. /// <img src="img/imaging/contrast_stretch.jpg" width="480" height="387" />
  43. /// </remarks>
  44. ///
  45. [Serializable] public class ContrastStretch : BaseInPlacePartialFilter
  46. {
  47. // private format translation dictionary
  48. private Dictionary<PixelFormat, PixelFormat> formatTransalations = new Dictionary<PixelFormat, PixelFormat>( );
  49. /// <summary>
  50. /// Format translations dictionary.
  51. /// </summary>
  52. public override Dictionary<PixelFormat, PixelFormat> FormatTransalations
  53. {
  54. get { return formatTransalations; }
  55. }
  56. /// <summary>
  57. /// Initializes a new instance of the <see cref="ContrastStretch"/> class.
  58. /// </summary>
  59. public ContrastStretch( )
  60. {
  61. formatTransalations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed;
  62. formatTransalations[PixelFormat.Format24bppRgb] = PixelFormat.Format24bppRgb;
  63. formatTransalations[PixelFormat.Format32bppRgb] = PixelFormat.Format32bppRgb;
  64. formatTransalations[PixelFormat.Format32bppArgb] = PixelFormat.Format32bppArgb;
  65. }
  66. /// <summary>
  67. /// Process the filter on the specified image.
  68. /// </summary>
  69. ///
  70. /// <param name="image">Source image data.</param>
  71. /// <param name="rect">Image rectangle for processing by the filter.</param>
  72. ///
  73. protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect )
  74. {
  75. int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8;
  76. int startX = rect.Left;
  77. int startY = rect.Top;
  78. int stopX = startX + rect.Width;
  79. int stopY = startY + rect.Height;
  80. int stride = image.Stride;
  81. int offset = stride - rect.Width * pixelSize;
  82. // levels linear correction filter is going to be used on STEP 2
  83. LevelsLinear levelsLinear = new LevelsLinear( );
  84. // STEP 1 - search for min and max pixel values
  85. byte* ptr = (byte*) image.ImageData.ToPointer( );
  86. // check image format
  87. if ( image.PixelFormat == PixelFormat.Format8bppIndexed )
  88. {
  89. // allign pointer to the first pixel to process
  90. ptr += ( startY * stride + startX );
  91. byte min = 255;
  92. byte max = 0;
  93. for ( int y = startY; y < stopY; y++ )
  94. {
  95. for ( int x = startX; x < stopX; x++, ptr++ )
  96. {
  97. byte value = *ptr;
  98. if ( value < min )
  99. min = value;
  100. if ( value > max )
  101. max = value;
  102. }
  103. ptr += offset;
  104. }
  105. levelsLinear.InGray = new IntRange( min, max );
  106. }
  107. else
  108. {
  109. // allign pointer to the first pixel to process
  110. ptr += ( startY * stride + startX * pixelSize );
  111. byte minR = 255, minG = 255, minB = 255;
  112. byte maxR = 0, maxG = 0, maxB = 0;
  113. for ( int y = startY; y < stopY; y++ )
  114. {
  115. for ( int x = startX; x < stopX; x++, ptr += pixelSize )
  116. {
  117. // red
  118. byte value = ptr[RGB.R];
  119. if ( value < minR )
  120. minR = value;
  121. if ( value > maxR )
  122. maxR = value;
  123. // green
  124. value = ptr[RGB.G];
  125. if ( value < minG )
  126. minG = value;
  127. if ( value > maxG )
  128. maxG = value;
  129. // blue
  130. value = ptr[RGB.B];
  131. if ( value < minB )
  132. minB = value;
  133. if ( value > maxB )
  134. maxB = value;
  135. }
  136. ptr += offset;
  137. }
  138. levelsLinear.InRed = new IntRange( minR, maxR );
  139. levelsLinear.InGreen = new IntRange( minG, maxG );
  140. levelsLinear.InBlue = new IntRange( minB, maxB );
  141. }
  142. // STEP 2 - run levels linear correction
  143. levelsLinear.ApplyInPlace( image, rect );
  144. }
  145. }
  146. }