/// <summary> Append length info. On success, store the result in "bits".</summary> internal static void appendLengthInfo(int numLetters, int version, Mode mode, BitVector bits) { int numBits = mode.getCharacterCountBits(Version.getVersionForNumber(version)); if (numLetters > ((1 << numBits) - 1)) { throw new WriterException(numLetters + "is bigger than" + ((1 << numBits) - 1)); } bits.appendBits(numLetters, numBits); }
// Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On // success, store the result in "matrix" and return true. //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: static void buildMatrix(com.google.zxing.common.BitArray dataBits, com.google.zxing.qrcode.decoder.ErrorCorrectionLevel ecLevel, com.google.zxing.qrcode.decoder.Version version, int maskPattern, ByteMatrix matrix) throws com.google.zxing.WriterException internal 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); }
/// <summary> Initialize "qrCode" according to "numInputBytes", "ecLevel", and "mode". On success, /// modify "qrCode". /// </summary> private static void initQRCode(int numInputBytes, ErrorCorrectionLevel ecLevel, Mode mode, QRCode qrCode) { qrCode.ECLevel = ecLevel; qrCode.Mode = mode; // In the following comments, we use numbers of Version 7-H. for (int versionNum = 1; versionNum <= 40; versionNum++) { Version version = Version.getVersionForNumber(versionNum); // numBytes = 196 int numBytes = version.TotalCodewords; // getNumECBytes = 130 Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); int numEcBytes = ecBlocks.TotalECCodewords; // getNumRSBlocks = 5 int numRSBlocks = ecBlocks.NumBlocks; // getNumDataBytes = 196 - 130 = 66 int numDataBytes = numBytes - numEcBytes; // We want to choose the smallest version which can contain data of "numInputBytes" + some // extra bits for the header (mode info and length info). The header can be three bytes // (precisely 4 + 16 bits) at most. Hence we do +3 here. if (numDataBytes >= numInputBytes + 3) { // Yay, we found the proper rs block info! qrCode.Version = versionNum; qrCode.NumTotalBytes = numBytes; qrCode.NumDataBytes = numDataBytes; qrCode.NumRSBlocks = numRSBlocks; // getNumECBytes = 196 - 66 = 130 qrCode.NumECBytes = numEcBytes; // matrix width = 21 + 6 * 4 = 45 qrCode.MatrixWidth = version.DimensionForVersion; return; } } throw new WriterException("Cannot find proper rs block info (input data too big?)"); }
protected internal virtual DetectorResult processFinderPatternInfo(FinderPatternInfo info) { FinderPattern topLeft = info.TopLeft; FinderPattern topRight = info.TopRight; FinderPattern bottomLeft = info.BottomLeft; float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft); if (moduleSize < 1.0f) { throw ReaderException.Instance; } int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize); Version provisionalVersion = Version.getProvisionalVersionForDimension(dimension); int modulesBetweenFPCenters = provisionalVersion.DimensionForVersion - 7; AlignmentPattern alignmentPattern = null; // Anything above version 1 has an alignment pattern if (provisionalVersion.AlignmentPatternCenters.Length > 0) { // Guess where a "bottom right" finder pattern would have been float bottomRightX = topRight.X - topLeft.X + bottomLeft.X; float bottomRightY = topRight.Y - topLeft.Y + bottomLeft.Y; // Estimate that alignment pattern is closer by 3 modules // from "bottom right" to known top left location //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" float correctionToTopLeft = 1.0f - 3.0f / (float)modulesBetweenFPCenters; //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" int estAlignmentX = (int)(topLeft.X + correctionToTopLeft * (bottomRightX - topLeft.X)); //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" int estAlignmentY = (int)(topLeft.Y + correctionToTopLeft * (bottomRightY - topLeft.Y)); // Kind of arbitrary -- expand search radius before giving up for (int i = 4; i <= 16; i <<= 1) { try { //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i); break; } catch (ReaderException re) { // try next round } } // If we didn't find alignment pattern... well try anyway without it } PerspectiveTransform transform = createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension); BitMatrix bits = sampleGrid(image, transform, dimension); ResultPoint[] points; if (alignmentPattern == null) { points = new ResultPoint[] { bottomLeft, topLeft, topRight }; } else { points = new ResultPoint[] { bottomLeft, topLeft, topRight, alignmentPattern }; } return(new DetectorResult(bits, points)); }
// Embed position adjustment patterns if need be. 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.get(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); } } } }
// 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. //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: static void maybeEmbedVersionInfo(com.google.zxing.qrcode.decoder.Version version, ByteMatrix matrix) throws com.google.zxing.WriterException internal 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. bool bit = versionInfoBits.get(bitIndex); bitIndex--; // Left bottom corner. matrix.set(i, matrix.Height - 11 + j, bit); // Right bottom corner. matrix.set(matrix.Height - 11 + j, i, bit); } } }
// 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. //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: static void makeVersionInfoBits(com.google.zxing.qrcode.decoder.Version version, com.google.zxing.common.BitArray bits) throws com.google.zxing.WriterException internal 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); } }
// 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 //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: static void embedBasicPatterns(com.google.zxing.qrcode.decoder.Version version, ByteMatrix matrix) throws com.google.zxing.WriterException internal 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); }