// The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details. // Basically it applies four rules and summate all penalties. private static int calculateMaskPenalty(ByteMatrix matrix) { return(MaskUtil.applyMaskPenaltyRule1(matrix)); }
/// <summary> /// /// </summary> /// <param name="content"></param> /// <param name="ecLevel"></param> /// <param name="hints"></param> /// <param name="qrCode"></param> public static void encode(System.String content, ErrorCorrectionLevel ecLevel, IDictionary <EncodeHintType, object> hints, MicroQRCode qrCode, int versionNum) { if (versionNum < 1 || versionNum > 4) { throw new ArgumentOutOfRangeException("versionNum", "versionNum [1, 4]"); } System.String encoding = null; if (hints.ContainsKey(EncodeHintType.CHARACTER_SET)) { encoding = hints == null ? null : (System.String)hints[EncodeHintType.CHARACTER_SET]; if (encoding == null) { encoding = DEFAULT_BYTE_MODE_ENCODING; } } // Step 1: Choose the mode (encoding). Mode mode = chooseMode(content, encoding); // Step 2: Append "bytes" into "dataBits" in appropriate encoding. BitVector dataBits = new BitVector(); appendBytes(content, mode, dataBits, encoding, versionNum); // Step 3: Initialize QR code that can contain "dataBits". int numInputBytes = dataBits.sizeInBytes(); initQRCode(numInputBytes, ecLevel, mode, qrCode, versionNum); // Step 4: Build another bit vector that contains header and data. BitVector headerAndDataBits = new BitVector(); //INFO ECB+Mode+Length+Data[+terminate] // Step 4.5: Append ECI message if applicable appendModeInfo(mode, headerAndDataBits, versionNum); int numLetters = mode.Equals(Mode.BYTE) ? dataBits.sizeInBytes() : content.Length; appendLengthInfo(numLetters, qrCode.Version, mode, headerAndDataBits); headerAndDataBits.appendBitVector(dataBits); // Step 5: Terminate the bits properly. terminateBits(qrCode.NumDataBytes, headerAndDataBits, versionNum); // Step 6: Interleave data bits with error correction code. BitVector finalBits = new BitVector(); interleaveWithECBytes(headerAndDataBits, versionNum, qrCode.NumTotalBytes, qrCode.NumDataBytes, qrCode.NumRSBlocks, finalBits); // Step 7: Choose the mask pattern and set to "qrCode". ByteMatrix matrix = new ByteMatrix(qrCode.MatrixWidth, qrCode.MatrixWidth); qrCode.MaskPattern = chooseMaskPattern(finalBits, qrCode.ECLevel, qrCode.Version, matrix); // Step 8. Build the matrix and set it to "qrCode". MatrixUtil.buildMatrix(finalBits, qrCode.ECLevel, qrCode.Version, qrCode.MaskPattern, matrix); qrCode.Matrix = matrix; //var decoder = new com.google.zxing.microqrcode.decoder.Decoder(); //var res = decoder.decode(com.google.zxing.common.BitMatrix.FromByteMatrix(matrix)); //Console.WriteLine(res.Text); // Step 9. Make sure we have a valid QR Code. if (!qrCode.Valid) { throw new WriterException("Invalid QR code: " + qrCode.ToString()); } }
private static int chooseMaskPattern(BitVector bits, ErrorCorrectionLevel ecLevel, int version, ByteMatrix matrix) { int maxPenalty = System.Int32.MinValue; // highest penalty is better. int bestMaskPattern = -1; // We try all mask patterns to choose the best one. for (int maskPattern = 0; maskPattern < MicroQRCode.NUM_MASK_PATTERNS; maskPattern++) { MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix); int penalty = calculateMaskPenalty(matrix); if (penalty > maxPenalty) { maxPenalty = penalty; bestMaskPattern = maskPattern; } } return(bestMaskPattern); }