not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
5.4 KiB

  1. /*
  2. Ported to JavaScript by Lazar Laszlo 2011
  3. lazarsoft@gmail.com, www.lazarsoft.info
  4. */
  5. /*
  6. *
  7. * Copyright 2007 ZXing authors
  8. *
  9. * Licensed under the Apache License, Version 2.0 (the "License");
  10. * you may not use this file except in compliance with the License.
  11. * You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing, software
  16. * distributed under the License is distributed on an "AS IS" BASIS,
  17. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. * See the License for the specific language governing permissions and
  19. * limitations under the License.
  20. */
  21. function BitMatrixParser(bitMatrix)
  22. {
  23. var dimension = bitMatrix.Dimension;
  24. if (dimension < 21 || (dimension & 0x03) != 1)
  25. {
  26. throw "Error BitMatrixParser";
  27. }
  28. this.bitMatrix = bitMatrix;
  29. this.parsedVersion = null;
  30. this.parsedFormatInfo = null;
  31. this.copyBit=function( i, j, versionBits)
  32. {
  33. return this.bitMatrix.get_Renamed(i, j)?(versionBits << 1) | 0x1:versionBits << 1;
  34. }
  35. this.readFormatInformation=function()
  36. {
  37. if (this.parsedFormatInfo != null)
  38. {
  39. return this.parsedFormatInfo;
  40. }
  41. // Read top-left format info bits
  42. var formatInfoBits = 0;
  43. for (var i = 0; i < 6; i++)
  44. {
  45. formatInfoBits = this.copyBit(i, 8, formatInfoBits);
  46. }
  47. // .. and skip a bit in the timing pattern ...
  48. formatInfoBits = this.copyBit(7, 8, formatInfoBits);
  49. formatInfoBits = this.copyBit(8, 8, formatInfoBits);
  50. formatInfoBits = this.copyBit(8, 7, formatInfoBits);
  51. // .. and skip a bit in the timing pattern ...
  52. for (var j = 5; j >= 0; j--)
  53. {
  54. formatInfoBits = this.copyBit(8, j, formatInfoBits);
  55. }
  56. this.parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits);
  57. if (this.parsedFormatInfo != null)
  58. {
  59. return this.parsedFormatInfo;
  60. }
  61. // Hmm, failed. Try the top-right/bottom-left pattern
  62. var dimension = this.bitMatrix.Dimension;
  63. formatInfoBits = 0;
  64. var iMin = dimension - 8;
  65. for (var i = dimension - 1; i >= iMin; i--)
  66. {
  67. formatInfoBits = this.copyBit(i, 8, formatInfoBits);
  68. }
  69. for (var j = dimension - 7; j < dimension; j++)
  70. {
  71. formatInfoBits = this.copyBit(8, j, formatInfoBits);
  72. }
  73. this.parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits);
  74. if (this.parsedFormatInfo != null)
  75. {
  76. return this.parsedFormatInfo;
  77. }
  78. throw "Error readFormatInformation";
  79. }
  80. this.readVersion=function()
  81. {
  82. if (this.parsedVersion != null)
  83. {
  84. return this.parsedVersion;
  85. }
  86. var dimension = this.bitMatrix.Dimension;
  87. var provisionalVersion = (dimension - 17) >> 2;
  88. if (provisionalVersion <= 6)
  89. {
  90. return Version.getVersionForNumber(provisionalVersion);
  91. }
  92. // Read top-right version info: 3 wide by 6 tall
  93. var versionBits = 0;
  94. var ijMin = dimension - 11;
  95. for (var j = 5; j >= 0; j--)
  96. {
  97. for (var i = dimension - 9; i >= ijMin; i--)
  98. {
  99. versionBits = this.copyBit(i, j, versionBits);
  100. }
  101. }
  102. this.parsedVersion = Version.decodeVersionInformation(versionBits);
  103. if (this.parsedVersion != null && this.parsedVersion.DimensionForVersion == dimension)
  104. {
  105. return this.parsedVersion;
  106. }
  107. // Hmm, failed. Try bottom left: 6 wide by 3 tall
  108. versionBits = 0;
  109. for (var i = 5; i >= 0; i--)
  110. {
  111. for (var j = dimension - 9; j >= ijMin; j--)
  112. {
  113. versionBits = this.copyBit(i, j, versionBits);
  114. }
  115. }
  116. this.parsedVersion = Version.decodeVersionInformation(versionBits);
  117. if (this.parsedVersion != null && this.parsedVersion.DimensionForVersion == dimension)
  118. {
  119. return this.parsedVersion;
  120. }
  121. throw "Error readVersion";
  122. }
  123. this.readCodewords=function()
  124. {
  125. var formatInfo = this.readFormatInformation();
  126. var version = this.readVersion();
  127. // Get the data mask for the format used in this QR Code. This will exclude
  128. // some bits from reading as we wind through the bit matrix.
  129. var dataMask = DataMask.forReference( formatInfo.DataMask);
  130. var dimension = this.bitMatrix.Dimension;
  131. dataMask.unmaskBitMatrix(this.bitMatrix, dimension);
  132. var functionPattern = version.buildFunctionPattern();
  133. var readingUp = true;
  134. var result = new Array(version.TotalCodewords);
  135. var resultOffset = 0;
  136. var currentByte = 0;
  137. var bitsRead = 0;
  138. // Read columns in pairs, from right to left
  139. for (var j = dimension - 1; j > 0; j -= 2)
  140. {
  141. if (j == 6)
  142. {
  143. // Skip whole column with vertical alignment pattern;
  144. // saves time and makes the other code proceed more cleanly
  145. j--;
  146. }
  147. // Read alternatingly from bottom to top then top to bottom
  148. for (var count = 0; count < dimension; count++)
  149. {
  150. var i = readingUp?dimension - 1 - count:count;
  151. for (var col = 0; col < 2; col++)
  152. {
  153. // Ignore bits covered by the function pattern
  154. if (!functionPattern.get_Renamed(j - col, i))
  155. {
  156. // Read a bit
  157. bitsRead++;
  158. currentByte <<= 1;
  159. if (this.bitMatrix.get_Renamed(j - col, i))
  160. {
  161. currentByte |= 1;
  162. }
  163. // If we've made a whole byte, save it off
  164. if (bitsRead == 8)
  165. {
  166. result[resultOffset++] = currentByte;
  167. bitsRead = 0;
  168. currentByte = 0;
  169. }
  170. }
  171. }
  172. }
  173. readingUp ^= true; // readingUp = !readingUp; // switch directions
  174. }
  175. if (resultOffset != version.TotalCodewords)
  176. {
  177. throw "Error readCodewords";
  178. }
  179. return result;
  180. }
  181. }