Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 "ZXBinaryBitmap.h"
  17. #import "ZXBitMatrix.h"
  18. #import "ZXDataMatrixDecoder.h"
  19. #import "ZXDataMatrixDetector.h"
  20. #import "ZXDataMatrixReader.h"
  21. #import "ZXDecodeHints.h"
  22. #import "ZXDecoderResult.h"
  23. #import "ZXDetectorResult.h"
  24. #import "ZXErrors.h"
  25. #import "ZXIntArray.h"
  26. #import "ZXResult.h"
  27. @interface ZXDataMatrixReader ()
  28. @property (nonatomic, strong, readonly) ZXDataMatrixDecoder *decoder;
  29. @end
  30. @implementation ZXDataMatrixReader
  31. - (id)init {
  32. if (self = [super init]) {
  33. _decoder = [[ZXDataMatrixDecoder alloc] init];
  34. }
  35. return self;
  36. }
  37. /**
  38. * Locates and decodes a Data Matrix code in an image.
  39. *
  40. * @return a String representing the content encoded by the Data Matrix code
  41. */
  42. - (ZXResult *)decode:(ZXBinaryBitmap *)image error:(NSError **)error {
  43. return [self decode:image hints:nil error:error];
  44. }
  45. - (ZXResult *)decode:(ZXBinaryBitmap *)image hints:(ZXDecodeHints *)hints error:(NSError **)error {
  46. ZXDecoderResult *decoderResult;
  47. NSArray *points;
  48. if (hints != nil && hints.pureBarcode) {
  49. ZXBitMatrix *matrix = [image blackMatrixWithError:error];
  50. if (!matrix) {
  51. return nil;
  52. }
  53. ZXBitMatrix *bits = [self extractPureBits:matrix];
  54. if (!bits) {
  55. if (error) *error = ZXNotFoundErrorInstance();
  56. return nil;
  57. }
  58. decoderResult = [self.decoder decodeMatrix:bits error:error];
  59. if (!decoderResult) {
  60. return nil;
  61. }
  62. points = @[];
  63. } else {
  64. ZXBitMatrix *matrix = [image blackMatrixWithError:error];
  65. if (!matrix) {
  66. return nil;
  67. }
  68. ZXDataMatrixDetector *detector = [[ZXDataMatrixDetector alloc] initWithImage:matrix error:error];
  69. if (!detector) {
  70. return nil;
  71. }
  72. ZXDetectorResult *detectorResult = [detector detectWithError:error];
  73. if (!detectorResult) {
  74. return nil;
  75. }
  76. decoderResult = [self.decoder decodeMatrix:detectorResult.bits error:error];
  77. if (!decoderResult) {
  78. return nil;
  79. }
  80. points = detectorResult.points;
  81. }
  82. ZXResult *result = [ZXResult resultWithText:decoderResult.text
  83. rawBytes:decoderResult.rawBytes
  84. resultPoints:points
  85. format:kBarcodeFormatDataMatrix];
  86. if (decoderResult.byteSegments != nil) {
  87. [result putMetadata:kResultMetadataTypeByteSegments value:decoderResult.byteSegments];
  88. }
  89. if (decoderResult.ecLevel != nil) {
  90. [result putMetadata:kResultMetadataTypeErrorCorrectionLevel value:decoderResult.ecLevel];
  91. }
  92. return result;
  93. }
  94. - (void)reset {
  95. // do nothing
  96. }
  97. /**
  98. * This method detects a code in a "pure" image -- that is, pure monochrome image
  99. * which contains only an unrotated, unskewed, image of a code, with some white border
  100. * around it. This is a specialized method that works exceptionally fast in this special
  101. * case.
  102. */
  103. - (ZXBitMatrix *)extractPureBits:(ZXBitMatrix *)image {
  104. ZXIntArray *leftTopBlack = image.topLeftOnBit;
  105. ZXIntArray *rightBottomBlack = image.bottomRightOnBit;
  106. if (leftTopBlack == nil || rightBottomBlack == nil) {
  107. return nil;
  108. }
  109. int moduleSize = [self moduleSize:leftTopBlack image:image];
  110. if (moduleSize == -1) {
  111. return nil;
  112. }
  113. int top = leftTopBlack.array[1];
  114. int bottom = rightBottomBlack.array[1];
  115. int left = leftTopBlack.array[0];
  116. int right = rightBottomBlack.array[0];
  117. int matrixWidth = (right - left + 1) / moduleSize;
  118. int matrixHeight = (bottom - top + 1) / moduleSize;
  119. if (matrixWidth <= 0 || matrixHeight <= 0) {
  120. return nil;
  121. }
  122. int nudge = moduleSize / 2;
  123. top += nudge;
  124. left += nudge;
  125. ZXBitMatrix *bits = [[ZXBitMatrix alloc] initWithWidth:matrixWidth height:matrixHeight];
  126. for (int y = 0; y < matrixHeight; y++) {
  127. int iOffset = top + y * moduleSize;
  128. for (int x = 0; x < matrixWidth; x++) {
  129. if ([image getX:left + x * moduleSize y:iOffset]) {
  130. [bits setX:x y:y];
  131. }
  132. }
  133. }
  134. return bits;
  135. }
  136. - (int)moduleSize:(ZXIntArray *)leftTopBlack image:(ZXBitMatrix *)image {
  137. int width = image.width;
  138. int x = leftTopBlack.array[0];
  139. int y = leftTopBlack.array[1];
  140. while (x < width && [image getX:x y:y]) {
  141. x++;
  142. }
  143. if (x == width) {
  144. return -1;
  145. }
  146. int moduleSize = x - leftTopBlack.array[0];
  147. if (moduleSize == 0) {
  148. return -1;
  149. }
  150. return moduleSize;
  151. }
  152. @end