private FormatInformation(int formatInfo) { // Bits 3,4 errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03); // Bottom 3 bits dataMask = (sbyte) (formatInfo & 0x07); }
public static VersionTableTestProperties GetVersionInfo(int versionNum, ErrorCorrectionLevel level) { Version version = VersionTable.GetVersionByNum(versionNum); int totalNumCodewords = version.TotalCodewords; ErrorCorrectionBlocks ecBlocks = version.GetECBlocksByLevel(level); int numECCodewords = ecBlocks.NumErrorCorrectionCodewards; string ecBlockString = ErrorCorrectionBlocksToString(ecBlocks); return new VersionTableTestProperties(versionNum, totalNumCodewords, level, numECCodewords, ecBlockString); }
public QRCode() { mode = null; ecLevel = null; version = -1; matrixWidth = -1; maskPattern = -1; numTotalBytes = -1; numDataBytes = -1; numECBytes = -1; numRSBlocks = -1; matrix = null; }
internal static ErrorCorrectionLevelInternal ToInternal(ErrorCorrectionLevel level) { switch (level) { case ErrorCorrectionLevel.L: return ErrorCorrectionLevelInternal.L; case ErrorCorrectionLevel.M: return ErrorCorrectionLevelInternal.M; case ErrorCorrectionLevel.Q: return ErrorCorrectionLevelInternal.Q; case ErrorCorrectionLevel.H: return ErrorCorrectionLevelInternal.H; } throw new NotSupportedException(string.Format("Error correction level {0} is not supported.", level)); }
/// <summary> /// Combine Gma.QrCodeNet.Encoding input recognition method and version control method /// with legacy code. To create expected answer. /// This is base on assume Gma.QrCodeNet.Encoding input recognition and version control sometime /// give different result as legacy code. /// </summary> /// <param name="content"></param> /// <returns></returns> internal static BitVector DataEncodeUsingReferenceImplementation(string content, ErrorCorrectionLevel ecLevel, out QRCodeInternal qrInternal) { if(string.IsNullOrEmpty(content)) throw new ArgumentException("input string content can not be null or empty"); //Choose mode RecognitionStruct recognitionResult = InputRecognise.Recognise(content); string encodingName = recognitionResult.EncodingName; Mode mode = ConvertMode(recognitionResult.Mode); //append byte to databits BitVector dataBits = new BitVector(); EncoderInternal.appendBytes(content, mode, dataBits, encodingName); int dataBitsLength = dataBits.size(); VersionControlStruct vcStruct = VersionControl.InitialSetup(dataBitsLength, recognitionResult.Mode, ecLevel, recognitionResult.EncodingName); //ECI BitVector headerAndDataBits = new BitVector(); string defaultByteMode = "iso-8859-1"; if (mode == Mode.BYTE && !defaultByteMode.Equals(encodingName)) { CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encodingName); if (eci != null) { EncoderInternal.appendECI(eci, headerAndDataBits); } } //Mode EncoderInternal.appendModeInfo(mode, headerAndDataBits); //Char info int numLetters = mode.Equals(Mode.BYTE)?dataBits.sizeInBytes():content.Length; EncoderInternal.appendLengthInfo(numLetters, vcStruct.VersionDetail.Version, mode, headerAndDataBits); //Combine with dataBits headerAndDataBits.appendBitVector(dataBits); // Terminate the bits properly. EncoderInternal.terminateBits(vcStruct.VersionDetail.NumDataBytes, headerAndDataBits); qrInternal = new QRCodeInternal(); qrInternal.Version = vcStruct.VersionDetail.Version; qrInternal.MatrixWidth = vcStruct.VersionDetail.MatrixWidth; qrInternal.EcLevelInternal = ErrorCorrectionLevelConverter.ToInternal(ecLevel); qrInternal.NumTotalBytes = vcStruct.VersionDetail.NumTotalBytes; qrInternal.NumDataBytes = vcStruct.VersionDetail.NumDataBytes; qrInternal.NumRSBlocks = vcStruct.VersionDetail.NumECBlocks; return headerAndDataBits; }
private static ErrorCorrectionLevelInternal ECLevelConvert(ErrorCorrectionLevel levelValue) { switch(levelValue) { case ErrorCorrectionLevel.L: return ErrorCorrectionLevelInternal.L; case ErrorCorrectionLevel.M: return ErrorCorrectionLevelInternal.M; case ErrorCorrectionLevel.Q: return ErrorCorrectionLevelInternal.Q; case ErrorCorrectionLevel.H: return ErrorCorrectionLevelInternal.H; default: throw new InvalidOperationException(string.Format("ErrorCorrection level {0} not correct.", levelValue)); } }
public static BitMatrix Encode(string content, ErrorCorrectionLevel ecLevel) { QRCodeInternal qrInternal; BitVector headerAndDataBits = DataEncodeUsingReferenceImplementation(content, ecLevel, out qrInternal); // Step 6: Interleave data bits with error correction code. BitVector finalBits = new BitVector(); EncoderInternal.interleaveWithECBytes(headerAndDataBits, qrInternal.NumTotalBytes, qrInternal.NumDataBytes, qrInternal.NumRSBlocks, finalBits); // Step 7: Choose the mask pattern and set to "QRCodeInternal". ByteMatrix matrix = new ByteMatrix(qrInternal.MatrixWidth, qrInternal.MatrixWidth); int MaskPattern = EncoderInternal.chooseMaskPattern(finalBits, qrInternal.EcLevelInternal, qrInternal.Version, matrix); // Step 8. Build the matrix and set it to "QRCodeInternal". MatrixUtil.buildMatrix(finalBits, qrInternal.EcLevelInternal, qrInternal.Version, MaskPattern, matrix); return matrix.ToBitMatrix(); }
/** * <p>Decodes a QR Code represented as a {@link BitMatrix}. A 1 or "true" is taken to mean a black module.</p> * * @param bits booleans representing white/black QR Code modules * @return text and bytes encoded within the QR Code * @throws ReaderException if the QR Code cannot be decoded */ public DecoderResult decode(BitMatrix bits) { try{ // Construct a parser and read version, error-correction level BitMatrixParser parser = new BitMatrixParser(bits); Version version = parser.readVersion(); ErrorCorrectionLevel ecLevel = parser.readFormatInformation().getErrorCorrectionLevel(); // Read codewords sbyte[] codewords = parser.readCodewords(); // Separate into data blocks DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version, ecLevel); // Count total number of data bytes int totalBytes = 0; for (int i = 0; i < dataBlocks.Length; i++) { totalBytes += dataBlocks[i].NumDataCodewords; } sbyte[] resultBytes = new sbyte[totalBytes]; int resultOffset = 0; // Error-correct and copy data blocks together into a stream of bytes for (int j = 0; j < dataBlocks.Length; j++) { DataBlock dataBlock = dataBlocks[j]; sbyte[] codewordBytes = dataBlock.Codewords; int numDataCodewords = dataBlock.NumDataCodewords; correctErrors(codewordBytes, numDataCodewords); for (int i = 0; i < numDataCodewords; i++) { resultBytes[resultOffset++] = codewordBytes[i]; } } // Decode the contents of that stream of bytes string sResult = DecodedBitStreamParser.decode(resultBytes, version); return(new DecoderResult(resultBytes, sResult, null)); }catch (Exception e) { throw new ReaderException(e.Message); } }
/// <summary> /// <p>Decodes a QR Code represented as a <seealso cref="BitMatrix"/>. A 1 or "true" is taken to mean a black module.</p> /// </summary> /// <param name="bits"> booleans representing white/black QR Code modules </param> /// <returns> text and bytes encoded within the QR Code </returns> /// <exception cref="FormatException"> if the QR Code cannot be decoded </exception> /// <exception cref="ChecksumException"> if error correction fails </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public com.google.zxing.common.DecoderResult decode(com.google.zxing.common.BitMatrix bits, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.FormatException, com.google.zxing.ChecksumException public DecoderResult decode(BitMatrix bits, IDictionary <DecodeHintType, object> hints) { // Construct a parser and read version, error-correction level BitMatrixParser parser = new BitMatrixParser(bits); Version version = parser.readVersion(); ErrorCorrectionLevel ecLevel = parser.readFormatInformation().ErrorCorrectionLevel; // Read codewords sbyte[] codewords = parser.readCodewords(); // Separate into data blocks DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version, ecLevel); // Count total number of data bytes int totalBytes = 0; foreach (DataBlock dataBlock in dataBlocks) { totalBytes += dataBlock.NumDataCodewords; } sbyte[] resultBytes = new sbyte[totalBytes]; int resultOffset = 0; // Error-correct and copy data blocks together into a stream of bytes foreach (DataBlock dataBlock in dataBlocks) { sbyte[] codewordBytes = dataBlock.Codewords; int numDataCodewords = dataBlock.NumDataCodewords; correctErrors(codewordBytes, numDataCodewords); for (int i = 0; i < numDataCodewords; i++) { resultBytes[resultOffset++] = codewordBytes[i]; } } // Decode the contents of that stream of bytes return(DecodedBitStreamParser.decode(resultBytes, version, ecLevel, hints)); }
/// <summary> <p>When QR Codes use multiple data blocks, they are actually interleave the bytes of each of them. /// That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This /// method will separate the data into original blocks.</p> /// /// </summary> /// <param name="rawCodewords">bytes as read directly from the QR Code /// </param> /// <param name="version">version of the QR Code /// </param> /// <param name="ecLevel">error-correction level of the QR Code /// </param> /// <returns> {@link DataBlock}s containing original bytes, "de-interleaved" from representation in the /// QR Code /// </returns> internal static DataBlock[] getDataBlocks(sbyte[] rawCodewords, Version version, ErrorCorrectionLevel ecLevel) { // Figure out the number and size of data blocks used by this version and // error correction level Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); // First count the total number of data blocks int totalBlocks = 0; Version.ECB[] ecBlockArray = ecBlocks.getECBlocks(); for (int i = 0; i < ecBlockArray.Length; i++) { totalBlocks += ecBlockArray[i].getCount(); } // Now establish DataBlocks of the appropriate size and number of data codewords DataBlock[] result = new DataBlock[totalBlocks]; int numResultBlocks = 0; for (int j = 0; j < ecBlockArray.Length; j++) { Version.ECB ecBlock = ecBlockArray[j]; for (int i = 0; i < ecBlock.getCount(); i++) { int numDataCodewords = ecBlock.getDataCodewords(); int numBlockCodewords = ecBlocks.getTotalECCodewords() + numDataCodewords; result[numResultBlocks++] = new DataBlock(numDataCodewords, new sbyte[numBlockCodewords]); } } // All blocks have the same amount of data, except that the last n // (where n may be 0) have 1 more byte. Figure out where these start. int shorterBlocksTotalCodewords = result[0].codewords.Length; int longerBlocksStartAt = result.Length - 1; while (longerBlocksStartAt >= 0) { int numCodewords = result[longerBlocksStartAt].codewords.Length; if (numCodewords == shorterBlocksTotalCodewords) { break; } if (numCodewords != shorterBlocksTotalCodewords + 1) { throw new System.SystemException("Data block sizes differ by more than 1"); } longerBlocksStartAt--; } longerBlocksStartAt++; int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getTotalECCodewords(); // The last elements of result may be 1 element longer; // first fill out as many elements as all of them have int rawCodewordsOffset = 0; for (int i = 0; i < shorterBlocksNumDataCodewords; i++) { for (int j = 0; j < numResultBlocks; j++) { result[j].codewords[i] = rawCodewords[rawCodewordsOffset++]; } } // Fill out the last data block in the longer ones for (int j = longerBlocksStartAt; j < numResultBlocks; j++) { result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++]; } // Now add in error correction blocks int max = result[0].codewords.Length; for (int i = shorterBlocksNumDataCodewords; i < max; i++) { for (int j = 0; j < numResultBlocks; j++) { int iOffset = j < longerBlocksStartAt ? i : i + 1; result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++]; } } if (rawCodewordsOffset != rawCodewords.Length) { throw new System.SystemException(); } return result; }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: static com.google.zxing.common.DecoderResult decode(byte[] bytes, Version version, ErrorCorrectionLevel ecLevel, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.FormatException internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel, IDictionary <DecodeHintType, object> hints) { BitSource bits = new BitSource(bytes); StringBuilder result = new StringBuilder(50); IList <sbyte[]> byteSegments = new List <sbyte[]>(1); try { CharacterSetECI currentCharacterSetECI = null; bool fc1InEffect = false; Mode mode; do { // While still another segment to read... if (bits.available() < 4) { // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here mode = Mode.TERMINATOR; } else { mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits } if (mode != Mode.TERMINATOR) { if (mode == Mode.FNC1_FIRST_POSITION || mode == Mode.FNC1_SECOND_POSITION) { // We do little with FNC1 except alter the parsed result a bit according to the spec fc1InEffect = true; } else if (mode == Mode.STRUCTURED_APPEND) { if (bits.available() < 16) { throw FormatException.FormatInstance; } // not really supported; all we do is ignore it // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue bits.readBits(16); } else if (mode == Mode.ECI) { // Count doesn't apply to ECI int value = parseECIValue(bits); currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value); if (currentCharacterSetECI == null) { throw FormatException.FormatInstance; } } else { // First handle Hanzi mode which does not start with character count if (mode == Mode.HANZI) { //chinese mode contains a sub set indicator right after mode indicator int subset = bits.readBits(4); int countHanzi = bits.readBits(mode.getCharacterCountBits(version)); if (subset == GB2312_SUBSET) { decodeHanziSegment(bits, result, countHanzi); } } else { // "Normal" QR code modes: // How many characters will follow, encoded in this mode? int count = bits.readBits(mode.getCharacterCountBits(version)); if (mode == Mode.NUMERIC) { decodeNumericSegment(bits, result, count); } else if (mode == Mode.ALPHANUMERIC) { decodeAlphanumericSegment(bits, result, count, fc1InEffect); } else if (mode == Mode.BYTE) { decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints); } else if (mode == Mode.KANJI) { decodeKanjiSegment(bits, result, count); } else { throw FormatException.FormatInstance; } } } } } while (mode != Mode.TERMINATOR); } catch (System.ArgumentException iae) { // from readBits() calls throw FormatException.FormatInstance; } return(new DecoderResult(bytes, result.ToString(), byteSegments.Count == 0 ? null : byteSegments, ecLevel == null ? null : ecLevel.ToString())); }
public void setECLevel(ErrorCorrectionLevel value) { ecLevel = value; }
// Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On // success, store the result in "matrix" and return true. public static void buildMatrix(BitVector dataBits, ErrorCorrectionLevel ecLevel, int version,int maskPattern, ByteMatrix matrix) { try{ 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); }catch(Exception e){ throw new WriterException(e.Message); } }
/// <summary> <p>When QR Codes use multiple data blocks, they are actually interleaved. /// That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This /// method will separate the data into original blocks.</p> /// /// </summary> /// <param name="rawCodewords">bytes as read directly from the QR Code /// </param> /// <param name="version">version of the QR Code /// </param> /// <param name="ecLevel">error-correction level of the QR Code /// </param> /// <returns> {@link DataBlock}s containing original bytes, "de-interleaved" from representation in the /// QR Code /// </returns> internal static DataBlock[] getDataBlocks(sbyte[] rawCodewords, Version version, ErrorCorrectionLevel ecLevel) { if (rawCodewords.Length != version.TotalCodewords) { throw new System.ArgumentException(); } // Figure out the number and size of data blocks used by this version and // error correction level Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); // First count the total number of data blocks int totalBlocks = 0; Version.ECB[] ecBlockArray = ecBlocks.getECBlocks(); for (int i = 0; i < ecBlockArray.Length; i++) { totalBlocks += ecBlockArray[i].Count; } // Now establish DataBlocks of the appropriate size and number of data codewords DataBlock[] result = new DataBlock[totalBlocks]; int numResultBlocks = 0; for (int j = 0; j < ecBlockArray.Length; j++) { Version.ECB ecBlock = ecBlockArray[j]; for (int i = 0; i < ecBlock.Count; i++) { int numDataCodewords = ecBlock.DataCodewords; int numBlockCodewords = ecBlocks.ECCodewordsPerBlock + numDataCodewords; result[numResultBlocks++] = new DataBlock(numDataCodewords, new sbyte[numBlockCodewords]); } } // All blocks have the same amount of data, except that the last n // (where n may be 0) have 1 more byte. Figure out where these start. int shorterBlocksTotalCodewords = result[0].codewords.Length; int longerBlocksStartAt = result.Length - 1; while (longerBlocksStartAt >= 0) { int numCodewords = result[longerBlocksStartAt].codewords.Length; if (numCodewords == shorterBlocksTotalCodewords) { break; } longerBlocksStartAt--; } longerBlocksStartAt++; int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.ECCodewordsPerBlock; // The last elements of result may be 1 element longer; // first fill out as many elements as all of them have int rawCodewordsOffset = 0; for (int i = 0; i < shorterBlocksNumDataCodewords; i++) { for (int j = 0; j < numResultBlocks; j++) { result[j].codewords[i] = rawCodewords[rawCodewordsOffset++]; } } // Fill out the last data block in the longer ones for (int j = longerBlocksStartAt; j < numResultBlocks; j++) { result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++]; } // Now add in error correction blocks int max = result[0].codewords.Length; for (int i = shorterBlocksNumDataCodewords; i < max; i++) { for (int j = 0; j < numResultBlocks; j++) { int iOffset = j < longerBlocksStartAt?i:i + 1; result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++]; } } return(result); }
// Embed type information. On success, modify the matrix. public static void embedTypeInfo(ErrorCorrectionLevel ecLevel, int maskPattern, ByteMatrix matrix) { BitVector typeInfoBits = new BitVector(); makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits); for (int i = 0; i < typeInfoBits.size(); ++i) { // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in // "typeInfoBits". int bit = typeInfoBits.at(typeInfoBits.size() - 1 - i); // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46). int x1 = TYPE_INFO_COORDINATES[i][0]; int y1 = TYPE_INFO_COORDINATES[i][1]; matrix.set(y1, x1, bit); if (i < 8) { // Right top corner. int x2 = matrix.width() - i - 1; int y2 = 8; matrix.set(y2, x2, bit); } else { // Left bottom corner. int x2 = 8; int y2 = matrix.height() - 7 + (i - 8); matrix.set(y2, x2, bit); } } }
// Make bit vector of type information. On success, store the result in "bits" and return true. // Encode error correction level and mask pattern. See 8.9 of // JISX0510:2004 (p.45) for details. public static void makeTypeInfoBits(ErrorCorrectionLevel ecLevel, int maskPattern, BitVector bits) { if (!QRCode.isValidMaskPattern(maskPattern)) { throw new WriterException("Invalid mask pattern"); } int typeInfo = (ecLevel.getBits() << 3) | maskPattern; bits.appendBits(typeInfo, 5); int bchCode = calculateBCHCode(typeInfo, TYPE_INFO_POLY); bits.appendBits(bchCode, 10); BitVector maskBits = new BitVector(); maskBits.appendBits(TYPE_INFO_MASK_PATTERN, 15); bits.xor(maskBits); if (bits.size() != 15) { // Just in case. throw new WriterException("should not happen but we got: " + bits.size()); } }
public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) { return ecBlocks[ecLevel.ordinal()]; }
private FormatInformation(int formatInfo) { //ISO/IEC 18004:2006(E) 6.9 Format information //Symbol number 0: 000 //Data mask pattern reference: 11 //Data bits (symbol number, data mask pattern reference): 00011 var p = SYMBOL_NUMBERS_INFO[(formatInfo >> 2) & 0x07]; errorCorrectionLevel = p.Value; version = Version.getVersionForNumber(p.Key); dataMask = (sbyte)(formatInfo & 0x03); }
private static int chooseMaskPattern(BitVector bits, ErrorCorrectionLevel ecLevel, int version,ByteMatrix matrix) { try{ int minPenalty = int.MaxValue; // Lower penalty is better. int bestMaskPattern = -1; // We try all mask patterns to choose the best one. for (int maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) { MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix); int penalty = calculateMaskPenalty(matrix); if (penalty < minPenalty) { minPenalty = penalty; bestMaskPattern = maskPattern; } } return bestMaskPattern; }catch(Exception e){ throw new ReaderException(e.Message); } }
// Encode "bytes" with the error correction level "getECLevel". The encoding mode will be chosen // internally by chooseMode(). On success, store the result in "qrCode" and return true. // We recommend you to use QRCode.EC_LEVEL_L (the lowest level) for // "getECLevel" since our primary use is to show QR code on desktop screens. We don't need very // strong error correction for this purpose. // // Note that there is no way to encode bytes in MODE_KANJI. We might want to add EncodeWithMode() // with which clients can specify the encoding mode. For now, we don't need the functionality. public static void encode(String content, ErrorCorrectionLevel ecLevel, QRCode qrCode) { // Step 1: Choose the mode (encoding). Mode mode = chooseMode(content); // Step 2: Append "bytes" into "dataBits" in appropriate encoding. BitVector dataBits = new BitVector(); appendBytes(content, mode, dataBits); // Step 3: Initialize QR code that can contain "dataBits". int numInputBytes = dataBits.sizeInBytes(); initQRCode(numInputBytes, ecLevel, mode, qrCode); // Step 4: Build another bit vector that contains header and data. BitVector headerAndDataBits = new BitVector(); appendModeInfo(qrCode.getMode(), headerAndDataBits); appendLengthInfo(content.Length, qrCode.getVersion(), qrCode.getMode(), headerAndDataBits); headerAndDataBits.appendBitVector(dataBits); // Step 5: Terminate the bits properly. terminateBits(qrCode.getNumDataBytes(), headerAndDataBits); // Step 6: Interleave data bits with error correction code. BitVector finalBits = new BitVector(); interleaveWithECBytes(headerAndDataBits, qrCode.getNumTotalBytes(), qrCode.getNumDataBytes(), qrCode.getNumRSBlocks(), finalBits); // Step 7: Choose the mask pattern and set to "qrCode". ByteMatrix matrix = new ByteMatrix(qrCode.getMatrixWidth(), qrCode.getMatrixWidth()); qrCode.setMaskPattern(chooseMaskPattern(finalBits, qrCode.getECLevel(), qrCode.getVersion(), matrix)); // Step 8. Build the matrix and set it to "qrCode". MatrixUtil.buildMatrix(finalBits, qrCode.getECLevel(), qrCode.getVersion(), qrCode.getMaskPattern(), matrix); qrCode.setMatrix(matrix); // Step 9. Make sure we have a valid QR Code. if (!qrCode.isValid()) { throw new WriterException("Invalid QR code: " + qrCode.toString()); } }
// Initialize "qrCode" according to "numInputBytes", "ecLevel", and "mode". On success, modify // "qrCode". private static void initQRCode(int numInputBytes, ErrorCorrectionLevel ecLevel, Mode mode, QRCode qrCode) { try { qrCode.setECLevel(ecLevel); qrCode.setMode(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.getTotalCodewords(); // getNumECBytes = 130 Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); int numEcBytes = ecBlocks.getTotalECCodewords(); // getNumRSBlocks = 5 int numRSBlocks = ecBlocks.getNumBlocks(); // 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.setVersion(versionNum); qrCode.setNumTotalBytes(numBytes); qrCode.setNumDataBytes(numDataBytes); qrCode.setNumRSBlocks(numRSBlocks); // getNumECBytes = 196 - 66 = 130 qrCode.setNumECBytes(numEcBytes); // matrix width = 21 + 6 * 4 = 45 qrCode.setMatrixWidth(version.getDimensionForVersion()); return; } } throw new WriterException("Cannot find proper rs block info (input data too big?)"); } catch(Exception e){ throw new WriterException(e.Message); } }
public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) { return(ecBlocks[ecLevel.ordinal()]); }
public static BitVector Codeword(string content, ErrorCorrectionLevel ecLevel) { QRCodeInternal qrInternal; BitVector headerAndDataBits = DataEncodeUsingReferenceImplementation(content, ecLevel, out qrInternal); // Step 6: Interleave data bits with error correction code. BitVector finalBits = new BitVector(); EncoderInternal.interleaveWithECBytes(headerAndDataBits, qrInternal.NumTotalBytes, qrInternal.NumDataBytes, qrInternal.NumRSBlocks, finalBits); return finalBits; }
internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel) { BitSource bits = new BitSource(bytes); System.Text.StringBuilder result = new System.Text.StringBuilder(50); CharacterSetECI currentCharacterSetECI = null; bool fc1InEffect = false; System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1)); Mode mode; do { // While still another segment to read... if (bits.available() < 4) { // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here mode = Mode.TERMINATOR; } else { try { mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits } catch (System.ArgumentException iae) { throw ReaderException.Instance; } } if (!mode.Equals(Mode.TERMINATOR)) { if (mode.Equals(Mode.FNC1_FIRST_POSITION) || mode.Equals(Mode.FNC1_SECOND_POSITION)) { // We do little with FNC1 except alter the parsed result a bit according to the spec fc1InEffect = true; } else if (mode.Equals(Mode.STRUCTURED_APPEND)) { // not really supported; all we do is ignore it // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue bits.readBits(16); } else if (mode.Equals(Mode.ECI)) { // Count doesn't apply to ECI int value_Renamed = parseECIValue(bits); currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value_Renamed); if (currentCharacterSetECI == null) { throw ReaderException.Instance; } } else { // How many characters will follow, encoded in this mode? int count = bits.readBits(mode.getCharacterCountBits(version)); if (mode.Equals(Mode.NUMERIC)) { decodeNumericSegment(bits, result, count); } else if (mode.Equals(Mode.ALPHANUMERIC)) { decodeAlphanumericSegment(bits, result, count, fc1InEffect); } else if (mode.Equals(Mode.BYTE)) { decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments); } else if (mode.Equals(Mode.KANJI)) { decodeKanjiSegment(bits, result, count); } else { throw ReaderException.Instance; } } } }while (!mode.Equals(Mode.TERMINATOR)); return(new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0)?null:byteSegments, ecLevel)); }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: static com.google.zxing.common.DecoderResult decode(byte[] bytes, Version version, ErrorCorrectionLevel ecLevel, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.FormatException internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel, IDictionary<DecodeHintType, object> hints) { BitSource bits = new BitSource(bytes); StringBuilder result = new StringBuilder(50); IList<sbyte[]> byteSegments = new List<sbyte[]>(1); try { CharacterSetECI currentCharacterSetECI = null; bool fc1InEffect = false; Mode mode; do { // While still another segment to read... if (bits.available() < 4) { // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here mode = Mode.TERMINATOR; } else { mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits } if (mode != Mode.TERMINATOR) { if (mode == Mode.FNC1_FIRST_POSITION || mode == Mode.FNC1_SECOND_POSITION) { // We do little with FNC1 except alter the parsed result a bit according to the spec fc1InEffect = true; } else if (mode == Mode.STRUCTURED_APPEND) { if (bits.available() < 16) { throw FormatException.FormatInstance; } // not really supported; all we do is ignore it // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue bits.readBits(16); } else if (mode == Mode.ECI) { // Count doesn't apply to ECI int value = parseECIValue(bits); currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value); if (currentCharacterSetECI == null) { throw FormatException.FormatInstance; } } else { // First handle Hanzi mode which does not start with character count if (mode == Mode.HANZI) { //chinese mode contains a sub set indicator right after mode indicator int subset = bits.readBits(4); int countHanzi = bits.readBits(mode.getCharacterCountBits(version)); if (subset == GB2312_SUBSET) { decodeHanziSegment(bits, result, countHanzi); } } else { // "Normal" QR code modes: // How many characters will follow, encoded in this mode? int count = bits.readBits(mode.getCharacterCountBits(version)); if (mode == Mode.NUMERIC) { decodeNumericSegment(bits, result, count); } else if (mode == Mode.ALPHANUMERIC) { decodeAlphanumericSegment(bits, result, count, fc1InEffect); } else if (mode == Mode.BYTE) { decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints); } else if (mode == Mode.KANJI) { decodeKanjiSegment(bits, result, count); } else { throw FormatException.FormatInstance; } } } } } while (mode != Mode.TERMINATOR); } catch (System.ArgumentException iae) { // from readBits() calls throw FormatException.FormatInstance; } return new DecoderResult(bytes, result.ToString(), byteSegments.Count == 0 ? null : byteSegments, ecLevel == null ? null : ecLevel.ToString()); }
internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel) { BitSource bits = new BitSource(bytes); System.Text.StringBuilder result = new System.Text.StringBuilder(50); CharacterSetECI currentCharacterSetECI = null; bool fc1InEffect = false; System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1)); Mode mode; do { // While still another segment to read... if (bits.available() < 4) { // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here mode = Mode.TERMINATOR; } else { try { mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits } catch (System.ArgumentException) { throw ReaderException.Instance; } } if (!mode.Equals(Mode.TERMINATOR)) { if (mode.Equals(Mode.FNC1_FIRST_POSITION) || mode.Equals(Mode.FNC1_SECOND_POSITION)) { // We do little with FNC1 except alter the parsed result a bit according to the spec fc1InEffect = true; } else if (mode.Equals(Mode.STRUCTURED_APPEND)) { // not really supported; all we do is ignore it // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue bits.readBits(16); } else if (mode.Equals(Mode.ECI)) { // Count doesn't apply to ECI int value_Renamed = parseECIValue(bits); currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value_Renamed); if (currentCharacterSetECI == null) { throw ReaderException.Instance; } } else { // How many characters will follow, encoded in this mode? int count = bits.readBits(mode.getCharacterCountBits(version)); if (mode.Equals(Mode.NUMERIC)) { decodeNumericSegment(bits, result, count); } else if (mode.Equals(Mode.ALPHANUMERIC)) { decodeAlphanumericSegment(bits, result, count, fc1InEffect); } else if (mode.Equals(Mode.BYTE)) { decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments); } else if (mode.Equals(Mode.KANJI)) { decodeKanjiSegment(bits, result, count); } else { throw ReaderException.Instance; } } } } while (!mode.Equals(Mode.TERMINATOR)); return new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0)?null:byteSegments, ecLevel); }
/// <summary> /// /// ISO/IEC 18004:2006(E) /// Table 2 ¡ª Mode indicators for QR Code 2005 /// </summary> /// <param name="bytes"></param> /// <param name="version"></param> /// <param name="ecLevel"></param> /// <returns></returns> internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel) { BitSource bits = new BitSource(bytes); System.Text.StringBuilder result = new System.Text.StringBuilder(50); CharacterSetECI currentCharacterSetECI = null; bool fc1InEffect = false; System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1)); Mode mode = Mode.TERMINATOR; int bitLen = Mode.NUMERIC.getBitsLength(version.VersionNumber); if (version.VersionNumber > 1) { try { mode = Mode.forBits(bits.readBits(bitLen)); } catch (System.ArgumentException iae) { throw ReaderException.Instance; } } else mode = Mode.NUMERIC; if (!mode.Equals(Mode.TERMINATOR)) { // How many characters will follow, encoded in this mode? int count = bits.readBits(mode.getCharacterCountBits(version)); if (mode.Equals(Mode.NUMERIC)) { decodeNumericSegment(bits, result, count); } else if (mode.Equals(Mode.ALPHANUMERIC)) { decodeAlphanumericSegment(bits, result, count, fc1InEffect); } else if (mode.Equals(Mode.BYTE)) { decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments); } else if (mode.Equals(Mode.KANJI)) { decodeKanjiSegment(bits, result, count); } else { throw ReaderException.Instance; } } return new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0) ? null : byteSegments, ecLevel); }