static MinimalEncoder() { var names = new[] { "ISO-8859-2", "ISO-8859-3", "ISO-8859-4", "ISO-8859-5", "ISO-8859-6", "ISO-8859-7", "ISO-8859-8", "ISO-8859-9", "ISO-8859-10", "ISO-8859-11", "ISO-8859-13", "ISO-8859-14", "ISO-8859-15", "ISO-8859-16", "windows-1250", "windows-1251", "windows-1252", "windows-1253", "windows-1254", "windows-1255", "windows-1256", "windows-1257", "windows-1258", "Shift_JIS" }; foreach (String name in names) { if (CharacterSetECI.getCharacterSetECIByName(name) != null) { try { ENCODERS.Add(Clone(Encoding.GetEncoding(name))); } catch (Exception) { // continue } } } }
/// <summary> /// Encodes the specified content. /// </summary> /// <param name="content">The content.</param> /// <param name="ecLevel">The ec level.</param> /// <param name="hints">The hints.</param> /// <returns></returns> public static QRCode encode(String content, ErrorCorrectionLevel ecLevel, IDictionary <EncodeHintType, object> hints) { // Determine what character encoding has been specified by the caller, if any #if !SILVERLIGHT || WINDOWS_PHONE String encoding = hints == null || !hints.ContainsKey(EncodeHintType.CHARACTER_SET) ? null : (String)hints[EncodeHintType.CHARACTER_SET]; if (encoding == null) { encoding = DEFAULT_BYTE_MODE_ENCODING; } bool generateECI = !DEFAULT_BYTE_MODE_ENCODING.Equals(encoding); #else // Silverlight supports only UTF-8 and UTF-16 out-of-the-box const string encoding = "UTF-8"; // caller of the method can only control if the ECI segment should be written // character set is fixed to UTF-8; but some scanners doesn't like the ECI segment bool generateECI = (hints != null && hints.ContainsKey(EncodeHintType.CHARACTER_SET)); #endif // http://zxingnet.codeplex.com/discussions/399045 if (hints != null && hints.ContainsKey(EncodeHintType.DISABLE_ECI) && (bool)hints[EncodeHintType.DISABLE_ECI]) { generateECI = false; } // Pick an encoding mode appropriate for the content. Note that this will not attempt to use // multiple modes / segments even if that were more efficient. Twould be nice. Mode mode = chooseMode(content, encoding); // This will store the header information, like mode and // length, as well as "header" segments like an ECI segment. BitArray headerBits = new BitArray(); // Append ECI segment if applicable if (mode == Mode.BYTE && generateECI) { CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding); if (eci != null) { appendECI(eci, headerBits); } } // (With ECI in place,) Write the mode marker appendModeInfo(mode, headerBits); // Collect data within the main segment, separately, to count its size if needed. Don't add it to // main payload yet. BitArray dataBits = new BitArray(); appendBytes(content, mode, dataBits, encoding); // Hard part: need to know version to know how many bits length takes. But need to know how many // bits it takes to know version. First we take a guess at version by assuming version will be // the minimum, 1: int provisionalBitsNeeded = headerBits.Size + mode.getCharacterCountBits(Version.getVersionForNumber(1)) + dataBits.Size; Version provisionalVersion = chooseVersion(provisionalBitsNeeded, ecLevel); // Use that guess to calculate the right version. I am still not sure this works in 100% of cases. int bitsNeeded = headerBits.Size + mode.getCharacterCountBits(provisionalVersion) + dataBits.Size; Version version = chooseVersion(bitsNeeded, ecLevel); BitArray headerAndDataBits = new BitArray(); headerAndDataBits.appendBitArray(headerBits); // Find "length" of main segment and write it int numLetters = mode == Mode.BYTE ? dataBits.SizeInBytes : content.Length; appendLengthInfo(numLetters, version, mode, headerAndDataBits); // Put data together into the overall payload headerAndDataBits.appendBitArray(dataBits); Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); int numDataBytes = version.TotalCodewords - ecBlocks.TotalECCodewords; // Terminate the bits properly. terminateBits(numDataBytes, headerAndDataBits); // Interleave data bits with error correction code. BitArray finalBits = interleaveWithECBytes(headerAndDataBits, version.TotalCodewords, numDataBytes, ecBlocks.NumBlocks); QRCode qrCode = new QRCode { ECLevel = ecLevel, Mode = mode, Version = version }; // Choose the mask pattern and set to "qrCode". int dimension = version.DimensionForVersion; ByteMatrix matrix = new ByteMatrix(dimension, dimension); int maskPattern = chooseMaskPattern(finalBits, ecLevel, version, matrix); qrCode.MaskPattern = maskPattern; // Build the matrix and set it to "qrCode". MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix); qrCode.Matrix = matrix; return(qrCode); }
/// <summary> /// Performs high-level encoding of a PDF417 message using the algorithm described in annex P /// of ISO/IEC 15438:2001(E). If byte compaction has been selected, then only byte compaction /// is used. /// </summary> /// <param name="msg">the message</param> /// <param name="compaction">compaction mode to use</param> /// <param name="encoding">character encoding used to encode in default or byte compaction /// or null for default / not applicable</param> /// <param name="disableEci">if true, don't add an ECI segment for different encodings than default</param> /// <returns>the encoded message (the char values range from 0 to 928)</returns> internal static String encodeHighLevel(String msg, Compaction compaction, Encoding encoding, bool disableEci) { //the codewords 0..928 are encoded as Unicode characters var sb = new StringBuilder(msg.Length); if (encoding != null && !disableEci && String.Compare(DEFAULT_ENCODING_NAME, encoding.WebName, StringComparison.Ordinal) != 0) { CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding.WebName); if (eci != null) { encodingECI(eci.Value, sb); } } int len = msg.Length; int p = 0; int textSubMode = SUBMODE_ALPHA; // User selected encoding mode switch (compaction) { case Compaction.TEXT: encodeText(msg, p, len, sb, textSubMode); break; case Compaction.BYTE: var msgBytes = toBytes(msg, encoding); encodeBinary(msgBytes, p, msgBytes.Length, BYTE_COMPACTION, sb); break; case Compaction.NUMERIC: sb.Append((char)LATCH_TO_NUMERIC); encodeNumeric(msg, p, len, sb); break; default: int encodingMode = TEXT_COMPACTION; //Default mode, see 4.4.2.1 byte[] bytes = null; while (p < len) { int n = determineConsecutiveDigitCount(msg, p); if (n >= 13) { sb.Append((char)LATCH_TO_NUMERIC); encodingMode = NUMERIC_COMPACTION; textSubMode = SUBMODE_ALPHA; //Reset after latch encodeNumeric(msg, p, n, sb); p += n; } else { int t = determineConsecutiveTextCount(msg, p); if (t >= 5 || n == len) { if (encodingMode != TEXT_COMPACTION) { sb.Append((char)LATCH_TO_TEXT); encodingMode = TEXT_COMPACTION; textSubMode = SUBMODE_ALPHA; //start with submode alpha after latch } textSubMode = encodeText(msg, p, t, sb, textSubMode); p += t; } else { if (bytes == null) { bytes = toBytes(msg, encoding); } int b = determineConsecutiveBinaryCount(msg, bytes, p, encoding); if (b == 0) { b = 1; } if (b == 1 && encodingMode == TEXT_COMPACTION) { //Switch for one byte (instead of latch) encodeBinary(bytes, 0, 1, TEXT_COMPACTION, sb); } else { //Mode latch performed by encodeBinary() encodeBinary(bytes, toBytes(msg.Substring(0, p), encoding).Length, toBytes(msg.Substring(p, b), encoding).Length, encodingMode, sb); encodingMode = BYTE_COMPACTION; textSubMode = SUBMODE_ALPHA; //Reset after latch } p += b; } } } break; } return(sb.ToString()); }
/// <summary> /// Performs high-level encoding of a PDF417 message using the algorithm described in annex P /// of ISO/IEC 15438:2001(E). If byte compaction has been selected, then only byte compaction /// is used. /// /// <param name="msg">the message</param> /// <returns>the encoded message (the char values range from 0 to 928)</returns> /// </summary> internal static String encodeHighLevel(String msg, Compaction compaction, Encoding encoding, bool disableEci) { //the codewords 0..928 are encoded as Unicode characters var sb = new StringBuilder(msg.Length); if (!DEFAULT_ENCODING.Equals(encoding) && !disableEci) { CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding.WebName); if (eci != null) { encodingECI(eci.Value, sb); } } int len = msg.Length; int p = 0; int textSubMode = SUBMODE_ALPHA; // User selected encoding mode byte[] bytes = null; //Fill later and only if needed if (compaction == Compaction.TEXT) { encodeText(msg, p, len, sb, textSubMode); } else if (compaction == Compaction.BYTE) { bytes = encoding.GetBytes(msg); encodeBinary(bytes, p, bytes.Length, BYTE_COMPACTION, sb); } else if (compaction == Compaction.NUMERIC) { sb.Append((char)LATCH_TO_NUMERIC); encodeNumeric(msg, p, len, sb); } else { int encodingMode = TEXT_COMPACTION; //Default mode, see 4.4.2.1 while (p < len) { int n = determineConsecutiveDigitCount(msg, p); if (n >= 13) { sb.Append((char)LATCH_TO_NUMERIC); encodingMode = NUMERIC_COMPACTION; textSubMode = SUBMODE_ALPHA; //Reset after latch encodeNumeric(msg, p, n, sb); p += n; } else { int t = determineConsecutiveTextCount(msg, p); if (t >= 5 || n == len) { if (encodingMode != TEXT_COMPACTION) { sb.Append((char)LATCH_TO_TEXT); encodingMode = TEXT_COMPACTION; textSubMode = SUBMODE_ALPHA; //start with submode alpha after latch } textSubMode = encodeText(msg, p, t, sb, textSubMode); p += t; } else { if (bytes == null) { bytes = encoding.GetBytes(msg); } int b = determineConsecutiveBinaryCount(msg, bytes, p); if (b == 0) { b = 1; } if (b == 1 && encodingMode == TEXT_COMPACTION) { //Switch for one byte (instead of latch) encodeBinary(bytes, p, 1, TEXT_COMPACTION, sb); } else { //Mode latch performed by encodeBinary() encodeBinary(bytes, p, b, encodingMode, sb); encodingMode = BYTE_COMPACTION; textSubMode = SUBMODE_ALPHA; //Reset after latch } p += b; } } } } return(sb.ToString()); }
/// <summary> /// Encodes the specified content. /// </summary> /// <param name="content">The content.</param> /// <param name="ecLevel">The ec level.</param> /// <param name="hints">The hints.</param> /// <returns></returns> public static QRCode encode(String content, ErrorCorrectionLevel ecLevel, IDictionary <EncodeHintType, object> hints) { // Determine what character encoding has been specified by the caller, if any bool hasEncodingHint = hints != null && hints.ContainsKey(EncodeHintType.CHARACTER_SET); #if !SILVERLIGHT || WINDOWS_PHONE var encoding = hints == null || !hints.ContainsKey(EncodeHintType.CHARACTER_SET) ? null : (String)hints[EncodeHintType.CHARACTER_SET]; if (encoding == null) { encoding = DEFAULT_BYTE_MODE_ENCODING; } var generateECI = hasEncodingHint || !DEFAULT_BYTE_MODE_ENCODING.Equals(encoding); #else // Silverlight supports only UTF-8 and UTF-16 out-of-the-box const string encoding = "UTF-8"; // caller of the method can only control if the ECI segment should be written // character set is fixed to UTF-8; but some scanners doesn't like the ECI segment var generateECI = hasEncodingHint; #endif // Pick an encoding mode appropriate for the content. Note that this will not attempt to use // multiple modes / segments even if that were more efficient. Twould be nice. var mode = chooseMode(content, encoding); // This will store the header information, like mode and // length, as well as "header" segments like an ECI segment. var headerBits = new BitArray(); // Append ECI segment if applicable if (mode == Mode.BYTE && generateECI) { var eci = CharacterSetECI.getCharacterSetECIByName(encoding); if (eci != null) { var eciIsExplicitDisabled = (hints != null && hints.ContainsKey(EncodeHintType.DISABLE_ECI) && hints[EncodeHintType.DISABLE_ECI] != null && Convert.ToBoolean(hints[EncodeHintType.DISABLE_ECI].ToString())); if (!eciIsExplicitDisabled) { appendECI(eci, headerBits); } } } // Append the FNC1 mode header for GS1 formatted data if applicable var hasGS1FormatHint = hints != null && hints.ContainsKey(EncodeHintType.GS1_FORMAT); if (hasGS1FormatHint && hints[EncodeHintType.GS1_FORMAT] != null && Convert.ToBoolean(hints[EncodeHintType.GS1_FORMAT].ToString())) { // GS1 formatted codes are prefixed with a FNC1 in first position mode header appendModeInfo(Mode.FNC1_FIRST_POSITION, headerBits); } // (With ECI in place,) Write the mode marker appendModeInfo(mode, headerBits); // Collect data within the main segment, separately, to count its size if needed. Don't add it to // main payload yet. var dataBits = new BitArray(); appendBytes(content, mode, dataBits, encoding); Version version; if (hints != null && hints.ContainsKey(EncodeHintType.QR_VERSION)) { int versionNumber = Int32.Parse(hints[EncodeHintType.QR_VERSION].ToString()); version = Version.getVersionForNumber(versionNumber); int bitsNeeded = calculateBitsNeeded(mode, headerBits, dataBits, version); if (!willFit(bitsNeeded, version, ecLevel)) { throw new WriterException("Data too big for requested version"); } } else { version = recommendVersion(ecLevel, mode, headerBits, dataBits); } var headerAndDataBits = new BitArray(); headerAndDataBits.appendBitArray(headerBits); // Find "length" of main segment and write it var numLetters = mode == Mode.BYTE ? dataBits.SizeInBytes : content.Length; appendLengthInfo(numLetters, version, mode, headerAndDataBits); // Put data together into the overall payload headerAndDataBits.appendBitArray(dataBits); var ecBlocks = version.getECBlocksForLevel(ecLevel); var numDataBytes = version.TotalCodewords - ecBlocks.TotalECCodewords; // Terminate the bits properly. terminateBits(numDataBytes, headerAndDataBits); // Interleave data bits with error correction code. var finalBits = interleaveWithECBytes(headerAndDataBits, version.TotalCodewords, numDataBytes, ecBlocks.NumBlocks); var qrCode = new QRCode { ECLevel = ecLevel, Mode = mode, Version = version }; // Choose the mask pattern and set to "qrCode". var dimension = version.DimensionForVersion; var matrix = new ByteMatrix(dimension, dimension); var maskPattern = chooseMaskPattern(finalBits, ecLevel, version, matrix); qrCode.MaskPattern = maskPattern; // Build the matrix and set it to "qrCode". MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix); qrCode.Matrix = matrix; return(qrCode); }
public static QRCode encode(String content, ErrorCorrectionLevel ecLevel, IDictionary hints) { // Determine what character encoding has been specified by the caller, if any String encoding = hints == null || !hints.Contains(EncodeHintType.CHARACTER_SET) ? null : (String)hints[EncodeHintType.CHARACTER_SET]; if (encoding == null) { encoding = DEFAULT_BYTE_MODE_ENCODING; } bool doSelectMask = hints == null || !hints.Contains(EncodeHintType.QR_DO_MASK_SELECTION) ? false : (bool)hints[EncodeHintType.QR_DO_MASK_SELECTION]; // Pick an encoding mode appropriate for the content. Note that this will not attempt to use // multiple modes / segments even if that were more efficient. Twould be nice. Mode mode = chooseMode(content, encoding); // This will store the header information, like mode and // length, as well as "header" segments like an ECI segment. BitArray headerBits = new BitArray(); // Append ECI segment if applicable if (mode == Mode.BYTE && !DEFAULT_BYTE_MODE_ENCODING.Equals(encoding)) { CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding); if (eci != null) { appendECI(eci, headerBits); } } // (With ECI in place,) Write the mode marker appendModeInfo(mode, headerBits); // Collect data within the main segment, separately, to count its size if needed. Don't add it to // main payload yet. BitArray dataBits = new BitArray(); appendBytes(content, mode, dataBits, encoding); // Hard part: need to know version to know how many bits length takes. But need to know how many // bits it takes to know version. To pick version size assume length takes maximum bits int bitsNeeded = headerBits.Size + mode.getCharacterCountBits(Version.getVersionForNumber(40)) + dataBits.Size; Version version = chooseVersion(bitsNeeded, ecLevel); BitArray headerAndDataBits = new BitArray(); headerAndDataBits.appendBitArray(headerBits); // Find "length" of main segment and write it int numLetters = mode == Mode.BYTE ? dataBits.SizeInBytes : content.Length; appendLengthInfo(numLetters, version, mode, headerAndDataBits); // Put data together into the overall payload headerAndDataBits.appendBitArray(dataBits); Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel); int numDataBytes = version.TotalCodewords - ecBlocks.TotalECCodewords; // Terminate the bits properly. terminateBits(numDataBytes, headerAndDataBits); // Interleave data bits with error correction code. BitArray finalBits = interleaveWithECBytes(headerAndDataBits, version.TotalCodewords, numDataBytes, ecBlocks.NumBlocks); QRCode qrCode = new QRCode { ECLevel = ecLevel, Mode = mode, Version = version }; // Choose the mask pattern and set to "qrCode". int dimension = version.DimensionForVersion; ByteMatrix matrix = new ByteMatrix(dimension, dimension); int maskPattern = 3; if (doSelectMask) { maskPattern = chooseMaskPattern(finalBits, ecLevel, version, matrix); } qrCode.MaskPattern = maskPattern; // Build the matrix and set it to "qrCode". MatrixUtil.buildMatrix(finalBits, ecLevel, version, maskPattern, matrix); qrCode.Matrix = matrix; return(qrCode); }