/// <summary> /// Constructs a QR code with the specified version number, /// error correction level, data codeword bytes, and mask number. /// </summary> /// <remarks> /// This is a low-level API that most users should not use directly. A mid-level /// API is the <see cref="EncodeSegments"/> function. /// </remarks> /// <param name="version">The version (size) to use (between 1 to 40).</param> /// <param name="ecl">The error correction level to use.</param> /// <param name="dataCodewords">The bytes representing segments to encode (without ECC).</param> /// <param name="mask">The mask pattern to use (either -1 for automatic selection, or a value from 0 to 7 for fixed choice).</param> /// <exception cref="ArgumentNullException"><paramref name="ecl"/> or <paramref name="dataCodewords"/> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException">The version or mask value is out of range, /// or the data has an invalid length for the specified version and error correction level.</exception> public QrCode(int version, Ecc ecl, byte[] dataCodewords, int mask = -1) { // Check arguments and initialize fields if (version < MinVersion || version > MaxVersion) { throw new ArgumentOutOfRangeException(nameof(version), "Version value out of range"); } if (mask < -1 || mask > 7) { throw new ArgumentOutOfRangeException(nameof(mask), "Mask value out of range"); } Version = version; Size = version * 4 + 17; Objects.RequireNonNull(ecl); ErrorCorrectionLevel = ecl; Objects.RequireNonNull(dataCodewords); _modules = new bool[Size * Size]; // Initially all white _isFunction = new bool[Size * Size]; // Compute ECC, draw modules, do masking DrawFunctionPatterns(); byte[] allCodewords = AddEccAndInterleave(dataCodewords); DrawCodewords(allCodewords); Mask = HandleConstructorMasking(mask); _isFunction = null; }
public QrCode(int ver, Ecc ecl, byte[] dataCodewords, int msk) { Utils.CheckNull(dataCodewords, nameof(dataCodewords)); if (ver < MIN_VERSION || ver > MAX_VERSION) { throw new ArgumentException("Version value out of range"); } if (msk < -1 || msk > 7) { throw new ArgumentException("Mask value out of range"); } _version = ver; _size = ver * 4 + 17; _errorCorrectionLevel = ecl; _modules = new bool[_size, _size]; _isFunction = new bool[_size, _size]; DrawFunctionPatterns(); var allCodewords = AddEccAndInterleave(dataCodewords); DrawCodewords(allCodewords); _mask = HandleConstructorMasking(msk); _isFunction = null; }
public virtual void SaveToXML(XmlElement objOrbit) { var nfi = System.Globalization.NumberFormatInfo.InvariantInfo; var xePlanet = objOrbit.OwnerDocument.CreateElement("Planet"); objOrbit.AppendChild(xePlanet); Common.CreateTextNode(xePlanet, "Type", PlanetType.ToString()); Common.CreateTextNode(xePlanet, "Dense", Dense.ToString()); Common.CreateTextNode(xePlanet, "Mass", Mass.ToString()); Common.CreateTextNode(xePlanet, "Gravity", Grav.ToString()); Common.CreateTextNode(xePlanet, "Pressure", Pressure.ToString()); Common.CreateTextNode(xePlanet, "MaxPop", Maxpop.ToString()); Common.CreateTextNode(xePlanet, "OrbitRange", OrbitRange.ToString()); Common.CreateTextNode(xePlanet, "OrbitNumber", OrbitNumber.ToString()); Common.CreateTextNode(xePlanet, "Tilt", Tilt.ToString()); Common.CreateTextNode(xePlanet, "Ecc", Ecc.ToString()); Common.CreateTextNode(xePlanet, "Rotation", Rotation.ToString()); Common.CreateTextNode(xePlanet, "TidallyLocked", TidallyLocked.ToString()); Common.CreateTextNode(xePlanet, "Temp", Temp.ToString()); Common.CreateTextNode(xePlanet, "Diameter", Diameter.ToString()); Common.CreateTextNode(xePlanet, "NumSats", Satellites.Count.ToString()); Common.CreateTextNode(xePlanet, "Mainworld", MainWorld.ToString()); Common.CreateTextNode(xePlanet, "NormalUWP", Normal.DisplayString(PlanetType, Diameter)); Common.CreateTextNode(xePlanet, "CollapseUWP", Collapse.DisplayString(PlanetType, Diameter)); Common.CreateTextNode(xePlanet, "Life", Life.ToString()); Common.CreateTextNode(xePlanet, "LifeFactor", LifeFactor.ToString()); Common.CreateTextNode(xePlanet, "Name", Name); var xeChild = objOrbit.OwnerDocument.CreateElement("Temperature"); for (var i = 0; i < (Constants.NUM_HEX_ROWS * 2) - 1; i += 2) { var xeTemp = objOrbit.OwnerDocument.CreateElement("Row" + (i / 2 + 1).ToString()); Common.CreateTextNode(xeTemp, "Summer", Summer[i].ToString("N", nfi) + "/" + Summer[i + 1].ToString("N", nfi)); Common.CreateTextNode(xeTemp, "Fall", Fall[i].ToString("N", nfi) + "/" + Fall[i + 1].ToString("N", nfi)); Common.CreateTextNode(xeTemp, "Winter", Winter[i].ToString("N", nfi) + "/" + Winter[i + 1].ToString("N", nfi)); xeChild.AppendChild(xeTemp); } xePlanet.AppendChild(xeChild); if (Life) { xeChild = objOrbit.OwnerDocument.CreateElement("AnimalEncounters"); TableGenerator.WriteToXML(xeChild); xePlanet.AppendChild(xeChild); } Normal.SaveToXML(xePlanet); Collapse.SaveToXML(xePlanet); foreach (var satellite in Satellites) { satellite.SaveToXML(xePlanet); } }
/// <summary> /// Generate random number. /// </summary> /// <param name="schema"></param> /// <returns>Random number.</returns> /// <summary> private static GXBigInteger GetRandomNumber(Ecc schema) { byte[] bytes = new byte[SchemeSize(schema)]; Random random = new Random(); random.NextBytes(bytes); return(new GXBigInteger(bytes)); }
/// <summary> /// Creates a QR code representing the specified text using the specified error correction level. /// <para> /// As a conservative upper bound, this function is guaranteed to succeed for strings with up to 738 /// Unicode code points (not UTF-16 code units) if the low error correction level is used. The smallest possible /// QR code version (size) is automatically chosen. The resulting ECC level will be higher than the one /// specified if it can be achieved without increasing the size (version). /// </para> /// </summary> /// <param name="text">The text to be encoded. The full range of Unicode characters may be used.</param> /// <param name="ecl">The minimum error correction level to use.</param> /// <returns>The created QR code instance representing the specified text.</returns> /// <exception cref="ArgumentNullException"><paramref name="text"/> or <paramref name="ecl"/> is <c>null</c>.</exception> /// <exception cref="DataTooLongException">The text is too long to fit in the largest QR code size (version) /// at the specified error correction level.</exception> public static QrCode EncodeText(string text, Ecc ecl) { Objects.RequireNonNull(text); Objects.RequireNonNull(ecl); List <QrSegment> segs = QrSegment.MakeSegments(text); return(EncodeSegments(segs, ecl)); }
/// <summary> /// Generate random number. /// </summary> /// <param name="schema"></param> /// <returns>Random number.</returns> /// <summary> private static GXBigInteger GetRandomNumber(Ecc schema) { byte[] bytes = new byte[schema == Ecc.P256 ? 32 : 48]; Random random = new Random(); random.NextBytes(bytes); return(new GXBigInteger(bytes)); }
public static QrCode EncodeText(string text, Ecc ecl) { Utils.CheckNull(text, nameof(text)); var segs = QrSegment.MakeSegments(text); return(EncodeSegments(segs, ecl)); }
/// <summary> /// Generate public and private key pair. /// </summary> /// <returns></returns> public static KeyValuePair <GXPrivateKey, GXPublicKey> GenerateKeyPair(Ecc scheme) { byte[] raw = GetRandomNumber(scheme).ToArray(); GXPrivateKey pk = GXPrivateKey.FromRawBytes(raw); GXPublicKey pub = pk.GetPublicKey(); return(new KeyValuePair <GXPrivateKey, GXPublicKey>(pk, pub)); }
/// <summary> /// Creates a QR code representing the specified binary data using the specified error correction level. /// <para> /// This function encodes the data in the binary segment mode. The maximum number of /// bytes allowed is 2953. The smallest possible QR code version is automatically chosen. /// The resulting ECC level will be higher than the one specified if it can be achieved without increasing the size (version). /// </para> /// </summary> /// <param name="data">The binary data to encode.</param> /// <param name="ecl">The minimum error correction level to use.</param> /// <returns>The created QR code representing the specified data.</returns> /// <exception cref="ArgumentNullException"><paramref name="data"/> or <paramref name="ecl"/> is <c>null</c>.</exception> /// <exception cref="DataTooLongException">The specified data is too long to fit in the largest QR code size (version) /// at the specified error correction level.</exception> public static QrCode EncodeBinary(byte[] data, Ecc ecl) { QrSegment seg = QrSegment.MakeBytes(data); return(EncodeSegments(new List <QrSegment> { seg }, ecl)); }
/// <summary> /// Creates a QR code representing the specified binary data using the specified error correction level. /// <para> /// This function encodes the data in the binary segment mode. The maximum number of /// bytes allowed is 2953. The smallest possible QR code version is automatically chosen. /// The resulting ECC level will be higher than the one specified if it can be achieved without increasing the size (version). /// </para> /// </summary> /// <param name="data">The binary data to encode.</param> /// <param name="ecl">The minimum error correction level to use.</param> /// <returns>The created QR code representing the specified data.</returns> /// <exception cref="ArgumentNullException"><paramref name="data"/> or <paramref name="ecl"/> is <c>null</c>.</exception> /// <exception cref="DataTooLongException">The specified data is too long to fit in the largest QR code size (version) /// at the specified error correction level.</exception> public static QrCode EncodeBinary(byte[] data, Ecc ecl) { Objects.RequireNonNull(data); Objects.RequireNonNull(ecl); QrSegment seg = QrSegment.MakeBytes(data); return(EncodeSegments(new List <QrSegment> { seg }, ecl)); }
/// <summary> /// Constructor. /// </summary> /// <param name="a">ECC curve a value.</param> /// <param name="b">ECC curve b parameter.</param> /// <param name="p">ECC curve p value.</param> /// <param name="g">x and y-coordinate of base point G</param> /// <param name="n">Order of point G in ECC curve.</param> public GXCurve(Ecc scheme) { if (scheme == Ecc.P256) { //Table A. 1 – ECC_P256_Domain_Parameters A = new GXBigInteger(new UInt32[] { 0xFFFFFFFF, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC }); G = new GXEccPoint(new GXBigInteger(new UInt32[] { 0x6B17D1F2, 0xE12C4247, 0xF8BCE6E5, 0x63A440F2, 0x77037D81, 0x2DEB33A0, 0xF4A13945, 0xD898C296 }), new GXBigInteger(new UInt32[] { 0x4FE342E2, 0xFE1A7F9B, 0x8EE7EB4A, 0x7C0F9E16, 0x2BCE3357, 0x6B315ECE, 0xCBB64068, 0x37BF51F5 }), new GXBigInteger(1)); N = new GXBigInteger(new UInt32[] { 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xBCE6FAAD, 0xA7179E84, 0xF3B9CAC2, 0xFC632551 }); P = new GXBigInteger(new UInt32[] { 0xFFFFFFFF, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }); B = new GXBigInteger(new UInt32[] { 0x5AC635D8, 0xAA3A93E7, 0xB3EBBD55, 0x769886BC, 0x651D06B0, 0xCC53B0F6, 0x3BCE3C3E, 0x27D2604B }); } else if (scheme == Ecc.P384) { //Table A. 2 – ECC_P384_Domain_Parameters A = new GXBigInteger(new UInt32[] { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFC }); G = new GXEccPoint(new GXBigInteger(new UInt32[] { 0xAA87CA22, 0xBE8B0537, 0x8EB1C71E, 0xF320AD74, 0x6E1D3B62, 0x8BA79B98, 0x59F741E0, 0x82542A38, 0x5502F25D, 0xBF55296C, 0x3A545E38, 0x72760AB7 }), new GXBigInteger(new UInt32[] { 0x3617DE4A, 0x96262C6F, 0x5D9E98BF, 0x9292DC29, 0xF8F41DBD, 0x289A147C, 0xE9DA3113, 0xB5F0B8C0, 0x0A60B1CE, 0x1D7E819D, 0x7A431D7C, 0x90EA0E5F }), new GXBigInteger(1)); N = new GXBigInteger(new UInt32[] { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC7634D81, 0xF4372DDF, 0x581A0DB2, 0x48B0A77A, 0xECEC196A, 0xCCC52973 }); P = new GXBigInteger(new UInt32[] { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF }); B = new GXBigInteger(new UInt32[] { 0xB3312FA7, 0xE23EE7E4, 0x988E056B, 0xE3F82D19, 0x181D9C6E, 0xFE814112, 0x0314088F, 0x5013875A, 0xC656398D, 0x8A2ED19D, 0x2A85C8ED, 0xD3EC2AEF }); } else { throw new ArgumentOutOfRangeException("Invalid scheme."); } }
public static List <QrSegment> MakeSegmentsOptimally(string text, Ecc ecl, int minVersion, int maxVersion) { Utils.CheckNull(text, nameof(text)); if (!(QrCode.MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= QrCode.MAX_VERSION)) { throw new ArgumentException("Invalid value"); } List <QrSegment> segs = null; var codePoints = ToCodePoints(text); for (int version = minVersion; ; version++) { if (version == minVersion || version == 10 || version == 27) { segs = MakeSegmentsOptimally(codePoints, version); } var dataCapacityBits = QrCode.GetNumDataCodewords(version, ecl) * 8; var dataUsedBits = QrSegment.GetTotalBits(segs, version); if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) { return(segs); } if (version >= maxVersion) { var msg = "Segment too long"; if (dataUsedBits != -1) { msg = String.Format("Data length = {0} bits, Max capacity = {1} bits", dataUsedBits, dataCapacityBits); } throw new DataTooLongException(msg); } } }
/// <summary> /// Get scheme size in bytes. /// </summary> /// <param name="scheme"></param> /// <returns></returns> private static int SchemeSize(Ecc scheme) { return(scheme == Ecc.P256 ? 32 : 48); }
/// <summary> /// Creates a QR code representing the specified segments with the specified encoding parameters. /// <para> /// The smallest possible QR code version (size) is used. The range of versions can be /// restricted by the <paramref name="minVersion"/> and <paramref name="maxVersion"/> parameters. /// </para> /// <para> /// If <paramref name="boostEcl"/> is <c>true</c>, the resulting ECC level will be higher than the /// one specified if it can be achieved without increasing the size (version). /// </para> /// <para> /// The QR code mask is usually automatically chosen. It can be explicitly set with the <paramref name="mask"/> /// parameter by using a value between 0 to 7 (inclusive). -1 is for automatic mode (which may be slow). /// </para> /// <para> /// This function allows the user to create a custom sequence of segments that switches /// between modes (such as alphanumeric and byte) to encode text in less space and gives full control over all /// encoding paramters. /// </para> /// </summary> /// <remarks> /// This is a mid-level API; the high-level APIs are <see cref="EncodeText(string, Ecc)"/> /// and <see cref="EncodeBinary(byte[], Ecc)"/>. /// </remarks> /// <param name="segments">The segments to encode.</param> /// <param name="ecl">The minimal or fixed error correction level to use .</param> /// <param name="minVersion">The minimum version (size) of the QR code (between 1 and 40).</param> /// <param name="maxVersion">The maximum version (size) of the QR code (between 1 and 40).</param> /// <param name="mask">The mask number to use (between 0 and 7), or -1 for automatic mask selection.</param> /// <param name="boostEcl">If <c>true</c> the ECC level wil be increased if it can be achieved without increasing the size (version).</param> /// <returns>The created QR code representing the segments.</returns> /// <exception cref="ArgumentNullException"><paramref name="segments"/>, any list element, or <paramref name="ecl"/> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException">1 ≤ minVersion ≤ maxVersion ≤ 40 /// or -1 ≤ mask ≤ 7 is violated.</exception> /// <exception cref="DataTooLongException">The segments are too long to fit in the largest QR code size (version) /// at the specified error correction level.</exception> public static QrCode EncodeSegments(List <QrSegment> segments, Ecc ecl, int minVersion = MinVersion, int maxVersion = MaxVersion, int mask = -1, bool boostEcl = true) { Objects.RequireNonNull(segments); Objects.RequireNonNull(ecl); if (minVersion < MinVersion || minVersion > maxVersion) { throw new ArgumentOutOfRangeException(nameof(minVersion), "Invalid value"); } if (maxVersion > MaxVersion) { throw new ArgumentOutOfRangeException(nameof(maxVersion), "Invalid value"); } if (mask < -1 || mask > 7) { throw new ArgumentOutOfRangeException(nameof(mask), "Invalid value"); } // Find the minimal version number to use int version, dataUsedBits; for (version = minVersion; ; version++) { int numDataBits = GetNumDataCodewords(version, ecl) * 8; // Number of data bits available dataUsedBits = QrSegment.GetTotalBits(segments, version); if (dataUsedBits != -1 && dataUsedBits <= numDataBits) { break; // This version number is found to be suitable } if (version >= maxVersion) { // All versions in the range could not fit the given data string msg = "Segment too long"; if (dataUsedBits != -1) { msg = $"Data length = {dataUsedBits} bits, Max capacity = {numDataBits} bits"; } throw new DataTooLongException(msg); } } Debug.Assert(dataUsedBits != -1); // Increase the error correction level while the data still fits in the current version number foreach (Ecc newEcl in Ecc.AllValues) { // From low to high if (boostEcl && dataUsedBits <= GetNumDataCodewords(version, newEcl) * 8) { ecl = newEcl; } } // Concatenate all segments to create the data bit string BitArray ba = new BitArray(0); foreach (QrSegment seg in segments) { ba.AppendBits(seg.EncodingMode.ModeBits, 4); ba.AppendBits((uint)seg.NumChars, seg.EncodingMode.NumCharCountBits(version)); ba.AppendData(seg.GetData()); } Debug.Assert(ba.Length == dataUsedBits); // Add terminator and pad up to a byte if applicable int dataCapacityBits = GetNumDataCodewords(version, ecl) * 8; Debug.Assert(ba.Length <= dataCapacityBits); ba.AppendBits(0, Math.Min(4, dataCapacityBits - ba.Length)); ba.AppendBits(0, (8 - ba.Length % 8) % 8); Debug.Assert(ba.Length % 8 == 0); // Pad with alternating bytes until data capacity is reached for (uint padByte = 0xEC; ba.Length < dataCapacityBits; padByte ^= 0xEC ^ 0x11) { ba.AppendBits(padByte, 8); } // Pack bits into bytes in big endian byte[] dataCodewords = new byte[ba.Length / 8]; for (int i = 0; i < ba.Length; i++) { if (ba.Get(i)) { dataCodewords[i >> 3] |= (byte)(1 << (7 - (i & 7))); } } // Create the QR code object return(new QrCode(version, ecl, dataCodewords, mask)); }
// Returns the number of 8-bit data (i.e. not error correction) codewords contained in any // QR code of the given version number and error correction level, with remainder bits discarded. // This stateless pure function could be implemented as a (40*4)-cell lookup table. internal static int GetNumDataCodewords(int ver, Ecc ecl) { return(GetNumRawDataModules(ver) / 8 - EccCodewordsPerBlock[ecl.Ordinal, ver] * NumErrorCorrectionBlocks[ecl.Ordinal, ver]); }
private GXEcdsa(Ecc scheme) { curve = new GXCurve(scheme); }
/// <summary> /// Creates a QR code representing the specified text using the specified error correction level. /// <para> /// As a conservative upper bound, this function is guaranteed to succeed for strings with up to 738 /// Unicode code points (not UTF-16 code units) if the low error correction level is used. The smallest possible /// QR code version (size) is automatically chosen. The resulting ECC level will be higher than the one /// specified if it can be achieved without increasing the size (version). /// </para> /// </summary> /// <param name="text">The text to be encoded. The full range of Unicode characters may be used.</param> /// <param name="ecl">The minimum error correction level to use.</param> /// <returns>The created QR code instance representing the specified text.</returns> /// <exception cref="ArgumentNullException"><paramref name="text"/> or <paramref name="ecl"/> is <c>null</c>.</exception> /// <exception cref="DataTooLongException">The text is too long to fit in the largest QR code size (version) /// at the specified error correction level.</exception> public static QrCode EncodeText(string text, Ecc ecl) { List <QrSegment> segs = QrSegment.MakeSegments(text); return(EncodeSegments(segs, ecl)); }
/// <summary> /// Update certificates with server and client system title. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void UpdateBtn_Click(object sender, EventArgs e) { try { _checkSystemTitle = false; SecuritySuite ss = (SecuritySuite)SecuritySuiteCb.SelectedItem; Ecc scheme = ss == SecuritySuite.Suite1 ? Ecc.P256 : Ecc.P384; byte[] tmp = GXDLMSTranslator.HexToBytes(SystemTitle); if (tmp.Length != 0 && tmp.Length != 8) { throw new Exception("Client system title is invalid."); } string clientST = null; if (tmp.Length != 0) { clientST = "CN=" + GXDLMSTranslator.ToHex(tmp, false); } tmp = GXDLMSTranslator.HexToBytes(ServerSystemTitle); if (tmp.Length != 0 && tmp.Length != 8) { throw new Exception("Server system title is invalid."); } string serverST = null; if (tmp.Length != 0) { serverST = "CN=" + GXDLMSTranslator.ToHex(tmp, false); } ClientAgreementKeysCb.SelectedItem = null; ServerAgreementKeysCb.SelectedItem = null; ClientSigningKeysCb.SelectedItem = null; ServerSigningKeysCb.SelectedItem = null; if (clientST != null) { foreach (object tmp2 in ClientAgreementKeysCb.Items) { if (tmp2 is KeyValuePair <GXPkcs8, GXx509Certificate> it) { if (it.Value != null && it.Value.PublicKey.Scheme == scheme && it.Value.Subject.Contains(clientST)) { ClientAgreementKeysCb.SelectedItem = it; break; } } } foreach (object tmp2 in ClientSigningKeysCb.Items) { if (tmp2 is KeyValuePair <GXPkcs8, GXx509Certificate> it) { if (it.Value != null && it.Value.PublicKey.Scheme == scheme && it.Value.Subject.Contains(clientST)) { ClientSigningKeysCb.SelectedItem = it; break; } } } } if (serverST != null) { foreach (object tmp2 in ServerAgreementKeysCb.Items) { if (tmp2 is KeyValuePair <GXPkcs8, GXx509Certificate> it) { if (it.Value != null && it.Value.PublicKey.Scheme == scheme && it.Value.Subject.Contains(serverST)) { ServerAgreementKeysCb.SelectedItem = it; break; } } } foreach (object tmp2 in ServerSigningKeysCb.Items) { if (tmp2 is KeyValuePair <GXPkcs8, GXx509Certificate> it) { if (it.Value != null && it.Value.PublicKey.Scheme == scheme && it.Value.Subject.Contains(serverST)) { ServerSigningKeysCb.SelectedItem = it; break; } } } } } catch (Exception ex) { MessageBox.Show(Parent, ex.Message); } finally { _checkSystemTitle = true; } }
public static QrCode EncodeSegments(List <QrSegment> segs, Ecc ecl, int minVersion, int maxVersion, int mask, bool boostEcl) { Utils.CheckNull(segs, nameof(segs)); if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7) { throw new ArgumentException("Invalid value"); } int version, dataUsedBits; for (version = minVersion; ; version++) { var capacityBits = GetNumDataCodewords(version, ecl) * 8; dataUsedBits = QrSegment.GetTotalBits(segs, version); if (dataUsedBits != -1 && dataUsedBits <= capacityBits) { break; } if (version >= maxVersion) { var msg = "Segment too long"; if (dataUsedBits != -1) { msg = string.Format("Data length = {0} bits, Max capacity = {1} bits", dataUsedBits, capacityBits); } throw new DataTooLongException(msg); } } foreach (var newEcl in new Ecc[] { Ecc.Low, Ecc.Medium, Ecc.Quartitle, Ecc.High }) { if (boostEcl && dataUsedBits <= GetNumDataCodewords(version, newEcl) * 8) { ecl = newEcl; } } var bb = new BitBuffer(); foreach (var seg in segs) { bb.AppendBits(seg.Mode.ModeBits, 4); bb.AppendBits(seg.NumChars, seg.Mode.NumCharCountBits(version)); bb.AppendData(seg.Data); } var dataCapacityBits = GetNumDataCodewords(version, ecl) * 8; bb.AppendBits(0, Math.Min(4, dataCapacityBits - bb.Length)); bb.AppendBits(0, (8 - bb.Length % 8) % 8); for (var padByte = 0xEC; bb.Length < dataCapacityBits; padByte ^= 0xEC ^ 0x11) { bb.AppendBits(padByte, 8); } var dataCodewords = new byte[bb.Length / 8]; for (var i = 0; i < bb.Length; i++) { dataCodewords[i >> 3] = (byte)(dataCodewords[i >> 3] | bb.GetBit(i) << (7 - (i & 7))); } // Create the QR Code object return(new QrCode(version, ecl, dataCodewords, mask)); }
public static QrCode EncodeSegments(List <QrSegment> segs, Ecc ecl) { return(EncodeSegments(segs, ecl, MIN_VERSION, MAX_VERSION, -1, true)); }
public static int GetNumDataCodewords(int ver, Ecc ecl) { return(GetNumRawDataModules(ver) / 8 - ECC_CODEWORDS_PER_BLOCK [(int)ecl][ver] * NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][ver]); }