Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

ZXQRCodeEncoder.m 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  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 "ZXByteArray.h"
  18. #import "ZXByteMatrix.h"
  19. #import "ZXCharacterSetECI.h"
  20. #import "ZXEncodeHints.h"
  21. #import "ZXErrors.h"
  22. #import "ZXGenericGF.h"
  23. #import "ZXIntArray.h"
  24. #import "ZXQRCode.h"
  25. #import "ZXQRCodeBlockPair.h"
  26. #import "ZXQRCodeEncoder.h"
  27. #import "ZXQRCodeErrorCorrectionLevel.h"
  28. #import "ZXQRCodeMaskUtil.h"
  29. #import "ZXQRCodeMatrixUtil.h"
  30. #import "ZXQRCodeMode.h"
  31. #import "ZXQRCodeVersion.h"
  32. #import "ZXReedSolomonEncoder.h"
  33. // The original table is defined in the table 5 of JISX0510:2004 (p.19).
  34. const int ZX_ALPHANUMERIC_TABLE[] = {
  35. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x0f
  36. -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f
  37. 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f
  38. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // 0x30-0x3f
  39. -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f
  40. 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f
  41. };
  42. const NSStringEncoding ZX_DEFAULT_BYTE_MODE_ENCODING = NSISOLatin1StringEncoding;
  43. @implementation ZXQRCodeEncoder
  44. // The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details.
  45. // Basically it applies four rules and summate all penalties.
  46. + (int)calculateMaskPenalty:(ZXByteMatrix *)matrix {
  47. return [ZXQRCodeMaskUtil applyMaskPenaltyRule1:matrix]
  48. + [ZXQRCodeMaskUtil applyMaskPenaltyRule2:matrix]
  49. + [ZXQRCodeMaskUtil applyMaskPenaltyRule3:matrix]
  50. + [ZXQRCodeMaskUtil applyMaskPenaltyRule4:matrix];
  51. }
  52. + (ZXQRCode *)encode:(NSString *)content ecLevel:(ZXQRCodeErrorCorrectionLevel *)ecLevel error:(NSError **)error {
  53. return [self encode:content ecLevel:ecLevel hints:nil error:error];
  54. }
  55. + (ZXQRCode *)encode:(NSString *)content ecLevel:(ZXQRCodeErrorCorrectionLevel *)ecLevel hints:(ZXEncodeHints *)hints error:(NSError **)error {
  56. // Determine what character encoding has been specified by the caller, if any
  57. NSStringEncoding encoding = hints == nil ? 0 : hints.encoding;
  58. if (encoding == 0) {
  59. encoding = ZX_DEFAULT_BYTE_MODE_ENCODING;
  60. }
  61. // Pick an encoding mode appropriate for the content. Note that this will not attempt to use
  62. // multiple modes / segments even if that were more efficient. Twould be nice.
  63. ZXQRCodeMode *mode = [self chooseMode:content encoding:encoding];
  64. // This will store the header information, like mode and
  65. // length, as well as "header" segments like an ECI segment.
  66. ZXBitArray *headerBits = [[ZXBitArray alloc] init];
  67. // Append ECI segment if applicable
  68. if ([mode isEqual:[ZXQRCodeMode byteMode]] && ZX_DEFAULT_BYTE_MODE_ENCODING != encoding) {
  69. ZXCharacterSetECI *eci = [ZXCharacterSetECI characterSetECIByEncoding:encoding];
  70. if (eci != nil) {
  71. [self appendECI:eci bits:headerBits];
  72. }
  73. }
  74. // (With ECI in place,) Write the mode marker
  75. [self appendModeInfo:mode bits:headerBits];
  76. // Collect data within the main segment, separately, to count its size if needed. Don't add it to
  77. // main payload yet.
  78. ZXBitArray *dataBits = [[ZXBitArray alloc] init];
  79. if (![self appendBytes:content mode:mode bits:dataBits encoding:encoding error:error]) {
  80. return nil;
  81. }
  82. // Hard part: need to know version to know how many bits length takes. But need to know how many
  83. // bits it takes to know version. First we take a guess at version by assuming version will be
  84. // the minimum, 1:
  85. int provisionalBitsNeeded = headerBits.size
  86. + [mode characterCountBits:[ZXQRCodeVersion versionForNumber:1]]
  87. + dataBits.size;
  88. ZXQRCodeVersion *provisionalVersion = [self chooseVersion:provisionalBitsNeeded ecLevel:ecLevel error:error];
  89. if (!provisionalVersion) {
  90. return nil;
  91. }
  92. // Use that guess to calculate the right version. I am still not sure this works in 100% of cases.
  93. int bitsNeeded = headerBits.size
  94. + [mode characterCountBits:provisionalVersion]
  95. + dataBits.size;
  96. ZXQRCodeVersion *version = [self chooseVersion:bitsNeeded ecLevel:ecLevel error:error];
  97. if (!version) {
  98. return nil;
  99. }
  100. ZXBitArray *headerAndDataBits = [[ZXBitArray alloc] init];
  101. [headerAndDataBits appendBitArray:headerBits];
  102. // Find "length" of main segment and write it
  103. int numLetters = [mode isEqual:[ZXQRCodeMode byteMode]] ? [dataBits sizeInBytes] : (int)[content length];
  104. if (![self appendLengthInfo:numLetters version:version mode:mode bits:headerAndDataBits error:error]) {
  105. return nil;
  106. }
  107. // Put data together into the overall payload
  108. [headerAndDataBits appendBitArray:dataBits];
  109. ZXQRCodeECBlocks *ecBlocks = [version ecBlocksForLevel:ecLevel];
  110. int numDataBytes = version.totalCodewords - ecBlocks.totalECCodewords;
  111. // Terminate the bits properly.
  112. if (![self terminateBits:numDataBytes bits:headerAndDataBits error:error]) {
  113. return nil;
  114. }
  115. // Interleave data bits with error correction code.
  116. ZXBitArray *finalBits = [self interleaveWithECBytes:headerAndDataBits numTotalBytes:version.totalCodewords numDataBytes:numDataBytes
  117. numRSBlocks:ecBlocks.numBlocks error:error];
  118. if (!finalBits) {
  119. return nil;
  120. }
  121. ZXQRCode *qrCode = [[ZXQRCode alloc] init];
  122. qrCode.ecLevel = ecLevel;
  123. qrCode.mode = mode;
  124. qrCode.version = version;
  125. // Choose the mask pattern and set to "qrCode".
  126. int dimension = version.dimensionForVersion;
  127. ZXByteMatrix *matrix = [[ZXByteMatrix alloc] initWithWidth:dimension height:dimension];
  128. int maskPattern = [self chooseMaskPattern:finalBits ecLevel:[qrCode ecLevel] version:[qrCode version] matrix:matrix error:error];
  129. if (maskPattern == -1) {
  130. return nil;
  131. }
  132. [qrCode setMaskPattern:maskPattern];
  133. // Build the matrix and set it to "qrCode".
  134. if (![ZXQRCodeMatrixUtil buildMatrix:finalBits ecLevel:ecLevel version:version maskPattern:maskPattern matrix:matrix error:error]) {
  135. return nil;
  136. }
  137. [qrCode setMatrix:matrix];
  138. return qrCode;
  139. }
  140. + (int)alphanumericCode:(int)code {
  141. if (code < sizeof(ZX_ALPHANUMERIC_TABLE) / sizeof(int)) {
  142. return ZX_ALPHANUMERIC_TABLE[code];
  143. }
  144. return -1;
  145. }
  146. + (ZXQRCodeMode *)chooseMode:(NSString *)content {
  147. return [self chooseMode:content encoding:-1];
  148. }
  149. /**
  150. * Choose the best mode by examining the content. Note that 'encoding' is used as a hint;
  151. * if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}.
  152. */
  153. + (ZXQRCodeMode *)chooseMode:(NSString *)content encoding:(NSStringEncoding)encoding {
  154. if (NSShiftJISStringEncoding == encoding) {
  155. return [self isOnlyDoubleByteKanji:content] ? [ZXQRCodeMode kanjiMode] : [ZXQRCodeMode byteMode];
  156. }
  157. BOOL hasNumeric = NO;
  158. BOOL hasAlphanumeric = NO;
  159. for (int i = 0; i < [content length]; ++i) {
  160. unichar c = [content characterAtIndex:i];
  161. if (c >= '0' && c <= '9') {
  162. hasNumeric = YES;
  163. } else if ([self alphanumericCode:c] != -1) {
  164. hasAlphanumeric = YES;
  165. } else {
  166. return [ZXQRCodeMode byteMode];
  167. }
  168. }
  169. if (hasAlphanumeric) {
  170. return [ZXQRCodeMode alphanumericMode];
  171. }
  172. if (hasNumeric) {
  173. return [ZXQRCodeMode numericMode];
  174. }
  175. return [ZXQRCodeMode byteMode];
  176. }
  177. + (BOOL)isOnlyDoubleByteKanji:(NSString *)content {
  178. NSData *data = [content dataUsingEncoding:NSShiftJISStringEncoding];
  179. int8_t *bytes = (int8_t *)[data bytes];
  180. NSUInteger length = [data length];
  181. if (length % 2 != 0) {
  182. return NO;
  183. }
  184. for (int i = 0; i < length; i += 2) {
  185. int byte1 = bytes[i] & 0xFF;
  186. if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) {
  187. return NO;
  188. }
  189. }
  190. return YES;
  191. }
  192. + (int)chooseMaskPattern:(ZXBitArray *)bits ecLevel:(ZXQRCodeErrorCorrectionLevel *)ecLevel version:(ZXQRCodeVersion *)version matrix:(ZXByteMatrix *)matrix error:(NSError **)error {
  193. int minPenalty = INT_MAX;
  194. int bestMaskPattern = -1;
  195. for (int maskPattern = 0; maskPattern < ZX_NUM_MASK_PATTERNS; maskPattern++) {
  196. if (![ZXQRCodeMatrixUtil buildMatrix:bits ecLevel:ecLevel version:version maskPattern:maskPattern matrix:matrix error:error]) {
  197. return -1;
  198. }
  199. int penalty = [self calculateMaskPenalty:matrix];
  200. if (penalty < minPenalty) {
  201. minPenalty = penalty;
  202. bestMaskPattern = maskPattern;
  203. }
  204. }
  205. return bestMaskPattern;
  206. }
  207. + (ZXQRCodeVersion *)chooseVersion:(int)numInputBits ecLevel:(ZXQRCodeErrorCorrectionLevel *)ecLevel error:(NSError **)error {
  208. // In the following comments, we use numbers of Version 7-H.
  209. for (int versionNum = 1; versionNum <= 40; versionNum++) {
  210. ZXQRCodeVersion *version = [ZXQRCodeVersion versionForNumber:versionNum];
  211. // numBytes = 196
  212. int numBytes = version.totalCodewords;
  213. // getNumECBytes = 130
  214. ZXQRCodeECBlocks *ecBlocks = [version ecBlocksForLevel:ecLevel];
  215. int numEcBytes = ecBlocks.totalECCodewords;
  216. // getNumDataBytes = 196 - 130 = 66
  217. int numDataBytes = numBytes - numEcBytes;
  218. int totalInputBytes = (numInputBits + 7) / 8;
  219. if (numDataBytes >= totalInputBytes) {
  220. return version;
  221. }
  222. }
  223. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Data too big"};
  224. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  225. return nil;
  226. }
  227. + (int)totalInputBytes:(int)numInputBits version:(ZXQRCodeVersion *)version mode:(ZXQRCodeMode *)mode {
  228. int modeInfoBits = 4;
  229. int charCountBits = [mode characterCountBits:version];
  230. int headerBits = modeInfoBits + charCountBits;
  231. int totalBits = numInputBits + headerBits;
  232. return (totalBits + 7) / 8;
  233. }
  234. + (BOOL)terminateBits:(int)numDataBytes bits:(ZXBitArray *)bits error:(NSError **)error {
  235. int capacity = numDataBytes * 8;
  236. if ([bits size] > capacity) {
  237. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"data bits cannot fit in the QR Code %d > %d", [bits size], capacity]};
  238. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  239. return NO;
  240. }
  241. for (int i = 0; i < 4 && [bits size] < capacity; ++i) {
  242. [bits appendBit:NO];
  243. }
  244. int numBitsInLastByte = [bits size] & 0x07;
  245. if (numBitsInLastByte > 0) {
  246. for (int i = numBitsInLastByte; i < 8; i++) {
  247. [bits appendBit:NO];
  248. }
  249. }
  250. int numPaddingBytes = numDataBytes - [bits sizeInBytes];
  251. for (int i = 0; i < numPaddingBytes; ++i) {
  252. [bits appendBits:(i & 0x01) == 0 ? 0xEC : 0x11 numBits:8];
  253. }
  254. if ([bits size] != capacity) {
  255. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Bits size does not equal capacity"};
  256. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  257. return NO;
  258. }
  259. return YES;
  260. }
  261. + (BOOL)numDataBytesAndNumECBytesForBlockID:(int)numTotalBytes numDataBytes:(int)numDataBytes numRSBlocks:(int)numRSBlocks blockID:(int)blockID numDataBytesInBlock:(int[])numDataBytesInBlock numECBytesInBlock:(int[])numECBytesInBlock error:(NSError **)error {
  262. if (blockID >= numRSBlocks) {
  263. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Block ID too large"};
  264. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  265. return NO;
  266. }
  267. int numRsBlocksInGroup2 = numTotalBytes % numRSBlocks;
  268. int numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2;
  269. int numTotalBytesInGroup1 = numTotalBytes / numRSBlocks;
  270. int numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1;
  271. int numDataBytesInGroup1 = numDataBytes / numRSBlocks;
  272. int numDataBytesInGroup2 = numDataBytesInGroup1 + 1;
  273. int numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1;
  274. int numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2;
  275. if (numEcBytesInGroup1 != numEcBytesInGroup2) {
  276. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"EC bytes mismatch"};
  277. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  278. return NO;
  279. }
  280. if (numRSBlocks != numRsBlocksInGroup1 + numRsBlocksInGroup2) {
  281. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"RS blocks mismatch"};
  282. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  283. return NO;
  284. }
  285. if (numTotalBytes != ((numDataBytesInGroup1 + numEcBytesInGroup1) * numRsBlocksInGroup1) + ((numDataBytesInGroup2 + numEcBytesInGroup2) * numRsBlocksInGroup2)) {
  286. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Total bytes mismatch"};
  287. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  288. return NO;
  289. }
  290. if (blockID < numRsBlocksInGroup1) {
  291. numDataBytesInBlock[0] = numDataBytesInGroup1;
  292. numECBytesInBlock[0] = numEcBytesInGroup1;
  293. } else {
  294. numDataBytesInBlock[0] = numDataBytesInGroup2;
  295. numECBytesInBlock[0] = numEcBytesInGroup2;
  296. }
  297. return YES;
  298. }
  299. + (ZXBitArray *)interleaveWithECBytes:(ZXBitArray *)bits numTotalBytes:(int)numTotalBytes numDataBytes:(int)numDataBytes numRSBlocks:(int)numRSBlocks error:(NSError **)error {
  300. // "bits" must have "getNumDataBytes" bytes of data.
  301. if ([bits sizeInBytes] != numDataBytes) {
  302. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Number of bits and data bytes does not match"};
  303. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  304. return nil;
  305. }
  306. // Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll
  307. // store the divided data bytes blocks and error correction bytes blocks into "blocks".
  308. int dataBytesOffset = 0;
  309. int maxNumDataBytes = 0;
  310. int maxNumEcBytes = 0;
  311. // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number.
  312. NSMutableArray *blocks = [NSMutableArray arrayWithCapacity:numRSBlocks];
  313. for (int i = 0; i < numRSBlocks; ++i) {
  314. int numDataBytesInBlock[1];
  315. int numEcBytesInBlock[1];
  316. if (![self numDataBytesAndNumECBytesForBlockID:numTotalBytes numDataBytes:numDataBytes numRSBlocks:numRSBlocks
  317. blockID:i numDataBytesInBlock:numDataBytesInBlock
  318. numECBytesInBlock:numEcBytesInBlock error:error]) {
  319. return nil;
  320. }
  321. int size = numDataBytesInBlock[0];
  322. ZXByteArray *dataBytes = [[ZXByteArray alloc] initWithLength:size];
  323. [bits toBytes:8 * dataBytesOffset array:dataBytes offset:0 numBytes:size];
  324. ZXByteArray *ecBytes = [self generateECBytes:dataBytes numEcBytesInBlock:numEcBytesInBlock[0]];
  325. [blocks addObject:[[ZXQRCodeBlockPair alloc] initWithData:dataBytes errorCorrection:ecBytes]];
  326. maxNumDataBytes = MAX(maxNumDataBytes, size);
  327. maxNumEcBytes = MAX(maxNumEcBytes, numEcBytesInBlock[0]);
  328. dataBytesOffset += numDataBytesInBlock[0];
  329. }
  330. if (numDataBytes != dataBytesOffset) {
  331. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Data bytes does not match offset"};
  332. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  333. return nil;
  334. }
  335. ZXBitArray *result = [[ZXBitArray alloc] init];
  336. // First, place data blocks.
  337. for (int i = 0; i < maxNumDataBytes; ++i) {
  338. for (ZXQRCodeBlockPair *block in blocks) {
  339. ZXByteArray *dataBytes = block.dataBytes;
  340. NSUInteger length = dataBytes.length;
  341. if (i < length) {
  342. [result appendBits:dataBytes.array[i] numBits:8];
  343. }
  344. }
  345. }
  346. // Then, place error correction blocks.
  347. for (int i = 0; i < maxNumEcBytes; ++i) {
  348. for (ZXQRCodeBlockPair *block in blocks) {
  349. ZXByteArray *ecBytes = block.errorCorrectionBytes;
  350. int length = ecBytes.length;
  351. if (i < length) {
  352. [result appendBits:ecBytes.array[i] numBits:8];
  353. }
  354. }
  355. }
  356. if (numTotalBytes != [result sizeInBytes]) {
  357. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Interleaving error: %d and %d differ.", numTotalBytes, [result sizeInBytes]]};
  358. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  359. return nil;
  360. }
  361. return result;
  362. }
  363. + (ZXByteArray *)generateECBytes:(ZXByteArray *)dataBytes numEcBytesInBlock:(int)numEcBytesInBlock {
  364. int numDataBytes = dataBytes.length;
  365. ZXIntArray *toEncode = [[ZXIntArray alloc] initWithLength:numDataBytes + numEcBytesInBlock];
  366. for (int i = 0; i < numDataBytes; i++) {
  367. toEncode.array[i] = dataBytes.array[i] & 0xFF;
  368. }
  369. [[[ZXReedSolomonEncoder alloc] initWithField:[ZXGenericGF QrCodeField256]] encode:toEncode ecBytes:numEcBytesInBlock];
  370. ZXByteArray *ecBytes = [[ZXByteArray alloc] initWithLength:numEcBytesInBlock];
  371. for (int i = 0; i < numEcBytesInBlock; i++) {
  372. ecBytes.array[i] = (int8_t) toEncode.array[numDataBytes + i];
  373. }
  374. return ecBytes;
  375. }
  376. + (void)appendModeInfo:(ZXQRCodeMode *)mode bits:(ZXBitArray *)bits {
  377. [bits appendBits:[mode bits] numBits:4];
  378. }
  379. /**
  380. * Append length info. On success, store the result in "bits".
  381. */
  382. + (BOOL)appendLengthInfo:(int)numLetters version:(ZXQRCodeVersion *)version mode:(ZXQRCodeMode *)mode bits:(ZXBitArray *)bits error:(NSError **)error {
  383. int numBits = [mode characterCountBits:version];
  384. if (numLetters >= (1 << numBits)) {
  385. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"%d is bigger than %d", numLetters, ((1 << numBits) - 1)]};
  386. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  387. return NO;
  388. }
  389. [bits appendBits:numLetters numBits:numBits];
  390. return YES;
  391. }
  392. + (BOOL)appendBytes:(NSString *)content mode:(ZXQRCodeMode *)mode bits:(ZXBitArray *)bits encoding:(NSStringEncoding)encoding error:(NSError **)error {
  393. if ([mode isEqual:[ZXQRCodeMode numericMode]]) {
  394. [self appendNumericBytes:content bits:bits];
  395. } else if ([mode isEqual:[ZXQRCodeMode alphanumericMode]]) {
  396. if (![self appendAlphanumericBytes:content bits:bits error:error]) {
  397. return NO;
  398. }
  399. } else if ([mode isEqual:[ZXQRCodeMode byteMode]]) {
  400. [self append8BitBytes:content bits:bits encoding:encoding];
  401. } else if ([mode isEqual:[ZXQRCodeMode kanjiMode]]) {
  402. if (![self appendKanjiBytes:content bits:bits error:error]) {
  403. return NO;
  404. }
  405. } else {
  406. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: [NSString stringWithFormat:@"Invalid mode: %@", mode]};
  407. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  408. return NO;
  409. }
  410. return YES;
  411. }
  412. + (void)appendNumericBytes:(NSString *)content bits:(ZXBitArray *)bits {
  413. NSUInteger length = [content length];
  414. int i = 0;
  415. while (i < length) {
  416. int num1 = [content characterAtIndex:i] - '0';
  417. if (i + 2 < length) {
  418. int num2 = [content characterAtIndex:i + 1] - '0';
  419. int num3 = [content characterAtIndex:i + 2] - '0';
  420. [bits appendBits:num1 * 100 + num2 * 10 + num3 numBits:10];
  421. i += 3;
  422. } else if (i + 1 < length) {
  423. int num2 = [content characterAtIndex:i + 1] - '0';
  424. [bits appendBits:num1 * 10 + num2 numBits:7];
  425. i += 2;
  426. } else {
  427. [bits appendBits:num1 numBits:4];
  428. i++;
  429. }
  430. }
  431. }
  432. + (BOOL)appendAlphanumericBytes:(NSString *)content bits:(ZXBitArray *)bits error:(NSError **)error {
  433. NSUInteger length = [content length];
  434. int i = 0;
  435. while (i < length) {
  436. int code1 = [self alphanumericCode:[content characterAtIndex:i]];
  437. if (code1 == -1) {
  438. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:nil];
  439. return NO;
  440. }
  441. if (i + 1 < length) {
  442. int code2 = [self alphanumericCode:[content characterAtIndex:i + 1]];
  443. if (code2 == -1) {
  444. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:nil];
  445. return NO;
  446. }
  447. [bits appendBits:code1 * 45 + code2 numBits:11];
  448. i += 2;
  449. } else {
  450. [bits appendBits:code1 numBits:6];
  451. i++;
  452. }
  453. }
  454. return YES;
  455. }
  456. + (void)append8BitBytes:(NSString *)content bits:(ZXBitArray *)bits encoding:(NSStringEncoding)encoding {
  457. NSData *data = [content dataUsingEncoding:encoding];
  458. int8_t *bytes = (int8_t *)[data bytes];
  459. for (int i = 0; i < [data length]; ++i) {
  460. [bits appendBits:bytes[i] numBits:8];
  461. }
  462. }
  463. + (BOOL)appendKanjiBytes:(NSString *)content bits:(ZXBitArray *)bits error:(NSError **)error {
  464. NSData *data = [content dataUsingEncoding:NSShiftJISStringEncoding];
  465. int8_t *bytes = (int8_t *)[data bytes];
  466. for (int i = 0; i < [data length]; i += 2) {
  467. int byte1 = bytes[i] & 0xFF;
  468. int byte2 = bytes[i + 1] & 0xFF;
  469. int code = (byte1 << 8) | byte2;
  470. int subtracted = -1;
  471. if (code >= 0x8140 && code <= 0x9ffc) {
  472. subtracted = code - 0x8140;
  473. } else if (code >= 0xe040 && code <= 0xebbf) {
  474. subtracted = code - 0xc140;
  475. }
  476. if (subtracted == -1) {
  477. NSDictionary *userInfo = @{NSLocalizedDescriptionKey: @"Invalid byte sequence"};
  478. if (error) *error = [[NSError alloc] initWithDomain:ZXErrorDomain code:ZXWriterError userInfo:userInfo];
  479. return NO;
  480. }
  481. int encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff);
  482. [bits appendBits:encoded numBits:13];
  483. }
  484. return YES;
  485. }
  486. + (void)appendECI:(ZXCharacterSetECI *)eci bits:(ZXBitArray *)bits {
  487. [bits appendBits:[[ZXQRCodeMode eciMode] bits] numBits:4];
  488. [bits appendBits:[eci value] numBits:8];
  489. }
  490. @end