/// <summary> /// Make bit vector of version information. On success, store the result in "bits" and return true. /// See 8.10 of JISX0510:2004 (p.45) for details. /// </summary> /// <param name="version">The version.</param> /// <param name="bits">The bits.</param> public static void makeVersionInfoBits(Version version, BitArray bits) { bits.appendBits(version.VersionNumber, 6); int bchCode = calculateBCHCode(version.VersionNumber, VERSION_INFO_POLY); bits.appendBits(bchCode, 12); if (bits.Size != 18) { // Just in case. throw new WriterException("should not happen but we got: " + bits.Size); } }
/// <summary> /// Embed position adjustment patterns if need be. /// </summary> /// <param name="version">The version.</param> /// <param name="matrix">The matrix.</param> private static void maybeEmbedPositionAdjustmentPatterns(Version version, ByteMatrix matrix) { if (version.VersionNumber < 2) { // The patterns appear if version >= 2 return; } int index = version.VersionNumber - 1; int[] coordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index]; int numCoordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index].Length; for (int i = 0; i < numCoordinates; ++i) { for (int j = 0; j < numCoordinates; ++j) { int y = coordinates[i]; int x = coordinates[j]; if (x == -1 || y == -1) { continue; } // If the cell is unset, we embed the position adjustment pattern here. if (isEmpty(matrix[x, y])) { // -2 is necessary since the x/y coordinates point to the center of the pattern, not the // left top corner. embedPositionAdjustmentPattern(x - 2, y - 2, matrix); } } } }
/// <summary> /// Embed version information if need be. On success, modify the matrix and return true. /// See 8.10 of JISX0510:2004 (p.47) for how to embed version information. /// </summary> /// <param name="version">The version.</param> /// <param name="matrix">The matrix.</param> public static void maybeEmbedVersionInfo(Version version, ByteMatrix matrix) { if (version.VersionNumber < 7) { // Version info is necessary if version >= 7. return; // Don't need version info. } BitArray versionInfoBits = new BitArray(); makeVersionInfoBits(version, versionInfoBits); int bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0. for (int i = 0; i < 6; ++i) { for (int j = 0; j < 3; ++j) { // Place bits in LSB (least significant bit) to MSB order. var bit = versionInfoBits[bitIndex] ? 1 : 0; bitIndex--; // Left bottom corner. matrix[i, matrix.Height - 11 + j] = bit; // Right bottom corner. matrix[matrix.Height - 11 + j, i] = bit; } } }
/// <summary> /// Embed basic patterns. On success, modify the matrix and return true. /// The basic patterns are: /// - Position detection patterns /// - Timing patterns /// - Dark dot at the left bottom corner /// - Position adjustment patterns, if need be /// </summary> /// <param name="version">The version.</param> /// <param name="matrix">The matrix.</param> public static void embedBasicPatterns(Version version, ByteMatrix matrix) { // Let's get started with embedding big squares at corners. embedPositionDetectionPatternsAndSeparators(matrix); // Then, embed the dark dot at the left bottom corner. embedDarkDotAtLeftBottomCorner(matrix); // Position adjustment patterns appear if version >= 2. maybeEmbedPositionAdjustmentPatterns(version, matrix); // Timing patterns should be embedded after position adj. patterns. embedTimingPatterns(matrix); }
/// <summary> /// Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On /// success, store the result in "matrix" and return true. /// </summary> /// <param name="dataBits">The data bits.</param> /// <param name="ecLevel">The ec level.</param> /// <param name="version">The version.</param> /// <param name="maskPattern">The mask pattern.</param> /// <param name="matrix">The matrix.</param> public static void buildMatrix(BitArray dataBits, ErrorCorrectionLevel ecLevel, Version version, int maskPattern, ByteMatrix matrix) { clearMatrix(matrix); embedBasicPatterns(version, matrix); // Type information appear with any version. embedTypeInfo(ecLevel, maskPattern, matrix); // Version info appear if version >= 7. maybeEmbedVersionInfo(version, matrix); // Data should be embedded at end. embedDataBits(dataBits, maskPattern, matrix); }
/** * Prepare the parser for a mirrored operation. * This flag has effect only on the {@link #readFormatInformation()} and the * {@link #readVersion()}. Before proceeding with {@link #readCodewords()} the * {@link #mirror()} method should be called. * * @param mirror Whether to read version and format information mirrored. */ internal void setMirror(bool mirror) { parsedVersion = null; parsedFormatInfo = null; mirrored = mirror; }
/// <summary> <p>Reads version information from one of its two locations within the QR Code.</p> /// /// </summary> /// <returns> {@link Version} encapsulating the QR Code's version /// </returns> /// <throws> ReaderException if both version information locations cannot be parsed as </throws> /// <summary> the valid encoding of version information /// </summary> internal Version readVersion() { if (parsedVersion != null) { return parsedVersion; } int dimension = bitMatrix.Height; int provisionalVersion = (dimension - 17) >> 2; if (provisionalVersion <= 6) { return Version.getVersionForNumber(provisionalVersion); } // Read top-right version info: 3 wide by 6 tall int versionBits = 0; int ijMin = dimension - 11; for (int j = 5; j >= 0; j--) { for (int i = dimension - 9; i >= ijMin; i--) { versionBits = copyBit(i, j, versionBits); } } parsedVersion = Version.decodeVersionInformation(versionBits); if (parsedVersion != null && parsedVersion.DimensionForVersion == dimension) { return parsedVersion; } // Hmm, failed. Try bottom left: 6 wide by 3 tall versionBits = 0; for (int i = 5; i >= 0; i--) { for (int j = dimension - 9; j >= ijMin; j--) { versionBits = copyBit(i, j, versionBits); } } parsedVersion = Version.decodeVersionInformation(versionBits); if (parsedVersion != null && parsedVersion.DimensionForVersion == dimension) { return parsedVersion; } return null; }