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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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 "ZXByteArray.h"
  18. #import "ZXErrors.h"
  19. #import "ZXQRCodeBitMatrixParser.h"
  20. #import "ZXQRCodeDataMask.h"
  21. #import "ZXQRCodeFormatInformation.h"
  22. #import "ZXQRCodeVersion.h"
  23. @interface ZXQRCodeBitMatrixParser ()
  24. @property (nonatomic, strong, readonly) ZXBitMatrix *bitMatrix;
  25. @property (nonatomic, assign) BOOL shouldMirror;
  26. @property (nonatomic, strong) ZXQRCodeFormatInformation *parsedFormatInfo;
  27. @property (nonatomic, strong) ZXQRCodeVersion *parsedVersion;
  28. @end
  29. @implementation ZXQRCodeBitMatrixParser
  30. - (id)initWithBitMatrix:(ZXBitMatrix *)bitMatrix error:(NSError **)error {
  31. int dimension = bitMatrix.height;
  32. if (dimension < 21 || (dimension & 0x03) != 1) {
  33. if (error) *error = ZXFormatErrorInstance();
  34. return nil;
  35. }
  36. if (self = [super init]) {
  37. _bitMatrix = bitMatrix;
  38. _parsedFormatInfo = nil;
  39. _parsedVersion = nil;
  40. }
  41. return self;
  42. }
  43. - (ZXQRCodeFormatInformation *)readFormatInformationWithError:(NSError **)error {
  44. if (self.parsedFormatInfo != nil) {
  45. return self.parsedFormatInfo;
  46. }
  47. int formatInfoBits1 = 0;
  48. for (int i = 0; i < 6; i++) {
  49. formatInfoBits1 = [self copyBit:i j:8 versionBits:formatInfoBits1];
  50. }
  51. formatInfoBits1 = [self copyBit:7 j:8 versionBits:formatInfoBits1];
  52. formatInfoBits1 = [self copyBit:8 j:8 versionBits:formatInfoBits1];
  53. formatInfoBits1 = [self copyBit:8 j:7 versionBits:formatInfoBits1];
  54. for (int j = 5; j >= 0; j--) {
  55. formatInfoBits1 = [self copyBit:8 j:j versionBits:formatInfoBits1];
  56. }
  57. int dimension = self.bitMatrix.height;
  58. int formatInfoBits2 = 0;
  59. int jMin = dimension - 7;
  60. for (int j = dimension - 1; j >= jMin; j--) {
  61. formatInfoBits2 = [self copyBit:8 j:j versionBits:formatInfoBits2];
  62. }
  63. for (int i = dimension - 8; i < dimension; i++) {
  64. formatInfoBits2 = [self copyBit:i j:8 versionBits:formatInfoBits2];
  65. }
  66. self.parsedFormatInfo = [ZXQRCodeFormatInformation decodeFormatInformation:formatInfoBits1 maskedFormatInfo2:formatInfoBits2];
  67. if (self.parsedFormatInfo != nil) {
  68. return self.parsedFormatInfo;
  69. }
  70. if (error) *error = ZXFormatErrorInstance();
  71. return nil;
  72. }
  73. - (ZXQRCodeVersion *)readVersionWithError:(NSError **)error {
  74. if (self.parsedVersion != nil) {
  75. return self.parsedVersion;
  76. }
  77. int dimension = self.bitMatrix.height;
  78. int provisionalVersion = (dimension - 17) / 4;
  79. if (provisionalVersion <= 6) {
  80. return [ZXQRCodeVersion versionForNumber:provisionalVersion];
  81. }
  82. int versionBits = 0;
  83. int ijMin = dimension - 11;
  84. for (int j = 5; j >= 0; j--) {
  85. for (int i = dimension - 9; i >= ijMin; i--) {
  86. versionBits = [self copyBit:i j:j versionBits:versionBits];
  87. }
  88. }
  89. ZXQRCodeVersion *theParsedVersion = [ZXQRCodeVersion decodeVersionInformation:versionBits];
  90. if (theParsedVersion != nil && theParsedVersion.dimensionForVersion == dimension) {
  91. self.parsedVersion = theParsedVersion;
  92. return self.parsedVersion;
  93. }
  94. versionBits = 0;
  95. for (int i = 5; i >= 0; i--) {
  96. for (int j = dimension - 9; j >= ijMin; j--) {
  97. versionBits = [self copyBit:i j:j versionBits:versionBits];
  98. }
  99. }
  100. theParsedVersion = [ZXQRCodeVersion decodeVersionInformation:versionBits];
  101. if (theParsedVersion != nil && theParsedVersion.dimensionForVersion == dimension) {
  102. self.parsedVersion = theParsedVersion;
  103. return self.parsedVersion;
  104. }
  105. if (error) *error = ZXFormatErrorInstance();
  106. return nil;
  107. }
  108. - (int)copyBit:(int)i j:(int)j versionBits:(int)versionBits {
  109. BOOL bit = self.shouldMirror ? [self.bitMatrix getX:j y:i] : [self.bitMatrix getX:i y:j];
  110. return bit ? (versionBits << 1) | 0x1 : versionBits << 1;
  111. }
  112. - (ZXByteArray *)readCodewordsWithError:(NSError **)error {
  113. ZXQRCodeFormatInformation *formatInfo = [self readFormatInformationWithError:error];
  114. if (!formatInfo) {
  115. return nil;
  116. }
  117. ZXQRCodeVersion *version = [self readVersionWithError:error];
  118. if (!version) {
  119. return nil;
  120. }
  121. // Get the data mask for the format used in this QR Code. This will exclude
  122. // some bits from reading as we wind through the bit matrix.
  123. ZXQRCodeDataMask *dataMask = [ZXQRCodeDataMask forReference:[formatInfo dataMask]];
  124. int dimension = self.bitMatrix.height;
  125. [dataMask unmaskBitMatrix:self.bitMatrix dimension:dimension];
  126. ZXBitMatrix *functionPattern = [version buildFunctionPattern];
  127. BOOL readingUp = YES;
  128. ZXByteArray *result = [[ZXByteArray alloc] initWithLength:version.totalCodewords];
  129. int resultOffset = 0;
  130. int currentByte = 0;
  131. int bitsRead = 0;
  132. // Read columns in pairs, from right to left
  133. for (int j = dimension - 1; j > 0; j -= 2) {
  134. if (j == 6) {
  135. // Skip whole column with vertical alignment pattern;
  136. // saves time and makes the other code proceed more cleanly
  137. j--;
  138. }
  139. // Read alternatingly from bottom to top then top to bottom
  140. for (int count = 0; count < dimension; count++) {
  141. int i = readingUp ? dimension - 1 - count : count;
  142. for (int col = 0; col < 2; col++) {
  143. // Ignore bits covered by the function pattern
  144. if (![functionPattern getX:j - col y:i]) {
  145. // Read a bit
  146. bitsRead++;
  147. currentByte <<= 1;
  148. if ([self.bitMatrix getX:j - col y:i]) {
  149. currentByte |= 1;
  150. }
  151. // If we've made a whole byte, save it off
  152. if (bitsRead == 8) {
  153. result.array[resultOffset++] = (int8_t) currentByte;
  154. bitsRead = 0;
  155. currentByte = 0;
  156. }
  157. }
  158. }
  159. }
  160. readingUp ^= YES; // readingUp = !readingUp; // switch directions
  161. }
  162. if (resultOffset != [version totalCodewords]) {
  163. if (error) *error = ZXFormatErrorInstance();
  164. return nil;
  165. }
  166. return result;
  167. }
  168. - (void)remask {
  169. if (!self.parsedFormatInfo) {
  170. return; // We have no format information, and have no data mask
  171. }
  172. ZXQRCodeDataMask *dataMask = [ZXQRCodeDataMask forReference:self.parsedFormatInfo.dataMask];
  173. int dimension = self.bitMatrix.height;
  174. [dataMask unmaskBitMatrix:self.bitMatrix dimension:dimension];
  175. }
  176. - (void)setMirror:(BOOL)mirror {
  177. self.parsedVersion = nil;
  178. self.parsedFormatInfo = nil;
  179. self.shouldMirror = mirror;
  180. }
  181. - (void)mirror {
  182. for (int x = 0; x < self.bitMatrix.width; x++) {
  183. for (int y = x + 1; y < self.bitMatrix.height; y++) {
  184. if ([self.bitMatrix getX:x y:y] != [self.bitMatrix getX:y y:x]) {
  185. [self.bitMatrix flipX:y y:x];
  186. [self.bitMatrix flipX:x y:y];
  187. }
  188. }
  189. }
  190. }
  191. @end