Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

ZXQRCodeDecoder.m 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  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 "ZXBitMatrix.h"
  17. #import "ZXBoolArray.h"
  18. #import "ZXByteArray.h"
  19. #import "ZXDecoderResult.h"
  20. #import "ZXErrors.h"
  21. #import "ZXGenericGF.h"
  22. #import "ZXIntArray.h"
  23. #import "ZXQRCodeBitMatrixParser.h"
  24. #import "ZXQRCodeDataBlock.h"
  25. #import "ZXQRCodeDecodedBitStreamParser.h"
  26. #import "ZXQRCodeDecoder.h"
  27. #import "ZXQRCodeDecoderMetaData.h"
  28. #import "ZXQRCodeErrorCorrectionLevel.h"
  29. #import "ZXQRCodeFormatInformation.h"
  30. #import "ZXQRCodeVersion.h"
  31. #import "ZXReedSolomonDecoder.h"
  32. @interface ZXQRCodeDecoder ()
  33. @property (nonatomic, strong, readonly) ZXReedSolomonDecoder *rsDecoder;
  34. @end
  35. @implementation ZXQRCodeDecoder
  36. - (id)init {
  37. if (self = [super init]) {
  38. _rsDecoder = [[ZXReedSolomonDecoder alloc] initWithField:[ZXGenericGF QrCodeField256]];
  39. }
  40. return self;
  41. }
  42. - (ZXDecoderResult *)decode:(NSArray *)image error:(NSError **)error {
  43. return [self decode:image hints:nil error:error];
  44. }
  45. - (ZXDecoderResult *)decode:(NSArray *)image hints:(ZXDecodeHints *)hints error:(NSError **)error {
  46. int dimension = (int)[image count];
  47. ZXBitMatrix *bits = [[ZXBitMatrix alloc] initWithDimension:dimension];
  48. for (int i = 0; i < dimension; i++) {
  49. ZXBoolArray *b = image[i];
  50. for (int j = 0; j < dimension; j++) {
  51. if (b.array[j]) {
  52. [bits setX:j y:i];
  53. }
  54. }
  55. }
  56. return [self decodeMatrix:bits hints:hints error:error];
  57. }
  58. - (ZXDecoderResult *)decodeMatrix:(ZXBitMatrix *)bits error:(NSError **)error {
  59. return [self decodeMatrix:bits hints:nil error:error];
  60. }
  61. - (ZXDecoderResult *)decodeMatrix:(ZXBitMatrix *)bits hints:(ZXDecodeHints *)hints error:(NSError **)error {
  62. ZXQRCodeBitMatrixParser *parser = [[ZXQRCodeBitMatrixParser alloc] initWithBitMatrix:bits error:error];
  63. if (!parser) {
  64. return nil;
  65. }
  66. ZXDecoderResult *result = [self decodeParser:parser hints:hints error:error];
  67. if (result) {
  68. return result;
  69. }
  70. // Revert the bit matrix
  71. [parser remask];
  72. // Will be attempting a mirrored reading of the version and format info.
  73. [parser setMirror:YES];
  74. // Preemptively read the version.
  75. if (![parser readVersionWithError:error]) {
  76. return nil;
  77. }
  78. /*
  79. * Since we're here, this means we have successfully detected some kind
  80. * of version and format information when mirrored. This is a good sign,
  81. * that the QR code may be mirrored, and we should try once more with a
  82. * mirrored content.
  83. */
  84. // Prepare for a mirrored reading.
  85. [parser mirror];
  86. result = [self decodeParser:parser hints:hints error:error];
  87. if (!result) {
  88. return nil;
  89. }
  90. // Success! Notify the caller that the code was mirrored.
  91. result.other = [[ZXQRCodeDecoderMetaData alloc] initWithMirrored:YES];
  92. return result;
  93. }
  94. - (ZXDecoderResult *)decodeParser:(ZXQRCodeBitMatrixParser *)parser hints:(ZXDecodeHints *)hints error:(NSError **)error {
  95. ZXQRCodeVersion *version = [parser readVersionWithError:error];
  96. if (!version) {
  97. return nil;
  98. }
  99. ZXQRCodeFormatInformation *formatInfo = [parser readFormatInformationWithError:error];
  100. if (!formatInfo) {
  101. return nil;
  102. }
  103. ZXQRCodeErrorCorrectionLevel *ecLevel = formatInfo.errorCorrectionLevel;
  104. ZXByteArray *codewords = [parser readCodewordsWithError:error];
  105. if (!codewords) {
  106. return nil;
  107. }
  108. NSArray *dataBlocks = [ZXQRCodeDataBlock dataBlocks:codewords version:version ecLevel:ecLevel];
  109. int totalBytes = 0;
  110. for (ZXQRCodeDataBlock *dataBlock in dataBlocks) {
  111. totalBytes += dataBlock.numDataCodewords;
  112. }
  113. if (totalBytes == 0) {
  114. return nil;
  115. }
  116. ZXByteArray *resultBytes = [[ZXByteArray alloc] initWithLength:totalBytes];
  117. int resultOffset = 0;
  118. for (ZXQRCodeDataBlock *dataBlock in dataBlocks) {
  119. ZXByteArray *codewordBytes = dataBlock.codewords;
  120. int numDataCodewords = [dataBlock numDataCodewords];
  121. if (![self correctErrors:codewordBytes numDataCodewords:numDataCodewords error:error]) {
  122. return nil;
  123. }
  124. for (int i = 0; i < numDataCodewords; i++) {
  125. resultBytes.array[resultOffset++] = codewordBytes.array[i];
  126. }
  127. }
  128. return [ZXQRCodeDecodedBitStreamParser decode:resultBytes version:version ecLevel:ecLevel hints:hints error:error];
  129. }
  130. /**
  131. * Given data and error-correction codewords received, possibly corrupted by errors, attempts to
  132. * correct the errors in-place using Reed-Solomon error correction.
  133. *
  134. * @param codewordBytes data and error correction codewords
  135. * @param numDataCodewords number of codewords that are data bytes
  136. * @return NO if error correction fails
  137. */
  138. - (BOOL)correctErrors:(ZXByteArray *)codewordBytes numDataCodewords:(int)numDataCodewords error:(NSError **)error {
  139. int numCodewords = (int)codewordBytes.length;
  140. // First read into an array of ints
  141. ZXIntArray *codewordsInts = [[ZXIntArray alloc] initWithLength:numCodewords];
  142. for (int i = 0; i < numCodewords; i++) {
  143. codewordsInts.array[i] = codewordBytes.array[i] & 0xFF;
  144. }
  145. int numECCodewords = (int)codewordBytes.length - numDataCodewords;
  146. NSError *decodeError = nil;
  147. if (![self.rsDecoder decode:codewordsInts twoS:numECCodewords error:&decodeError]) {
  148. if (decodeError.code == ZXReedSolomonError) {
  149. if (error) *error = ZXChecksumErrorInstance();
  150. return NO;
  151. } else {
  152. if (error) *error = decodeError;
  153. return NO;
  154. }
  155. }
  156. // Copy back into array of bytes -- only need to worry about the bytes that were data
  157. // We don't care about errors in the error-correction codewords
  158. for (int i = 0; i < numDataCodewords; i++) {
  159. codewordBytes.array[i] = (int8_t) codewordsInts.array[i];
  160. }
  161. return YES;
  162. }
  163. @end