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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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 "ZXErrors.h"
  17. #import "ZXGenericMultipleBarcodeReader.h"
  18. #import "ZXReader.h"
  19. #import "ZXResultPoint.h"
  20. const int ZX_MIN_DIMENSION_TO_RECUR = 100;
  21. const int ZX_MAX_DEPTH = 4;
  22. @interface ZXGenericMultipleBarcodeReader ()
  23. @property (nonatomic, readonly) id<ZXReader> delegate;
  24. @end
  25. @implementation ZXGenericMultipleBarcodeReader
  26. - (id)initWithDelegate:(id<ZXReader>)delegate {
  27. if (self = [super init]) {
  28. _delegate = delegate;
  29. }
  30. return self;
  31. }
  32. - (NSArray *)decodeMultiple:(ZXBinaryBitmap *)image error:(NSError **)error {
  33. return [self decodeMultiple:image hints:nil error:error];
  34. }
  35. - (NSArray *)decodeMultiple:(ZXBinaryBitmap *)image hints:(ZXDecodeHints *)hints error:(NSError **)error {
  36. NSMutableArray *results = [NSMutableArray array];
  37. [self doDecodeMultiple:image hints:hints results:results xOffset:0 yOffset:0 currentDepth:0 error:error];
  38. if (results.count == 0) {
  39. if (error) *error = ZXNotFoundErrorInstance();
  40. return nil;
  41. }
  42. return results;
  43. }
  44. - (void)doDecodeMultiple:(ZXBinaryBitmap *)image hints:(ZXDecodeHints *)hints results:(NSMutableArray *)results
  45. xOffset:(int)xOffset yOffset:(int)yOffset currentDepth:(int)currentDepth error:(NSError **)error {
  46. if (currentDepth > ZX_MAX_DEPTH) {
  47. return;
  48. }
  49. ZXResult *result = [self.delegate decode:image hints:hints error:error];
  50. if (!result) {
  51. return;
  52. }
  53. BOOL alreadyFound = NO;
  54. for (ZXResult *existingResult in results) {
  55. if ([[existingResult text] isEqualToString:[result text]]) {
  56. alreadyFound = YES;
  57. break;
  58. }
  59. }
  60. if (!alreadyFound) {
  61. [results addObject:[self translateResultPoints:result xOffset:xOffset yOffset:yOffset]];
  62. }
  63. NSMutableArray *resultPoints = [result resultPoints];
  64. if (resultPoints == nil || resultPoints.count == 0) {
  65. return;
  66. }
  67. int width = [image width];
  68. int height = [image height];
  69. float minX = width;
  70. float minY = height;
  71. float maxX = 0.0f;
  72. float maxY = 0.0f;
  73. for (ZXResultPoint *point in resultPoints) {
  74. if ((id)point == [NSNull null]) {
  75. continue;
  76. }
  77. float x = [point x];
  78. float y = [point y];
  79. if (x < minX) {
  80. minX = x;
  81. }
  82. if (y < minY) {
  83. minY = y;
  84. }
  85. if (x > maxX) {
  86. maxX = x;
  87. }
  88. if (y > maxY) {
  89. maxY = y;
  90. }
  91. }
  92. if (minX > ZX_MIN_DIMENSION_TO_RECUR) {
  93. [self doDecodeMultiple:[image crop:0 top:0 width:(int)minX height:height] hints:hints results:results xOffset:xOffset yOffset:yOffset currentDepth:currentDepth + 1 error:error];
  94. }
  95. if (minY > ZX_MIN_DIMENSION_TO_RECUR) {
  96. [self doDecodeMultiple:[image crop:0 top:0 width:width height:(int)minY] hints:hints results:results xOffset:xOffset yOffset:yOffset currentDepth:currentDepth + 1 error:error];
  97. }
  98. if (maxX < width - ZX_MIN_DIMENSION_TO_RECUR) {
  99. [self doDecodeMultiple:[image crop:(int)maxX top:0 width:width - (int)maxX height:height] hints:hints results:results xOffset:xOffset + (int)maxX yOffset:yOffset currentDepth:currentDepth + 1 error:error];
  100. }
  101. if (maxY < height - ZX_MIN_DIMENSION_TO_RECUR) {
  102. [self doDecodeMultiple:[image crop:0 top:(int)maxY width:width height:height - (int)maxY] hints:hints results:results xOffset:xOffset yOffset:yOffset + (int)maxY currentDepth:currentDepth + 1 error:error];
  103. }
  104. }
  105. - (ZXResult *)translateResultPoints:(ZXResult *)result xOffset:(int)xOffset yOffset:(int)yOffset {
  106. NSArray *oldResultPoints = [result resultPoints];
  107. if (oldResultPoints == nil) {
  108. return result;
  109. }
  110. NSMutableArray *newResultPoints = [NSMutableArray arrayWithCapacity:[oldResultPoints count]];
  111. for (ZXResultPoint *oldPoint in oldResultPoints) {
  112. if ((id)oldPoint != [NSNull null]) {
  113. [newResultPoints addObject:[[ZXResultPoint alloc] initWithX:[oldPoint x] + xOffset y:[oldPoint y] + yOffset]];
  114. }
  115. }
  116. ZXResult *newResult = [ZXResult resultWithText:result.text rawBytes:result.rawBytes resultPoints:newResultPoints format:result.barcodeFormat];
  117. [newResult putAllMetadata:result.resultMetadata];
  118. return newResult;
  119. }
  120. @end