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

ZXRGBLuminanceSource.m 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Copyright 2012 ZXing 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. #import "ZXByteArray.h"
  17. #import "ZXRGBLuminanceSource.h"
  18. @interface ZXRGBLuminanceSource ()
  19. @property (nonatomic, strong, readonly) ZXByteArray *luminances;
  20. @property (nonatomic, assign, readonly) int dataWidth;
  21. @property (nonatomic, assign, readonly) int dataHeight;
  22. @property (nonatomic, assign, readonly) int left;
  23. @property (nonatomic, assign, readonly) int top;
  24. @end
  25. @implementation ZXRGBLuminanceSource
  26. - (id)initWithWidth:(int)width height:(int)height pixels:(int *)pixels pixelsLen:(int)pixelsLen {
  27. if (self = [super initWithWidth:width height:height]) {
  28. _dataWidth = width;
  29. _dataHeight = height;
  30. _left = 0;
  31. _top = 0;
  32. // In order to measure pure decoding speed, we convert the entire image to a greyscale array
  33. // up front, which is the same as the Y channel of the YUVLuminanceSource in the real app.
  34. _luminances = [[ZXByteArray alloc] initWithLength:width * height];
  35. for (int y = 0; y < height; y++) {
  36. int offset = y * width;
  37. for (int x = 0; x < width; x++) {
  38. int pixel = pixels[offset + x];
  39. int r = (pixel >> 16) & 0xff;
  40. int g = (pixel >> 8) & 0xff;
  41. int b = pixel & 0xff;
  42. if (r == g && g == b) {
  43. // Image is already greyscale, so pick any channel.
  44. _luminances.array[offset + x] = (int8_t) r;
  45. } else {
  46. // Calculate luminance cheaply, favoring green.
  47. _luminances.array[offset + x] = (int8_t) ((r + g + g + b) / 4);
  48. }
  49. }
  50. }
  51. }
  52. return self;
  53. }
  54. - (id)initWithPixels:(ZXByteArray *)pixels dataWidth:(int)dataWidth dataHeight:(int)dataHeight
  55. left:(int)left top:(int)top width:(int)width height:(int)height {
  56. if (self = [super initWithWidth:width height:height]) {
  57. if (left + self.width > dataWidth || top + self.height > dataHeight) {
  58. [NSException raise:NSInvalidArgumentException format:@"Crop rectangle does not fit within image data."];
  59. }
  60. _luminances = pixels;
  61. _dataWidth = dataWidth;
  62. _dataHeight = dataHeight;
  63. _left = left;
  64. _top = top;
  65. }
  66. return self;
  67. }
  68. - (ZXByteArray *)rowAtY:(int)y row:(ZXByteArray *)row {
  69. if (y < 0 || y >= self.height) {
  70. [NSException raise:NSInvalidArgumentException format:@"Requested row is outside the image: %d", y];
  71. }
  72. int width = self.width;
  73. if (!row || row.length < width) {
  74. row = [[ZXByteArray alloc] initWithLength:width];
  75. }
  76. int offset = (y + self.top) * self.dataWidth + self.left;
  77. memcpy(row.array, self.luminances.array + offset, self.width * sizeof(int8_t));
  78. return row;
  79. }
  80. - (ZXByteArray *)matrix {
  81. int width = self.width;
  82. int height = self.height;
  83. // If the caller asks for the entire underlying image, save the copy and give them the
  84. // original data. The docs specifically warn that result.length must be ignored.
  85. if (width == self.dataWidth && height == self.dataHeight) {
  86. return self.luminances;
  87. }
  88. int area = self.width * self.height;
  89. ZXByteArray *matrix = [[ZXByteArray alloc] initWithLength:area];
  90. int inputOffset = self.top * self.dataWidth + self.left;
  91. // If the width matches the full width of the underlying data, perform a single copy.
  92. if (self.width == self.dataWidth) {
  93. memcpy(matrix.array, self.luminances.array + inputOffset, (area - inputOffset) * sizeof(int8_t));
  94. return matrix;
  95. }
  96. // Otherwise copy one cropped row at a time.
  97. for (int y = 0; y < self.height; y++) {
  98. int outputOffset = y * self.width;
  99. memcpy(matrix.array + outputOffset, self.luminances.array + inputOffset, self.width * sizeof(int8_t));
  100. inputOffset += self.dataWidth;
  101. }
  102. return matrix;
  103. }
  104. - (BOOL)cropSupported {
  105. return YES;
  106. }
  107. - (ZXLuminanceSource *)crop:(int)left top:(int)top width:(int)width height:(int)height {
  108. return [[[self class] alloc] initWithPixels:self.luminances
  109. dataWidth:self.dataWidth
  110. dataHeight:self.dataHeight
  111. left:self.left + left
  112. top:self.top + top
  113. width:width
  114. height:height];
  115. }
  116. @end