5 * Created by Christian Brunschen on 20/05/2008.
6 * Copyright 2008 ZXing authors All rights reserved.
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
21 #include "BitMatrixParser.h"
27 using namespace common;
29 int BitMatrixParser::copyBit(size_t i, size_t j, int versionBits) {
30 return bitMatrix_->get(i, j) ?
31 (versionBits << 1) | 0x1
35 BitMatrixParser::BitMatrixParser(Ref<BitMatrix> bitMatrix) :
36 bitMatrix_(bitMatrix), parsedVersion_(0), parsedFormatInfo_() {
37 int dimension = bitMatrix->getDimension();
38 if ((dimension < 21) || (dimension & 0x03) != 1) {
39 throw new ReaderException("Dimension must be 1 mod 4 and >= 21");
43 Ref<FormatInformation> BitMatrixParser::readFormatInformation() {
44 if (parsedFormatInfo_ != 0) {
45 return parsedFormatInfo_;
48 // Read top-left format info bits
49 int formatInfoBits = 0;
50 for (int j = 0; j < 6; j++) {
51 formatInfoBits = copyBit(8, j, formatInfoBits);
53 // .. and skip a bit in the timing pattern ...
54 formatInfoBits = copyBit(8, 7, formatInfoBits);
55 formatInfoBits = copyBit(8, 8, formatInfoBits);
56 formatInfoBits = copyBit(7, 8, formatInfoBits);
57 // .. and skip a bit in the timing pattern ...
58 for (int i = 5; i >= 0; i--) {
59 formatInfoBits = copyBit(i, 8, formatInfoBits);
62 parsedFormatInfo_ = FormatInformation::decodeFormatInformation(formatInfoBits);
63 if (parsedFormatInfo_ != 0) {
64 return parsedFormatInfo_;
67 // Hmm, failed. Try the top-right/bottom-left pattern
68 int dimension = bitMatrix_->getDimension();
70 int iMin = dimension - 8;
71 for (int i = dimension - 1; i >= iMin; i--) {
72 formatInfoBits = copyBit(i, 8, formatInfoBits);
74 for (int j = dimension - 7; j < dimension; j++) {
75 formatInfoBits = copyBit(8, j, formatInfoBits);
78 parsedFormatInfo_ = FormatInformation::decodeFormatInformation(formatInfoBits);
79 if (parsedFormatInfo_ != 0) {
80 return parsedFormatInfo_;
82 throw new ReaderException("Could not decode format information");
85 Version *BitMatrixParser::readVersion() {
86 if (parsedVersion_ != 0) {
87 return parsedVersion_;
90 int dimension = bitMatrix_->getDimension();
92 int provisionalVersion = (dimension - 17) >> 2;
93 if (provisionalVersion <= 6) {
94 return Version::getVersionForNumber(provisionalVersion);
97 // Read top-right version info: 3 wide by 6 tall
99 for (int i = 5; i >= 0; i--) {
100 int jMin = dimension - 11;
101 for (int j = dimension - 9; j >= jMin; j--) {
102 versionBits = copyBit(i, j, versionBits);
106 parsedVersion_ = Version::decodeVersionInformation(versionBits);
107 if (parsedVersion_ != 0) {
108 return parsedVersion_;
111 // Hmm, failed. Try bottom left: 6 wide by 3 tall
113 for (int j = 5; j >= 0; j--) {
114 int iMin = dimension - 11;
115 for (int i = dimension - 9; i >= iMin; i--) {
116 versionBits = copyBit(i, j, versionBits);
120 parsedVersion_ = Version::decodeVersionInformation(versionBits);
121 if (parsedVersion_ != 0) {
122 return parsedVersion_;
124 throw new ReaderException("Could not decode version");
127 ArrayRef<unsigned char> BitMatrixParser::readCodewords() {
128 Ref<FormatInformation> formatInfo = readFormatInformation();
129 Version *version = readVersion();
131 // Get the data mask for the format used in this QR Code. This will exclude
132 // some bits from reading as we wind through the bit matrix.
133 DataMask &dataMask = DataMask::forReference((int) formatInfo->getDataMask());
134 int dimension = bitMatrix_->getDimension();
135 dataMask.unmaskBitMatrix(bitMatrix_->getBits(), dimension);
137 Ref<BitMatrix> functionPattern = version->buildFunctionPattern();
139 bool readingUp = true;
140 ArrayRef<unsigned char> result(version->getTotalCodewords());
141 int resultOffset = 0;
144 // Read columns in pairs, from right to left
145 size_t D = functionPattern.object_->dimension_;
146 for (int j = dimension - 1; j > 0; j -= 2) {
148 // Skip whole column with vertical alignment pattern;
149 // saves time and makes the other code proceed more cleanly
152 // Read alternatingly from bottom to top then top to bottom
153 for (int count = 0; count < dimension; count++) {
154 int i = readingUp ? dimension - 1 - count : count;
155 for (int col = 0; col < 2; col++) {
156 // Ignore bits covered by the function pattern
157 if (functionPattern.object_->dimension_ != D) {
158 cout << "function pattern dimension changed from " << D << " to " << functionPattern.object_->dimension_ << "\n";
159 D = functionPattern.object_->dimension_;
161 if (!functionPattern->get(i, j - col)) {
165 if (bitMatrix_->get(i, j - col)) {
168 // If we've made a whole byte, save it off
170 result[resultOffset++] = (unsigned char) currentByte;
177 readingUp = !readingUp; // switch directions
179 if (resultOffset != version->getTotalCodewords()) {
180 throw new ReaderException("Did not read all codewords");