123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- /*
- * Copyright 2012 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- #import "ZXBitMatrix.h"
- #import "ZXByteArray.h"
- #import "ZXErrors.h"
- #import "ZXQRCodeBitMatrixParser.h"
- #import "ZXQRCodeDataMask.h"
- #import "ZXQRCodeFormatInformation.h"
- #import "ZXQRCodeVersion.h"
-
- @interface ZXQRCodeBitMatrixParser ()
-
- @property (nonatomic, strong, readonly) ZXBitMatrix *bitMatrix;
- @property (nonatomic, assign) BOOL shouldMirror;
- @property (nonatomic, strong) ZXQRCodeFormatInformation *parsedFormatInfo;
- @property (nonatomic, strong) ZXQRCodeVersion *parsedVersion;
-
- @end
-
- @implementation ZXQRCodeBitMatrixParser
-
- - (id)initWithBitMatrix:(ZXBitMatrix *)bitMatrix error:(NSError **)error {
- int dimension = bitMatrix.height;
- if (dimension < 21 || (dimension & 0x03) != 1) {
- if (error) *error = ZXFormatErrorInstance();
- return nil;
- }
-
- if (self = [super init]) {
- _bitMatrix = bitMatrix;
- _parsedFormatInfo = nil;
- _parsedVersion = nil;
- }
- return self;
- }
-
- - (ZXQRCodeFormatInformation *)readFormatInformationWithError:(NSError **)error {
- if (self.parsedFormatInfo != nil) {
- return self.parsedFormatInfo;
- }
- int formatInfoBits1 = 0;
-
- for (int i = 0; i < 6; i++) {
- formatInfoBits1 = [self copyBit:i j:8 versionBits:formatInfoBits1];
- }
-
- formatInfoBits1 = [self copyBit:7 j:8 versionBits:formatInfoBits1];
- formatInfoBits1 = [self copyBit:8 j:8 versionBits:formatInfoBits1];
- formatInfoBits1 = [self copyBit:8 j:7 versionBits:formatInfoBits1];
-
- for (int j = 5; j >= 0; j--) {
- formatInfoBits1 = [self copyBit:8 j:j versionBits:formatInfoBits1];
- }
-
- int dimension = self.bitMatrix.height;
- int formatInfoBits2 = 0;
- int jMin = dimension - 7;
-
- for (int j = dimension - 1; j >= jMin; j--) {
- formatInfoBits2 = [self copyBit:8 j:j versionBits:formatInfoBits2];
- }
-
- for (int i = dimension - 8; i < dimension; i++) {
- formatInfoBits2 = [self copyBit:i j:8 versionBits:formatInfoBits2];
- }
-
- self.parsedFormatInfo = [ZXQRCodeFormatInformation decodeFormatInformation:formatInfoBits1 maskedFormatInfo2:formatInfoBits2];
- if (self.parsedFormatInfo != nil) {
- return self.parsedFormatInfo;
- }
- if (error) *error = ZXFormatErrorInstance();
- return nil;
- }
-
- - (ZXQRCodeVersion *)readVersionWithError:(NSError **)error {
- if (self.parsedVersion != nil) {
- return self.parsedVersion;
- }
- int dimension = self.bitMatrix.height;
- int provisionalVersion = (dimension - 17) / 4;
- if (provisionalVersion <= 6) {
- return [ZXQRCodeVersion versionForNumber:provisionalVersion];
- }
- int versionBits = 0;
- int ijMin = dimension - 11;
-
- for (int j = 5; j >= 0; j--) {
-
- for (int i = dimension - 9; i >= ijMin; i--) {
- versionBits = [self copyBit:i j:j versionBits:versionBits];
- }
-
- }
-
- ZXQRCodeVersion *theParsedVersion = [ZXQRCodeVersion decodeVersionInformation:versionBits];
- if (theParsedVersion != nil && theParsedVersion.dimensionForVersion == dimension) {
- self.parsedVersion = theParsedVersion;
- return self.parsedVersion;
- }
- versionBits = 0;
-
- for (int i = 5; i >= 0; i--) {
- for (int j = dimension - 9; j >= ijMin; j--) {
- versionBits = [self copyBit:i j:j versionBits:versionBits];
- }
- }
-
- theParsedVersion = [ZXQRCodeVersion decodeVersionInformation:versionBits];
- if (theParsedVersion != nil && theParsedVersion.dimensionForVersion == dimension) {
- self.parsedVersion = theParsedVersion;
- return self.parsedVersion;
- }
- if (error) *error = ZXFormatErrorInstance();
- return nil;
- }
-
- - (int)copyBit:(int)i j:(int)j versionBits:(int)versionBits {
- BOOL bit = self.shouldMirror ? [self.bitMatrix getX:j y:i] : [self.bitMatrix getX:i y:j];
- return bit ? (versionBits << 1) | 0x1 : versionBits << 1;
- }
-
- - (ZXByteArray *)readCodewordsWithError:(NSError **)error {
- ZXQRCodeFormatInformation *formatInfo = [self readFormatInformationWithError:error];
- if (!formatInfo) {
- return nil;
- }
-
- ZXQRCodeVersion *version = [self readVersionWithError:error];
- if (!version) {
- return nil;
- }
-
- // Get the data mask for the format used in this QR Code. This will exclude
- // some bits from reading as we wind through the bit matrix.
- ZXQRCodeDataMask *dataMask = [ZXQRCodeDataMask forReference:[formatInfo dataMask]];
- int dimension = self.bitMatrix.height;
- [dataMask unmaskBitMatrix:self.bitMatrix dimension:dimension];
-
- ZXBitMatrix *functionPattern = [version buildFunctionPattern];
-
- BOOL readingUp = YES;
- ZXByteArray *result = [[ZXByteArray alloc] initWithLength:version.totalCodewords];
- int resultOffset = 0;
- int currentByte = 0;
- int bitsRead = 0;
- // Read columns in pairs, from right to left
- for (int j = dimension - 1; j > 0; j -= 2) {
- if (j == 6) {
- // Skip whole column with vertical alignment pattern;
- // saves time and makes the other code proceed more cleanly
- j--;
- }
- // Read alternatingly from bottom to top then top to bottom
- for (int count = 0; count < dimension; count++) {
- int i = readingUp ? dimension - 1 - count : count;
- for (int col = 0; col < 2; col++) {
- // Ignore bits covered by the function pattern
- if (![functionPattern getX:j - col y:i]) {
- // Read a bit
- bitsRead++;
- currentByte <<= 1;
- if ([self.bitMatrix getX:j - col y:i]) {
- currentByte |= 1;
- }
- // If we've made a whole byte, save it off
- if (bitsRead == 8) {
- result.array[resultOffset++] = (int8_t) currentByte;
- bitsRead = 0;
- currentByte = 0;
- }
- }
- }
- }
- readingUp ^= YES; // readingUp = !readingUp; // switch directions
- }
- if (resultOffset != [version totalCodewords]) {
- if (error) *error = ZXFormatErrorInstance();
- return nil;
- }
- return result;
- }
-
- - (void)remask {
- if (!self.parsedFormatInfo) {
- return; // We have no format information, and have no data mask
- }
- ZXQRCodeDataMask *dataMask = [ZXQRCodeDataMask forReference:self.parsedFormatInfo.dataMask];
- int dimension = self.bitMatrix.height;
- [dataMask unmaskBitMatrix:self.bitMatrix dimension:dimension];
- }
-
- - (void)setMirror:(BOOL)mirror {
- self.parsedVersion = nil;
- self.parsedFormatInfo = nil;
- self.shouldMirror = mirror;
- }
-
- - (void)mirror {
- for (int x = 0; x < self.bitMatrix.width; x++) {
- for (int y = x + 1; y < self.bitMatrix.height; y++) {
- if ([self.bitMatrix getX:x y:y] != [self.bitMatrix getX:y y:x]) {
- [self.bitMatrix flipX:y y:x];
- [self.bitMatrix flipX:x y:y];
- }
- }
- }
- }
-
- @end
|