/// <summary> /// Gets the version number for the QR code encoding. /// </summary> /// <param name="textUTF8">The user unicode string of UTF-8.</param> /// <param name="errorCorrection">The QR code error correction level.</param> /// <returns>int</returns> internal static QRCodeVersion GetMinVersionForBinaryMode(string textUTF8, QRCodeErrorCorrection levelCorrection) { // Validation if (string.IsNullOrEmpty(textUTF8)) { throw new ArgumentException(nameof(textUTF8)); } if (!Enum.IsDefined(typeof(QRCodeErrorCorrection), levelCorrection)) { throw new ArgumentException(nameof(levelCorrection)); } for (int version = 0; version < 40; version++) { int bitsCountFullSizeOfHeader = version < 10 ? 16 : 24; int bitsFullSizeOfData = (new UTF8Encoding().GetBytes(textUTF8).Length << 3) + bitsCountFullSizeOfHeader; if (QRCodesData.QRCodeMaxLengths[version][(int)levelCorrection] >= bitsFullSizeOfData) { return((QRCodeVersion)(version + 1)); } } throw new InvalidOperationException(); }
/// <summary> /// Generates a QR code with specified error correction level, version, pixel scaling, color, background color, and quiet zone from the input data and returns the QR code image as an array of bytes. /// </summary> /// <param name="data">The user data for encoding.</param> /// <param name="encoding">The QR code encoding.</param> /// <param name="levelCorrection">The level of error correction.</param> /// <param name="version">The QR code version.</param> /// <param name="scaleMultiplier">The pixel scaling of the resulting QR code image.</param> /// <param name="foregroundColor">The QR code color.</param> /// <param name="backgroundColor">The background color.</param> /// <param name="hasQuietZones">Defines whether the QR code has a "quiet zone".</param> /// <returns>byte[]</returns> public static byte[] GetQRCode(string data, QRCodeEncodingMethod encoding, QRCodeErrorCorrection levelCorrection, QRCodeVersion version, int scaleMultiplier, Color foregroundColor, Color backgroundColor, bool hasQuietZones = true) { // Validation if (string.IsNullOrEmpty(data)) { throw new ArgumentException(nameof(data)); } if (!Enum.IsDefined(typeof(QRCodeEncodingMethod), encoding)) { throw new ArgumentException(nameof(encoding)); } if (!Enum.IsDefined(typeof(QRCodeErrorCorrection), levelCorrection)) { throw new ArgumentException(nameof(levelCorrection)); } if (!Enum.IsDefined(typeof(QRCodeVersion), version)) { throw new ArgumentOutOfRangeException(nameof(version)); } if (scaleMultiplier <= 0) { throw new ArgumentOutOfRangeException(nameof(scaleMultiplier)); } // Results return(QRCodesRenderer.GetQRCodeImage(data, encoding, levelCorrection, version, scaleMultiplier, foregroundColor, backgroundColor, hasQuietZones ? 4 : 0)); }
private static void AddLevelAndMaskCodes(Bitmap image, int numberMask, QRCodeErrorCorrection levelCorrection, int sizeCanvas, Color foregroundColor, int margin) { int code = QRCodesData.CodeMaskAndLevels[8 * ((int)levelCorrection) + numberMask]; for (int i = 0; i < 15; i++) { if (((code >> i) & 1) == 1) { if (i < 6) { SetPixelToBitmap(image, 8, i, margin, foregroundColor); SetPixelToBitmap(image, sizeCanvas - i - 1, 8, margin, foregroundColor); } else if (i < 8) { SetPixelToBitmap(image, 8, i + 1, margin, foregroundColor); SetPixelToBitmap(image, sizeCanvas - i - 1, 8, margin, foregroundColor); } else if (i < 9) { SetPixelToBitmap(image, 8, sizeCanvas - 7, margin, foregroundColor); SetPixelToBitmap(image, 7, 8, margin, foregroundColor); } else { SetPixelToBitmap(image, 5 - (i - 9), 8, margin, foregroundColor); SetPixelToBitmap(image, 8, sizeCanvas - 7 + (i - 8), margin, foregroundColor); } } } SetPixelToBitmap(image, 8, sizeCanvas - 8, margin, foregroundColor); }
/// <summary> /// Generates a QR code with the automatically defined version and specified error correction level, pixel scaling, color, background color, and quiet zone from the input data and returns the QR code image as an array of bytes. /// </summary> /// <param name="data">The user data for encoding.</param> /// <param name="encoding">The QR code encoding.</param> /// <param name="levelCorrection">The level of error correction.</param> /// <param name="scaleMultiplier">The pixel scaling of the resulting QR code image.</param> /// <param name="foregroundColor">The QR code color.</param> /// <param name="backgroundColor">The background color.</param> /// <param name="hasQuietZones">Defines whether the QR code has a "quiet zone".</param> /// <returns>byte[]</returns> public static byte[] GetQRCode(string data, QRCodeEncodingMethod encoding, QRCodeErrorCorrection levelCorrection, int scaleMultiplier, Color foregroundColor, Color backgroundColor, bool hasQuietZones = true) { return(GetQRCode(data, encoding, levelCorrection, QRCodesUtils.GetMinVersionForBinaryMode(data, levelCorrection), scaleMultiplier, foregroundColor, backgroundColor, hasQuietZones)); }
/// <summary> /// Creates a QR code in the binary encoding. /// </summary> /// <param name="data">The user data for encoding.</param> /// <param name="version">The QR code version.</param> /// <param name="levelCorrection">The level of error correction.</param> /// <returns>byte[]</returns> public static byte[] EncodeQRCodeData(string data, int version, QRCodeErrorCorrection levelCorrection) { BitArray arrData; UTF8Encoding utf8 = new UTF8Encoding(); var arrBytes = utf8.GetBytes(data); byte codeMethod = MethodCode(QRCodeEncodingMethod.Binary); int lengthStandard = QRCodesData.QRCodeMaxLengths[version - 1][(int)levelCorrection]; arrData = new BitArray(lengthStandard); int bitsSaved = 0; // Write the header if (version < 10) { SaveByteToBitArray(ref arrData, codeMethod, 4); SaveByteToBitArray(ref arrData, (byte)arrBytes.Length); bitsSaved += 12; } else { SaveByteToBitArray(ref arrData, codeMethod, 4); SaveByteToBitArray(ref arrData, (byte)((arrBytes.Length >> 8) & 0xFF)); SaveByteToBitArray(ref arrData, (byte)(arrBytes.Length & 0xFF)); bitsSaved += 20; } // No space for data error if ((arrBytes.Length << 3) + bitsSaved + (bitsSaved % 8) > lengthStandard) { throw new InvalidOperationException(); } // Write the data foreach (var byteData in arrBytes) { SaveByteToBitArray(ref arrData, byteData); } // Align to full bytes size bitsSaved += arrBytes.Length << 3; int bitsTail = bitsSaved % 8; arrData = QRCodesUtils.LeftShift(arrData, bitsTail); AlignToFullSize(ref arrData, bitsSaved + bitsTail, lengthStandard); int countBlocks = QRCodesData.QRCodeBlockCounts[version - 1][(int)levelCorrection]; var lengthBlocks = GetLengthOfBlocks(lengthStandard, countBlocks); // Split the data into blocks var dataBlocks = GetBlocks(lengthBlocks, arrData); var countCorrection = QRCodesData.QRCodeCorrectionCounts[version - 1][(int)levelCorrection]; byte[] kCorrection = QRCodesData.QRCodeCorrectionK[(byte)countCorrection]; // Add correction codes to the blocks and return results return(AddCorrectionCodeToBlocks(dataBlocks, countCorrection, kCorrection)); }
public void TestErrorCorrectionOfQRCode(QRCodeErrorCorrection correctionLevel, string expectedHash, string caseName) { // Method 1 byte[] data = BarcodesMaker.GetQRCode("test", QRCodeEncodingMethod.Binary, correctionLevel, 1); string hash = CalculateImageCanvasHash(data); hash.Should().Be(expectedHash); // Method 2 data = BarcodesMaker.GetQRCode("test", QRCodeEncodingMethod.Binary, correctionLevel, QRCodeVersion.Version1, 1, Color.Black, Color.White); hash = CalculateImageCanvasHash(data); hash.Should().Be(expectedHash); Assert.True(true, caseName); }
/// <summary> /// Generates a QR code with the automatically defined version and specified error correction level and pixel scaling from the input data and returns the QR code image as an array of bytes. /// </summary> /// <param name="data">The user data for encoding.</param> /// <param name="encoding">The QR code encoding.</param> /// <param name="levelCorrection">The level of error correction.</param> /// <param name="scaleMultiplier">The pixel scaling of the resulting QR code image.</param> /// <returns>byte[]</returns> public static byte[] GetQRCode(string data, QRCodeEncodingMethod encoding, QRCodeErrorCorrection levelCorrection, int scaleMultiplier = 1) { return(GetQRCode(data, encoding, levelCorrection, scaleMultiplier, Color.Black, Color.White)); }
private static Bitmap CreateBitmap(byte[] dataBinary, int version, int numberMask, QRCodeErrorCorrection levelCorrection, Brush foregroundColor, Brush backgroundColor, int margin) { var foregroundBrush = (SolidBrush)foregroundColor; int sizeCanvas = 21 + 4 * (version - 1); int size = sizeCanvas + 2 * margin; var image = new Bitmap(size, size); var imageMaskQRCode = new Bitmap(size, size); // system zones // Create a base system template using (Graphics graph = Graphics.FromImage(image)) { using (Graphics graphMaskQRCode = Graphics.FromImage(imageMaskQRCode)) { graph.InterpolationMode = InterpolationMode.NearestNeighbor; graph.SmoothingMode = SmoothingMode.None; graph.PixelOffsetMode = PixelOffsetMode.Half; graph.PageUnit = GraphicsUnit.Pixel; graph.FillRectangle(backgroundColor, new RectangleF(0, 0, image.Width, image.Height)); AddTemplateToGraphics(graph, graphMaskQRCode, version, sizeCanvas, foregroundColor, backgroundColor, margin); AddLevelDataToMask(graphMaskQRCode, sizeCanvas, margin); } } // Add sync lines to the image AddSyncToImage(image, imageMaskQRCode, sizeCanvas, foregroundBrush, margin); // Add the version code to the image AddVersionDataToImage(image, imageMaskQRCode, version, sizeCanvas, foregroundBrush.Color, margin); // Add the data to the image AddBinaryDataToImage(image, imageMaskQRCode, dataBinary, sizeCanvas, foregroundBrush, numberMask, margin); // Add the code of the selected correction level and mask AddLevelAndMaskCodes(image, numberMask, levelCorrection, sizeCanvas, foregroundBrush.Color, margin); return(image); }
/// <summary> /// Renders a QR code on bitmap from the encoded data and returns an array of bytes. /// </summary> /// <param name="data">The user data for encoding.</param> /// <param name="encoding">The QR code encoding.</param> /// <param name="levelCorrection">The level of error correction.</param> /// <param name="version">The QR code version.</param> /// <param name="scaleMultiplier">The pixel scaling of the resulting QR code image.</param> /// <param name="foregroundColor">The QR code color.</param> /// <param name="backgroundColor">The background color.</param> /// <param name="quietZone">The size of the quiet zone.</param> /// <returns>byte[]</returns> internal static byte[] GetQRCodeImage(string data, QRCodeEncodingMethod encoding, QRCodeErrorCorrection levelCorrection, QRCodeVersion version, int scaleMultiplier, Color foregroundColor, Color backgroundColor, int quietZone = 4) { if (!Enum.IsDefined(typeof(QRCodeVersion), version)) { throw new ArgumentOutOfRangeException(); } // Only the binary method is implemented if (encoding != QRCodeEncodingMethod.Binary) { throw new NotImplementedException(); } int numVersion; if (version == QRCodeVersion.Automatic) { numVersion = (int)QRCodesUtils.GetMinVersionForBinaryMode(data, levelCorrection); } else { numVersion = (int)version; } var numberMask = 4; // Get the image data array byte[] dataBinary = QRCodesEncoder.EncodeQRCodeData(data, numVersion, levelCorrection); // Create a bitmap for the QR code var bitmapSource = CreateBitmap(dataBinary, numVersion, numberMask, levelCorrection, new SolidBrush(foregroundColor), new SolidBrush(backgroundColor), quietZone); // Pixel scaling var bitmap = QRCodesUtils.Scale(bitmapSource, scaleMultiplier); // Save the resulting image in the PNG format var memStream = new MemoryStream(); bitmap.Save(memStream, System.Drawing.Imaging.ImageFormat.Png); memStream.Flush(); var qrData = memStream.ToArray(); memStream.Close(); return(qrData); }