Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

ZXQRCodeMatrixUtil.m 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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 "ZXBitArray.h"
  17. #import "ZXByteMatrix.h"
  18. #import "ZXErrors.h"
  19. #import "ZXQRCode.h"
  20. #import "ZXQRCodeErrorCorrectionLevel.h"
  21. #import "ZXQRCodeMaskUtil.h"
  22. #import "ZXQRCodeMatrixUtil.h"
  23. #import "ZXQRCodeVersion.h"
  24. const int ZX_POSITION_DETECTION_PATTERN[][7] = {
  25. {1, 1, 1, 1, 1, 1, 1},
  26. {1, 0, 0, 0, 0, 0, 1},
  27. {1, 0, 1, 1, 1, 0, 1},
  28. {1, 0, 1, 1, 1, 0, 1},
  29. {1, 0, 1, 1, 1, 0, 1},
  30. {1, 0, 0, 0, 0, 0, 1},
  31. {1, 1, 1, 1, 1, 1, 1},
  32. };
  33. const int ZX_POSITION_ADJUSTMENT_PATTERN[][5] = {
  34. {1, 1, 1, 1, 1},
  35. {1, 0, 0, 0, 1},
  36. {1, 0, 1, 0, 1},
  37. {1, 0, 0, 0, 1},
  38. {1, 1, 1, 1, 1},
  39. };
  40. // From Appendix E. Table 1, JIS0510X:2004 (p 71). The table was double-checked by komatsu.
  41. const int ZX_POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[][7] = {
  42. {-1, -1, -1, -1, -1, -1, -1}, // Version 1
  43. { 6, 18, -1, -1, -1, -1, -1}, // Version 2
  44. { 6, 22, -1, -1, -1, -1, -1}, // Version 3
  45. { 6, 26, -1, -1, -1, -1, -1}, // Version 4
  46. { 6, 30, -1, -1, -1, -1, -1}, // Version 5
  47. { 6, 34, -1, -1, -1, -1, -1}, // Version 6
  48. { 6, 22, 38, -1, -1, -1, -1}, // Version 7
  49. { 6, 24, 42, -1, -1, -1, -1}, // Version 8
  50. { 6, 26, 46, -1, -1, -1, -1}, // Version 9
  51. { 6, 28, 50, -1, -1, -1, -1}, // Version 10
  52. { 6, 30, 54, -1, -1, -1, -1}, // Version 11
  53. { 6, 32, 58, -1, -1, -1, -1}, // Version 12
  54. { 6, 34, 62, -1, -1, -1, -1}, // Version 13
  55. { 6, 26, 46, 66, -1, -1, -1}, // Version 14
  56. { 6, 26, 48, 70, -1, -1, -1}, // Version 15
  57. { 6, 26, 50, 74, -1, -1, -1}, // Version 16
  58. { 6, 30, 54, 78, -1, -1, -1}, // Version 17
  59. { 6, 30, 56, 82, -1, -1, -1}, // Version 18
  60. { 6, 30, 58, 86, -1, -1, -1}, // Version 19
  61. { 6, 34, 62, 90, -1, -1, -1}, // Version 20
  62. { 6, 28, 50, 72, 94, -1, -1}, // Version 21
  63. { 6, 26, 50, 74, 98, -1, -1}, // Version 22
  64. { 6, 30, 54, 78, 102, -1, -1}, // Version 23
  65. { 6, 28, 54, 80, 106, -1, -1}, // Version 24
  66. { 6, 32, 58, 84, 110, -1, -1}, // Version 25
  67. { 6, 30, 58, 86, 114, -1, -1}, // Version 26
  68. { 6, 34, 62, 90, 118, -1, -1}, // Version 27
  69. { 6, 26, 50, 74, 98, 122, -1}, // Version 28
  70. { 6, 30, 54, 78, 102, 126, -1}, // Version 29
  71. { 6, 26, 52, 78, 104, 130, -1}, // Version 30
  72. { 6, 30, 56, 82, 108, 134, -1}, // Version 31
  73. { 6, 34, 60, 86, 112, 138, -1}, // Version 32
  74. { 6, 30, 58, 86, 114, 142, -1}, // Version 33
  75. { 6, 34, 62, 90, 118, 146, -1}, // Version 34
  76. { 6, 30, 54, 78, 102, 126, 150}, // Version 35
  77. { 6, 24, 50, 76, 102, 128, 154}, // Version 36
  78. { 6, 28, 54, 80, 106, 132, 158}, // Version 37
  79. { 6, 32, 58, 84, 110, 136, 162}, // Version 38
  80. { 6, 26, 54, 82, 110, 138, 166}, // Version 39
  81. { 6, 30, 58, 86, 114, 142, 170}, // Version 40
  82. };
  83. // Type info cells at the left top corner.
  84. const int ZX_TYPE_INFO_COORDINATES[][2] = {
  85. {8, 0},
  86. {8, 1},
  87. {8, 2},
  88. {8, 3},
  89. {8, 4},
  90. {8, 5},
  91. {8, 7},
  92. {8, 8},
  93. {7, 8},
  94. {5, 8},
  95. {4, 8},
  96. {3, 8},
  97. {2, 8},
  98. {1, 8},
  99. {0, 8},
  100. };
  101. // From Appendix D in JISX0510:2004 (p. 67)
  102. const int ZX_VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101
  103. // From Appendix C in JISX0510:2004 (p.65).
  104. const int ZX_TYPE_INFO_POLY = 0x537;
  105. const int ZX_TYPE_INFO_MASK_PATTERN = 0x5412;
  106. @implementation ZXQRCodeMatrixUtil
  107. + (void)clearMatrix:(ZXByteMatrix *)matrix {
  108. [matrix clear:-1];
  109. }
  110. + (BOOL)buildMatrix:(ZXBitArray *)dataBits ecLevel:(ZXQRCodeErrorCorrectionLevel *)ecLevel version:(ZXQRCodeVersion *)version maskPattern:(int)maskPattern matrix:(ZXByteMatrix *)matrix error:(NSError **)error {
  111. [self clearMatrix:matrix];
  112. if (![self embedBasicPatterns:version matrix:matrix error:error]) {
  113. return NO;
  114. }
  115. // Type information appear with any version.
  116. if (![self embedTypeInfo:ecLevel maskPattern:maskPattern matrix:matrix error:error]) {
  117. return NO;
  118. }
  119. // Version info appear if version >= 7.
  120. if (![self maybeEmbedVersionInfo:version matrix:matrix error:error]) {
  121. return NO;
  122. }
  123. // Data should be embedded at end.
  124. if (![self embedDataBits:dataBits maskPattern:maskPattern matrix:matrix error:error]) {
  125. return NO;
  126. }
  127. return YES;
  128. }
  129. + (BOOL)embedBasicPatterns:(ZXQRCodeVersion *)version matrix:(ZXByteMatrix *)matrix error:(NSError **)error {
  130. // Let's get started with embedding big squares at corners.
  131. if (![self embedPositionDetectionPatternsAndSeparators:matrix]) {
  132. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXNotFoundError userInfo:nil];
  133. return NO;
  134. }
  135. // Then, embed the dark dot at the left bottom corner.
  136. if (![self embedDarkDotAtLeftBottomCorner:matrix]) {
  137. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXNotFoundError userInfo:nil];
  138. return NO;
  139. }
  140. // Position adjustment patterns appear if version >= 2.
  141. [self maybeEmbedPositionAdjustmentPatterns:version matrix:matrix];
  142. // Timing patterns should be embedded after position adj. patterns.
  143. [self embedTimingPatterns:matrix];
  144. return YES;
  145. }
  146. + (BOOL)embedTypeInfo:(ZXQRCodeErrorCorrectionLevel *)ecLevel maskPattern:(int)maskPattern matrix:(ZXByteMatrix *)matrix error:(NSError **)error {
  147. ZXBitArray *typeInfoBits = [[ZXBitArray alloc] init];
  148. if (![self makeTypeInfoBits:ecLevel maskPattern:maskPattern bits:typeInfoBits error:error]) {
  149. return NO;
  150. }
  151. for (int i = 0; i < [typeInfoBits size]; ++i) {
  152. // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in
  153. // "typeInfoBits".
  154. BOOL bit = [typeInfoBits get:[typeInfoBits size] - 1 - i];
  155. // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46).
  156. int x1 = ZX_TYPE_INFO_COORDINATES[i][0];
  157. int y1 = ZX_TYPE_INFO_COORDINATES[i][1];
  158. [matrix setX:x1 y:y1 boolValue:bit];
  159. if (i < 8) {
  160. // Right top corner.
  161. int x2 = [matrix width] - i - 1;
  162. int y2 = 8;
  163. [matrix setX:x2 y:y2 boolValue:bit];
  164. } else {
  165. // Left bottom corner.
  166. int x2 = 8;
  167. int y2 = [matrix height] - 7 + (i - 8);
  168. [matrix setX:x2 y:y2 boolValue:bit];
  169. }
  170. }
  171. return YES;
  172. }
  173. + (BOOL)maybeEmbedVersionInfo:(ZXQRCodeVersion *)version matrix:(ZXByteMatrix *)matrix error:(NSError **)error {
  174. if (version.versionNumber < 7) { // Version info is necessary if version >= 7.
  175. return YES; // Don't need version info.
  176. }
  177. ZXBitArray *versionInfoBits = [[ZXBitArray alloc] init];
  178. if (![self makeVersionInfoBits:version bits:versionInfoBits error:error]) {
  179. return NO;
  180. }
  181. int bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0.
  182. for (int i = 0; i < 6; ++i) {
  183. for (int j = 0; j < 3; ++j) {
  184. // Place bits in LSB (least significant bit) to MSB order.
  185. BOOL bit = [versionInfoBits get:bitIndex];
  186. bitIndex--;
  187. // Left bottom corner.
  188. [matrix setX:i y:[matrix height] - 11 + j boolValue:bit];
  189. // Right bottom corner.
  190. [matrix setX:[matrix height] - 11 + j y:i boolValue:bit];
  191. }
  192. }
  193. return YES;
  194. }
  195. + (BOOL)embedDataBits:(ZXBitArray *)dataBits maskPattern:(int)maskPattern matrix:(ZXByteMatrix *)matrix error:(NSError **)error {
  196. int bitIndex = 0;
  197. int direction = -1;
  198. // Start from the right bottom cell.
  199. int x = [matrix width] - 1;
  200. int y = [matrix height] - 1;
  201. while (x > 0) {
  202. // Skip the vertical timing pattern.
  203. if (x == 6) {
  204. x -= 1;
  205. }
  206. while (y >= 0 && y < [matrix height]) {
  207. for (int i = 0; i < 2; ++i) {
  208. int xx = x - i;
  209. // Skip the cell if it's not empty.
  210. if (![self isEmpty:[matrix getX:xx y:y]]) {
  211. continue;
  212. }
  213. BOOL bit;
  214. if (bitIndex < [dataBits size]) {
  215. bit = [dataBits get:bitIndex];
  216. ++bitIndex;
  217. } else {
  218. // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described
  219. // in 8.4.9 of JISX0510:2004 (p. 24).
  220. bit = NO;
  221. }
  222. // Skip masking if mask_pattern is -1.
  223. if (maskPattern != -1 && [ZXQRCodeMaskUtil dataMaskBit:maskPattern x:xx y:y]) {
  224. bit = !bit;
  225. }
  226. [matrix setX:xx y:y boolValue:bit];
  227. }
  228. y += direction;
  229. }
  230. direction = -direction; // Reverse the direction.
  231. y += direction;
  232. x -= 2; // Move to the left.
  233. }
  234. // All bits should be consumed.
  235. if (bitIndex != [dataBits size]) {
  236. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Not all bits consumed: %d/%d", bitIndex, [dataBits size]]};
  237. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXNotFoundError userInfo:userInfo];
  238. return NO;
  239. }
  240. return YES;
  241. }
  242. + (int)findMSBSet:(int)value {
  243. int numDigits = 0;
  244. while (value != 0) {
  245. value = (int)((unsigned int)value >> 1);
  246. ++numDigits;
  247. }
  248. return numDigits;
  249. }
  250. + (int)calculateBCHCode:(int)value poly:(int)poly {
  251. // If poly is "1 1111 0010 0101" (version info poly), msbSetInPoly is 13. We'll subtract 1
  252. // from 13 to make it 12.
  253. int msbSetInPoly = [self findMSBSet:poly];
  254. value <<= msbSetInPoly - 1;
  255. // Do the division business using exclusive-or operations.
  256. while ([self findMSBSet:value] >= msbSetInPoly) {
  257. value ^= poly << ([self findMSBSet:value] - msbSetInPoly);
  258. }
  259. // Now the "value" is the remainder (i.e. the BCH code)
  260. return value;
  261. }
  262. + (BOOL)makeTypeInfoBits:(ZXQRCodeErrorCorrectionLevel *)ecLevel maskPattern:(int)maskPattern bits:(ZXBitArray *)bits error:(NSError **)error {
  263. if (![ZXQRCode isValidMaskPattern:maskPattern]) {
  264. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Invalid mask pattern"};
  265. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXNotFoundError userInfo:userInfo];
  266. return NO;
  267. }
  268. int typeInfo = ([ecLevel bits] << 3) | maskPattern;
  269. [bits appendBits:typeInfo numBits:5];
  270. int bchCode = [self calculateBCHCode:typeInfo poly:ZX_TYPE_INFO_POLY];
  271. [bits appendBits:bchCode numBits:10];
  272. ZXBitArray *maskBits = [[ZXBitArray alloc] init];
  273. [maskBits appendBits:ZX_TYPE_INFO_MASK_PATTERN numBits:15];
  274. [bits xor:maskBits];
  275. if ([bits size] != 15) { // Just in case.
  276. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"should not happen but we got: %d", [bits size]]};
  277. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXNotFoundError userInfo:userInfo];
  278. return NO;
  279. }
  280. return YES;
  281. }
  282. + (BOOL)makeVersionInfoBits:(ZXQRCodeVersion *)version bits:(ZXBitArray *)bits error:(NSError **)error {
  283. [bits appendBits:version.versionNumber numBits:6];
  284. int bchCode = [self calculateBCHCode:version.versionNumber poly:ZX_VERSION_INFO_POLY];
  285. [bits appendBits:bchCode numBits:12];
  286. if ([bits size] != 18) { // Just in case.
  287. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"should not happen but we got: %d", [bits size]]};
  288. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXNotFoundError userInfo:userInfo];
  289. return NO;
  290. }
  291. return YES;
  292. }
  293. // Check if "value" is empty.
  294. + (BOOL)isEmpty:(int)value {
  295. return value == -1;
  296. }
  297. + (void)embedTimingPatterns:(ZXByteMatrix *)matrix {
  298. // -8 is for skipping position detection patterns (size 7), and two horizontal/vertical
  299. // separation patterns (size 1). Thus, 8 = 7 + 1.
  300. for (int i = 8; i < [matrix width] - 8; ++i) {
  301. int bit = (i + 1) % 2;
  302. // Horizontal line.
  303. if ([self isEmpty:[matrix getX:i y:6]]) {
  304. [matrix setX:i y:6 boolValue:bit];
  305. }
  306. // Vertical line.
  307. if ([self isEmpty:[matrix getX:6 y:i]]) {
  308. [matrix setX:6 y:i boolValue:bit];
  309. }
  310. }
  311. }
  312. // Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46)
  313. + (BOOL)embedDarkDotAtLeftBottomCorner:(ZXByteMatrix *)matrix {
  314. if ([matrix getX:8 y:matrix.height - 8] == 0) {
  315. return NO;
  316. }
  317. [matrix setX:8 y:matrix.height - 8 intValue:1];
  318. return YES;
  319. }
  320. + (BOOL)embedHorizontalSeparationPattern:(int)xStart yStart:(int)yStart matrix:(ZXByteMatrix *)matrix {
  321. for (int x = 0; x < 8; ++x) {
  322. if (![self isEmpty:[matrix getX:xStart + x y:yStart]]) {
  323. return NO;
  324. }
  325. [matrix setX:xStart + x y:yStart intValue:0];
  326. }
  327. return YES;
  328. }
  329. + (BOOL)embedVerticalSeparationPattern:(int)xStart yStart:(int)yStart matrix:(ZXByteMatrix *)matrix {
  330. for (int y = 0; y < 7; ++y) {
  331. if (![self isEmpty:[matrix getX:xStart y:yStart + y]]) {
  332. return NO;
  333. }
  334. [matrix setX:xStart y:yStart + y intValue:0];
  335. }
  336. return YES;
  337. }
  338. // Note that we cannot unify the function with embedPositionDetectionPattern() despite they are
  339. // almost identical, since we cannot write a function that takes 2D arrays in different sizes in
  340. // C/C++. We should live with the fact.
  341. + (void)embedPositionAdjustmentPattern:(int)xStart yStart:(int)yStart matrix:(ZXByteMatrix *)matrix {
  342. for (int y = 0; y < 5; ++y) {
  343. for (int x = 0; x < 5; ++x) {
  344. [matrix setX:xStart + x y:yStart + y intValue:ZX_POSITION_ADJUSTMENT_PATTERN[y][x]];
  345. }
  346. }
  347. }
  348. + (void)embedPositionDetectionPattern:(int)xStart yStart:(int)yStart matrix:(ZXByteMatrix *)matrix {
  349. for (int y = 0; y < 7; ++y) {
  350. for (int x = 0; x < 7; ++x) {
  351. [matrix setX:xStart + x y:yStart + y intValue:ZX_POSITION_DETECTION_PATTERN[y][x]];
  352. }
  353. }
  354. }
  355. // Embed position detection patterns and surrounding vertical/horizontal separators.
  356. + (BOOL)embedPositionDetectionPatternsAndSeparators:(ZXByteMatrix *)matrix {
  357. // Embed three big squares at corners.
  358. int pdpWidth = sizeof(ZX_POSITION_DETECTION_PATTERN[0]) / sizeof(int);
  359. // Left top corner.
  360. [self embedPositionDetectionPattern:0 yStart:0 matrix:matrix];
  361. // Right top corner.
  362. [self embedPositionDetectionPattern:[matrix width] - pdpWidth yStart:0 matrix:matrix];
  363. // Left bottom corner.
  364. [self embedPositionDetectionPattern:0 yStart:[matrix width] - pdpWidth matrix:matrix];
  365. // Embed horizontal separation patterns around the squares.
  366. int hspWidth = 8;
  367. // Left top corner.
  368. [self embedHorizontalSeparationPattern:0 yStart:hspWidth - 1 matrix:matrix];
  369. // Right top corner.
  370. [self embedHorizontalSeparationPattern:[matrix width] - hspWidth yStart:hspWidth - 1 matrix:matrix];
  371. // Left bottom corner.
  372. [self embedHorizontalSeparationPattern:0 yStart:[matrix width] - hspWidth matrix:matrix];
  373. // Embed vertical separation patterns around the squares.
  374. int vspSize = 7;
  375. // Left top corner.
  376. if (![self embedVerticalSeparationPattern:vspSize yStart:0 matrix:matrix]) {
  377. return NO;
  378. }
  379. // Right top corner.
  380. if (![self embedVerticalSeparationPattern:[matrix height] - vspSize - 1 yStart:0 matrix:matrix]) {
  381. return NO;
  382. }
  383. // Left bottom corner.
  384. if (![self embedVerticalSeparationPattern:vspSize yStart:[matrix height] - vspSize matrix:matrix]) {
  385. return NO;
  386. }
  387. return YES;
  388. }
  389. // Embed position adjustment patterns if need be.
  390. + (void)maybeEmbedPositionAdjustmentPatterns:(ZXQRCodeVersion *)version matrix:(ZXByteMatrix *)matrix {
  391. if (version.versionNumber < 2) { // The patterns appear if version >= 2
  392. return;
  393. }
  394. int index = version.versionNumber - 1;
  395. int numCoordinates = sizeof(ZX_POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index]) / sizeof(int);
  396. for (int i = 0; i < numCoordinates; ++i) {
  397. for (int j = 0; j < numCoordinates; ++j) {
  398. int y = ZX_POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index][i];
  399. int x = ZX_POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index][j];
  400. if (x == -1 || y == -1) {
  401. continue;
  402. }
  403. // If the cell is unset, we embed the position adjustment pattern here.
  404. if ([self isEmpty:[matrix getX:x y:y]]) {
  405. // -2 is necessary since the x/y coordinates point to the center of the pattern, not the
  406. // left top corner.
  407. [self embedPositionAdjustmentPattern:x - 2 yStart:y - 2 matrix:matrix];
  408. }
  409. }
  410. }
  411. }
  412. @end