You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

BaseLuminanceSource.cs 7.6 kB

10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * Copyright 2012 ZXing.Net authors
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. using System;
  17. namespace ZXing
  18. {
  19. /// <summary>
  20. /// The base class for luminance sources which supports
  21. /// cropping and rotating based upon the luminance values.
  22. /// </summary>
  23. public abstract class BaseLuminanceSource : LuminanceSource
  24. {
  25. // the following channel weights give nearly the same
  26. // gray scale picture as the java version with BufferedImage.TYPE_BYTE_GRAY
  27. // they are used in sub classes for luminance / gray scale calculation
  28. protected const int RChannelWeight = 19562;
  29. protected const int GChannelWeight = 38550;
  30. protected const int BChannelWeight = 7424;
  31. protected const int ChannelWeight = 16;
  32. /// <summary>
  33. ///
  34. /// </summary>
  35. protected byte[] luminances;
  36. /// <summary>
  37. /// Initializes a new instance of the <see cref="BaseLuminanceSource"/> class.
  38. /// </summary>
  39. /// <param name="width">The width.</param>
  40. /// <param name="height">The height.</param>
  41. protected BaseLuminanceSource(int width, int height)
  42. : base(width, height)
  43. {
  44. luminances = new byte[width * height];
  45. }
  46. /// <summary>
  47. /// Initializes a new instance of the <see cref="BaseLuminanceSource"/> class.
  48. /// </summary>
  49. /// <param name="luminanceArray">The luminance array.</param>
  50. /// <param name="width">The width.</param>
  51. /// <param name="height">The height.</param>
  52. protected BaseLuminanceSource(byte[] luminanceArray, int width, int height)
  53. : base(width, height)
  54. {
  55. luminances = new byte[width * height];
  56. Buffer.BlockCopy(luminanceArray, 0, luminances, 0, width * height);
  57. }
  58. /// <summary>
  59. /// Fetches one row of luminance data from the underlying platform's bitmap. Values range from
  60. /// 0 (black) to 255 (white). It is preferable for implementations of this method
  61. /// to only fetch this row rather than the whole image, since no 2D Readers may be installed and
  62. /// getMatrix() may never be called.
  63. /// </summary>
  64. /// <param name="y">The row to fetch, 0 &lt;= y &lt; Height.</param>
  65. /// <param name="row">An optional preallocated array. If null or too small, it will be ignored.
  66. /// Always use the returned object, and ignore the .length of the array.</param>
  67. /// <returns>
  68. /// An array containing the luminance data.
  69. /// </returns>
  70. override public byte[] getRow(int y, byte[] row)
  71. {
  72. int width = Width;
  73. if (row == null || row.Length < width)
  74. {
  75. row = new byte[width];
  76. }
  77. for (int i = 0; i < width; i++)
  78. row[i] = luminances[y * width + i];
  79. return row;
  80. }
  81. public override byte[] Matrix
  82. {
  83. get { return luminances; }
  84. }
  85. /// <summary>
  86. /// Returns a new object with rotated image data by 90 degrees counterclockwise.
  87. /// Only callable if {@link #isRotateSupported()} is true.
  88. /// </summary>
  89. /// <returns>
  90. /// A rotated version of this object.
  91. /// </returns>
  92. public override LuminanceSource rotateCounterClockwise()
  93. {
  94. var rotatedLuminances = new byte[Width * Height];
  95. var newWidth = Height;
  96. var newHeight = Width;
  97. var localLuminances = Matrix;
  98. for (var yold = 0; yold < Height; yold++)
  99. {
  100. for (var xold = 0; xold < Width; xold++)
  101. {
  102. var ynew = newHeight - xold - 1;
  103. var xnew = yold;
  104. rotatedLuminances[ynew * newWidth + xnew] = localLuminances[yold * Width + xold];
  105. }
  106. }
  107. return CreateLuminanceSource(rotatedLuminances, newWidth, newHeight);
  108. }
  109. /// <summary>
  110. /// TODO: not implemented yet
  111. /// </summary>
  112. /// <returns>
  113. /// A rotated version of this object.
  114. /// </returns>
  115. public override LuminanceSource rotateCounterClockwise45()
  116. {
  117. // TODO: implement a good 45 degrees rotation without lost of information
  118. return base.rotateCounterClockwise45();
  119. }
  120. /// <summary>
  121. /// </summary>
  122. /// <returns> Whether this subclass supports counter-clockwise rotation.</returns>
  123. public override bool RotateSupported
  124. {
  125. get
  126. {
  127. return true;
  128. }
  129. }
  130. /// <summary>
  131. /// Returns a new object with cropped image data. Implementations may keep a reference to the
  132. /// original data rather than a copy. Only callable if CropSupported is true.
  133. /// </summary>
  134. /// <param name="left">The left coordinate, 0 &lt;= left &lt; Width.</param>
  135. /// <param name="top">The top coordinate, 0 &lt;= top &lt;= Height.</param>
  136. /// <param name="width">The width of the rectangle to crop.</param>
  137. /// <param name="height">The height of the rectangle to crop.</param>
  138. /// <returns>
  139. /// A cropped version of this object.
  140. /// </returns>
  141. public override LuminanceSource crop(int left, int top, int width, int height)
  142. {
  143. if (left + width > Width || top + height > Height)
  144. {
  145. throw new ArgumentException("Crop rectangle does not fit within image data.");
  146. }
  147. var croppedLuminances = new byte[width * height];
  148. var oldLuminances = Matrix;
  149. var oldWidth = Width;
  150. var oldRightBound = left + width;
  151. var oldBottomBound = top + height;
  152. for (int yold = top, ynew = 0; yold < oldBottomBound; yold++, ynew++)
  153. {
  154. for (int xold = left, xnew = 0; xold < oldRightBound; xold++, xnew++)
  155. {
  156. croppedLuminances[ynew * width + xnew] = oldLuminances[yold * oldWidth + xold];
  157. }
  158. }
  159. return CreateLuminanceSource(croppedLuminances, width, height);
  160. }
  161. /// <summary>
  162. /// </summary>
  163. /// <returns> Whether this subclass supports cropping.</returns>
  164. public override bool CropSupported
  165. {
  166. get
  167. {
  168. return true;
  169. }
  170. }
  171. /// <summary>
  172. /// </summary>
  173. /// <returns>Whether this subclass supports invertion.</returns>
  174. public override bool InversionSupported
  175. {
  176. get
  177. {
  178. return true;
  179. }
  180. }
  181. /// <summary>
  182. /// Should create a new luminance source with the right class type.
  183. /// The method is used in methods crop and rotate.
  184. /// </summary>
  185. /// <param name="newLuminances">The new luminances.</param>
  186. /// <param name="width">The width.</param>
  187. /// <param name="height">The height.</param>
  188. /// <returns></returns>
  189. protected abstract LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height);
  190. }
  191. }