Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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 "ZXAztecDecoder.h"
  17. #import "ZXAztecDetectorResult.h"
  18. #import "ZXBitMatrix.h"
  19. #import "ZXBoolArray.h"
  20. #import "ZXDecoderResult.h"
  21. #import "ZXErrors.h"
  22. #import "ZXGenericGF.h"
  23. #import "ZXIntArray.h"
  24. #import "ZXReedSolomonDecoder.h"
  25. #import "ZXByteArray.h"
  26. typedef enum {
  27. ZXAztecTableUpper = 0,
  28. ZXAztecTableLower,
  29. ZXAztecTableMixed,
  30. ZXAztecTableDigit,
  31. ZXAztecTablePunct,
  32. ZXAztecTableBinary
  33. } ZXAztecTable;
  34. static NSString *ZX_AZTEC_UPPER_TABLE[] = {
  35. @"CTRL_PS", @" ", @"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L", @"M", @"N", @"O", @"P",
  36. @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z", @"CTRL_LL", @"CTRL_ML", @"CTRL_DL", @"CTRL_BS"
  37. };
  38. static NSString *ZX_AZTEC_LOWER_TABLE[] = {
  39. @"CTRL_PS", @" ", @"a", @"b", @"c", @"d", @"e", @"f", @"g", @"h", @"i", @"j", @"k", @"l", @"m", @"n", @"o", @"p",
  40. @"q", @"r", @"s", @"t", @"u", @"v", @"w", @"x", @"y", @"z", @"CTRL_US", @"CTRL_ML", @"CTRL_DL", @"CTRL_BS"
  41. };
  42. static NSString *ZX_AZTEC_MIXED_TABLE[] = {
  43. @"CTRL_PS", @" ", @"\1", @"\2", @"\3", @"\4", @"\5", @"\6", @"\7", @"\b", @"\t", @"\n",
  44. @"\13", @"\f", @"\r", @"\33", @"\34", @"\35", @"\36", @"\37", @"@", @"\\", @"^", @"_",
  45. @"`", @"|", @"~", @"\177", @"CTRL_LL", @"CTRL_UL", @"CTRL_PL", @"CTRL_BS"
  46. };
  47. static NSString *ZX_AZTEC_PUNCT_TABLE[] = {
  48. @"", @"\r", @"\r\n", @". ", @", ", @": ", @"!", @"\"", @"#", @"$", @"%", @"&", @"'", @"(", @")",
  49. @"*", @"+", @",", @"-", @".", @"/", @":", @";", @"<", @"=", @">", @"?", @"[", @"]", @"{", @"}", @"CTRL_UL"
  50. };
  51. static NSString *ZX_AZTEC_DIGIT_TABLE[] = {
  52. @"CTRL_PS", @" ", @"0", @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @",", @".", @"CTRL_UL", @"CTRL_US"
  53. };
  54. @interface ZXAztecDecoder ()
  55. @property (nonatomic, strong) ZXAztecDetectorResult *ddata;
  56. @end
  57. @implementation ZXAztecDecoder
  58. - (ZXDecoderResult *)decode:(ZXAztecDetectorResult *)detectorResult error:(NSError **)error {
  59. self.ddata = detectorResult;
  60. ZXBitMatrix *matrix = [detectorResult bits];
  61. ZXBoolArray *rawbits = [self extractBits:matrix];
  62. if (!rawbits) {
  63. if (error) *error = ZXFormatErrorInstance();
  64. return nil;
  65. }
  66. ZXBoolArray *correctedBits = [self correctBits:rawbits error:error];
  67. if (!correctedBits) {
  68. return nil;
  69. }
  70. NSMutableArray *rawBytes = [ZXAztecDecoder convertBoolArrayToByteArray: correctedBits];
  71. NSString *result = [[self class] encodedData:correctedBits];
  72. NSUInteger rawBytesSize = [rawBytes count];
  73. ZXByteArray *rawBytesReturned = [[ZXByteArray alloc] initWithLength:(unsigned int)rawBytesSize];
  74. for (int i = 0; i < rawBytesSize; i++) {
  75. rawBytesReturned.array[i] = (int8_t)[rawBytes[i] intValue];
  76. }
  77. return [[ZXDecoderResult alloc] initWithRawBytes:rawBytesReturned text:result byteSegments:nil ecLevel:nil];
  78. }
  79. + (NSString *)highLevelDecode:(ZXBoolArray *)correctedBits {
  80. return [self encodedData:correctedBits];
  81. }
  82. /**
  83. * Gets the string encoded in the aztec code bits
  84. *
  85. * @return the decoded string
  86. */
  87. + (NSString *)encodedData:(ZXBoolArray *)correctedBits {
  88. int endIndex = (int)correctedBits.length;
  89. ZXAztecTable latchTable = ZXAztecTableUpper; // table most recently latched to
  90. ZXAztecTable shiftTable = ZXAztecTableUpper; // table to use for the next read
  91. NSMutableString *result = [NSMutableString stringWithCapacity:20];
  92. int index = 0;
  93. while (index < endIndex) {
  94. if (shiftTable == ZXAztecTableBinary) {
  95. if (endIndex - index < 5) {
  96. break;
  97. }
  98. int length = [self readCode:correctedBits startIndex:index length:5];
  99. index += 5;
  100. if (length == 0) {
  101. if (endIndex - index < 11) {
  102. break;
  103. }
  104. length = [self readCode:correctedBits startIndex:index length:11] + 31;
  105. index += 11;
  106. }
  107. for (int charCount = 0; charCount < length; charCount++) {
  108. if (endIndex - index < 8) {
  109. index = endIndex; // Force outer loop to exit
  110. break;
  111. }
  112. int code = [self readCode:correctedBits startIndex:index length:8];
  113. [result appendFormat:@"%C", (unichar)code];
  114. index += 8;
  115. }
  116. // Go back to whatever mode we had been in
  117. shiftTable = latchTable;
  118. } else {
  119. int size = shiftTable == ZXAztecTableDigit ? 4 : 5;
  120. if (endIndex - index < size) {
  121. break;
  122. }
  123. int code = [self readCode:correctedBits startIndex:index length:size];
  124. index += size;
  125. NSString *str = [self character:shiftTable code:code];
  126. if ([str hasPrefix:@"CTRL_"]) {
  127. // Table changes
  128. shiftTable = [self table:[str characterAtIndex:5]];
  129. if ([str characterAtIndex:6] == 'L') {
  130. latchTable = shiftTable;
  131. }
  132. } else {
  133. [result appendString:str];
  134. // Go back to whatever mode we had been in
  135. shiftTable = latchTable;
  136. }
  137. }
  138. }
  139. return [NSString stringWithString:result];
  140. }
  141. /**
  142. * gets the table corresponding to the char passed
  143. */
  144. + (ZXAztecTable)table:(unichar)t {
  145. switch (t) {
  146. case 'L':
  147. return ZXAztecTableLower;
  148. case 'P':
  149. return ZXAztecTablePunct;
  150. case 'M':
  151. return ZXAztecTableMixed;
  152. case 'D':
  153. return ZXAztecTableDigit;
  154. case 'B':
  155. return ZXAztecTableBinary;
  156. case 'U':
  157. default:
  158. return ZXAztecTableUpper;
  159. }
  160. }
  161. /**
  162. * Gets the character (or string) corresponding to the passed code in the given table
  163. *
  164. * @param table the table used
  165. * @param code the code of the character
  166. */
  167. + (NSString *)character:(ZXAztecTable)table code:(int)code {
  168. switch (table) {
  169. case ZXAztecTableUpper:
  170. return ZX_AZTEC_UPPER_TABLE[code];
  171. case ZXAztecTableLower:
  172. return ZX_AZTEC_LOWER_TABLE[code];
  173. case ZXAztecTableMixed:
  174. return ZX_AZTEC_MIXED_TABLE[code];
  175. case ZXAztecTablePunct:
  176. return ZX_AZTEC_PUNCT_TABLE[code];
  177. case ZXAztecTableDigit:
  178. return ZX_AZTEC_DIGIT_TABLE[code];
  179. default:
  180. // Should not reach here.
  181. @throw [NSException exceptionWithName:@"IllegalStateException" reason:@"Bad table" userInfo:nil];
  182. }
  183. }
  184. /**
  185. * <p>Performs RS error correction on an array of bits.</p>
  186. *
  187. * @return the number of corrected bits, or 0 if the input contains too many errors
  188. */
  189. - (ZXBoolArray *)correctBits:(ZXBoolArray *)rawbits error:(NSError **)error {
  190. ZXGenericGF *gf;
  191. int codewordSize;
  192. if ([self.ddata nbLayers] <= 2) {
  193. codewordSize = 6;
  194. gf = [ZXGenericGF AztecData6];
  195. } else if ([self.ddata nbLayers] <= 8) {
  196. codewordSize = 8;
  197. gf = [ZXGenericGF AztecData8];
  198. } else if ([self.ddata nbLayers] <= 22) {
  199. codewordSize = 10;
  200. gf = [ZXGenericGF AztecData10];
  201. } else {
  202. codewordSize = 12;
  203. gf = [ZXGenericGF AztecData12];
  204. }
  205. int numDataCodewords = [self.ddata nbDatablocks];
  206. int numCodewords = rawbits.length / codewordSize;
  207. if (numCodewords < numDataCodewords) {
  208. if (error) *error = ZXFormatErrorInstance();
  209. return 0;
  210. }
  211. int offset = rawbits.length % codewordSize;
  212. int numECCodewords = numCodewords - numDataCodewords;
  213. ZXIntArray *dataWords = [[ZXIntArray alloc] initWithLength:numCodewords];
  214. for (int i = 0; i < numCodewords; i++, offset += codewordSize) {
  215. dataWords.array[i] = [[self class] readCode:rawbits startIndex:offset length:codewordSize];
  216. }
  217. ZXReedSolomonDecoder *rsDecoder = [[ZXReedSolomonDecoder alloc] initWithField:gf];
  218. NSError *decodeError = nil;
  219. if (![rsDecoder decode:dataWords twoS:numECCodewords error:&decodeError]) {
  220. if (decodeError.code == ZXReedSolomonError) {
  221. if (error) *error = ZXFormatErrorInstance();
  222. } else {
  223. if (error) *error = decodeError;
  224. }
  225. return 0;
  226. }
  227. // Now perform the unstuffing operation.
  228. // First, count how many bits are going to be thrown out as stuffing
  229. int mask = (1 << codewordSize) - 1;
  230. int stuffedBits = 0;
  231. for (int i = 0; i < numDataCodewords; i++) {
  232. int32_t dataWord = dataWords.array[i];
  233. if (dataWord == 0 || dataWord == mask) {
  234. if (error) *error = ZXFormatErrorInstance();
  235. return 0;
  236. } else if (dataWord == 1 || dataWord == mask - 1) {
  237. stuffedBits++;
  238. }
  239. }
  240. // Now, actually unpack the bits and remove the stuffing
  241. ZXBoolArray *correctedBits = [[ZXBoolArray alloc] initWithLength:numDataCodewords * codewordSize - stuffedBits];
  242. int index = 0;
  243. for (int i = 0; i < numDataCodewords; i++) {
  244. int dataWord = dataWords.array[i];
  245. if (dataWord == 1 || dataWord == mask - 1) {
  246. // next codewordSize-1 bits are all zeros or all ones
  247. memset(correctedBits.array + index * sizeof(BOOL), dataWord > 1, codewordSize - 1);
  248. index += codewordSize - 1;
  249. } else {
  250. for (int bit = codewordSize - 1; bit >= 0; --bit) {
  251. correctedBits.array[index++] = (dataWord & (1 << bit)) != 0;
  252. }
  253. }
  254. }
  255. return correctedBits;
  256. }
  257. /**
  258. * Gets the array of bits from an Aztec Code matrix
  259. *
  260. * @return the size of the array of bits
  261. */
  262. - (ZXBoolArray *)extractBits:(ZXBitMatrix *)matrix {
  263. BOOL compact = self.ddata.isCompact;
  264. int layers = self.ddata.nbLayers;
  265. int baseMatrixSize = compact ? 11 + layers * 4 : 14 + layers * 4; // not including alignment lines
  266. ZXIntArray *alignmentMap = [[ZXIntArray alloc] initWithLength:baseMatrixSize];
  267. ZXBoolArray *rawbits = [[ZXBoolArray alloc] initWithLength:[self totalBitsInLayer:layers compact:compact]];
  268. if (compact) {
  269. for (int i = 0; i < alignmentMap.length; i++) {
  270. alignmentMap.array[i] = i;
  271. }
  272. } else {
  273. int matrixSize = baseMatrixSize + 1 + 2 * ((baseMatrixSize / 2 - 1) / 15);
  274. int origCenter = baseMatrixSize / 2;
  275. int center = matrixSize / 2;
  276. for (int i = 0; i < origCenter; i++) {
  277. int newOffset = i + i / 15;
  278. alignmentMap.array[origCenter - i - 1] = (int32_t)(center - newOffset - 1);
  279. alignmentMap.array[origCenter + i] = (int32_t)(center + newOffset + 1);
  280. }
  281. }
  282. for (int i = 0, rowOffset = 0; i < layers; i++) {
  283. int rowSize = compact ? (layers - i) * 4 + 9 : (layers - i) * 4 + 12;
  284. // The top-left most point of this layer is <low, low> (not including alignment lines)
  285. int low = i * 2;
  286. // The bottom-right most point of this layer is <high, high> (not including alignment lines)
  287. int high = baseMatrixSize - 1 - low;
  288. // We pull bits from the two 2 x rowSize columns and two rowSize x 2 rows
  289. for (int j = 0; j < rowSize; j++) {
  290. int columnOffset = j * 2;
  291. for (int k = 0; k < 2; k++) {
  292. // left column
  293. rawbits.array[rowOffset + columnOffset + k] =
  294. [matrix getX:alignmentMap.array[low + k] y:alignmentMap.array[low + j]];
  295. // bottom row
  296. rawbits.array[rowOffset + 2 * rowSize + columnOffset + k] =
  297. [matrix getX:alignmentMap.array[low + j] y:alignmentMap.array[high - k]];
  298. // right column
  299. rawbits.array[rowOffset + 4 * rowSize + columnOffset + k] =
  300. [matrix getX:alignmentMap.array[high - k] y:alignmentMap.array[high - j]];
  301. // top row
  302. rawbits.array[rowOffset + 6 * rowSize + columnOffset + k] =
  303. [matrix getX:alignmentMap.array[high - j] y:alignmentMap.array[low + k]];
  304. }
  305. }
  306. rowOffset += rowSize * 8;
  307. }
  308. return rawbits;
  309. }
  310. /**
  311. * Reads a code of given length and at given index in an array of bits
  312. */
  313. + (int)readCode:(ZXBoolArray *)rawbits startIndex:(int)startIndex length:(int)length {
  314. int res = 0;
  315. for (int i = startIndex; i < startIndex + length; i++) {
  316. res <<= 1;
  317. if (rawbits.array[i]) {
  318. res |= 0x01;
  319. }
  320. }
  321. return res;
  322. }
  323. /**
  324. * Reads a code of length 8 in an array of bits, padding with zeros
  325. */
  326. + (int) readByte:(ZXBoolArray *) rawbits startIndex:(int) startIndex {
  327. int n = rawbits.length - startIndex;
  328. if (n >= 8) {
  329. return (int) [self readCode:rawbits startIndex:startIndex length:8];
  330. }
  331. return (int) ([self readCode:rawbits startIndex:startIndex length:n] << (8 - n));
  332. }
  333. /**
  334. * Packs a bit array into bytes, most significant bit first
  335. */
  336. + (NSMutableArray *) convertBoolArrayToByteArray:(ZXBoolArray *) boolArr {
  337. NSMutableArray *byteArr = [[NSMutableArray alloc] init];
  338. int byteArrLength = (boolArr.length + 7) / 8;
  339. for (int i = 0; i < byteArrLength; i++) {
  340. int code = [self readByte:boolArr startIndex:8 * i];
  341. [byteArr addObject:@(code)];
  342. }
  343. return byteArr;
  344. }
  345. - (int)totalBitsInLayer:(int)layers compact:(BOOL)compact {
  346. return ((compact ? 88 : 112) + 16 * layers) * layers;
  347. }
  348. @end