BitMatrixParser.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * BitMatrixParser.cpp
  3. * zxing
  4. *
  5. * Created by Christian Brunschen on 20/05/2008.
  6. * Copyright 2008 ZXing authors All rights reserved.
  7. *
  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
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  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.
  19. */
  20. #include <zxing/qrcode/decoder/BitMatrixParser.h>
  21. #include <zxing/qrcode/decoder/DataMask.h>
  22. namespace zxing {
  23. namespace qrcode {
  24. int BitMatrixParser::copyBit(size_t x, size_t y, int versionBits) {
  25. return bitMatrix_->get(x, y) ? (versionBits << 1) | 0x1 : versionBits << 1;
  26. }
  27. BitMatrixParser::BitMatrixParser(Ref<BitMatrix> bitMatrix) :
  28. bitMatrix_(bitMatrix), parsedVersion_(0), parsedFormatInfo_() {
  29. size_t dimension = bitMatrix->getHeight();
  30. if ((dimension < 21) || (dimension & 0x03) != 1) {
  31. throw ReaderException("Dimension must be 1 mod 4 and >= 21");
  32. }
  33. }
  34. Ref<FormatInformation> BitMatrixParser::readFormatInformation() {
  35. if (parsedFormatInfo_ != 0) {
  36. return parsedFormatInfo_;
  37. }
  38. // Read top-left format info bits
  39. int formatInfoBits1 = 0;
  40. for (int i = 0; i < 6; i++) {
  41. formatInfoBits1 = copyBit(i, 8, formatInfoBits1);
  42. }
  43. // .. and skip a bit in the timing pattern ...
  44. formatInfoBits1 = copyBit(7, 8, formatInfoBits1);
  45. formatInfoBits1 = copyBit(8, 8, formatInfoBits1);
  46. formatInfoBits1 = copyBit(8, 7, formatInfoBits1);
  47. // .. and skip a bit in the timing pattern ...
  48. for (int j = 5; j >= 0; j--) {
  49. formatInfoBits1 = copyBit(8, j, formatInfoBits1);
  50. }
  51. // Read the top-right/bottom-left pattern
  52. int dimension = bitMatrix_->getHeight();
  53. int formatInfoBits2 = 0;
  54. int jMin = dimension - 7;
  55. for (int j = dimension - 1; j >= jMin; j--) {
  56. formatInfoBits2 = copyBit(8, j, formatInfoBits2);
  57. }
  58. for (int i = dimension - 8; i < dimension; i++) {
  59. formatInfoBits2 = copyBit(i, 8, formatInfoBits2);
  60. }
  61. parsedFormatInfo_ = FormatInformation::decodeFormatInformation(formatInfoBits1,formatInfoBits2);
  62. if (parsedFormatInfo_ != 0) {
  63. return parsedFormatInfo_;
  64. }
  65. throw ReaderException("Could not decode format information");
  66. }
  67. Version *BitMatrixParser::readVersion() {
  68. if (parsedVersion_ != 0) {
  69. return parsedVersion_;
  70. }
  71. int dimension = bitMatrix_->getHeight();
  72. int provisionalVersion = (dimension - 17) >> 2;
  73. if (provisionalVersion <= 6) {
  74. return Version::getVersionForNumber(provisionalVersion);
  75. }
  76. // Read top-right version info: 3 wide by 6 tall
  77. int versionBits = 0;
  78. for (int y = 5; y >= 0; y--) {
  79. int xMin = dimension - 11;
  80. for (int x = dimension - 9; x >= xMin; x--) {
  81. versionBits = copyBit(x, y, versionBits);
  82. }
  83. }
  84. parsedVersion_ = Version::decodeVersionInformation(versionBits);
  85. if (parsedVersion_ != 0 && parsedVersion_->getDimensionForVersion() == dimension) {
  86. return parsedVersion_;
  87. }
  88. // Hmm, failed. Try bottom left: 6 wide by 3 tall
  89. versionBits = 0;
  90. for (int x = 5; x >= 0; x--) {
  91. int yMin = dimension - 11;
  92. for (int y = dimension - 9; y >= yMin; y--) {
  93. versionBits = copyBit(x, y, versionBits);
  94. }
  95. }
  96. parsedVersion_ = Version::decodeVersionInformation(versionBits);
  97. if (parsedVersion_ != 0 && parsedVersion_->getDimensionForVersion() == dimension) {
  98. return parsedVersion_;
  99. }
  100. throw ReaderException("Could not decode version");
  101. }
  102. ArrayRef<char> BitMatrixParser::readCodewords() {
  103. Ref<FormatInformation> formatInfo = readFormatInformation();
  104. Version *version = readVersion();
  105. // Get the data mask for the format used in this QR Code. This will exclude
  106. // some bits from reading as we wind through the bit matrix.
  107. DataMask &dataMask = DataMask::forReference((int)formatInfo->getDataMask());
  108. // cout << (int)formatInfo->getDataMask() << endl;
  109. int dimension = bitMatrix_->getHeight();
  110. dataMask.unmaskBitMatrix(*bitMatrix_, dimension);
  111. // cerr << *bitMatrix_ << endl;
  112. // cerr << version->getTotalCodewords() << endl;
  113. Ref<BitMatrix> functionPattern = version->buildFunctionPattern();
  114. // cout << *functionPattern << endl;
  115. bool readingUp = true;
  116. ArrayRef<char> result(version->getTotalCodewords());
  117. int resultOffset = 0;
  118. int currentByte = 0;
  119. int bitsRead = 0;
  120. // Read columns in pairs, from right to left
  121. for (int x = dimension - 1; x > 0; x -= 2) {
  122. if (x == 6) {
  123. // Skip whole column with vertical alignment pattern;
  124. // saves time and makes the other code proceed more cleanly
  125. x--;
  126. }
  127. // Read alternatingly from bottom to top then top to bottom
  128. for (int counter = 0; counter < dimension; counter++) {
  129. int y = readingUp ? dimension - 1 - counter : counter;
  130. for (int col = 0; col < 2; col++) {
  131. // Ignore bits covered by the function pattern
  132. if (!functionPattern->get(x - col, y)) {
  133. // Read a bit
  134. bitsRead++;
  135. currentByte <<= 1;
  136. if (bitMatrix_->get(x - col, y)) {
  137. currentByte |= 1;
  138. }
  139. // If we've made a whole byte, save it off
  140. if (bitsRead == 8) {
  141. result[resultOffset++] = (char)currentByte;
  142. bitsRead = 0;
  143. currentByte = 0;
  144. }
  145. }
  146. }
  147. }
  148. readingUp = !readingUp; // switch directions
  149. }
  150. if (resultOffset != version->getTotalCodewords()) {
  151. throw ReaderException("Did not read all codewords");
  152. }
  153. return result;
  154. }
  155. }
  156. }