How to fix QR code generation using ZXing.Net lib - c#

It is necessary to generate a QR code from the text. I'm using the ZXing.unity.dll library
using ZXing;
using ZXing.QrCode;
Generating QR code
private static Color32[] Encode(string textForEncoding, int width, int height) {
var writer = new BarcodeWriter {
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions{
Height = height,
Width = width
}
};
return writer.Write(textForEncoding);
}
public Texture2D generateQR(string text) {
var encoded = new Texture2D (256, 256);
var color32 = Encode(text, encoded.width, encoded.height);
encoded.SetPixels32(color32);
encoded.Apply();
return encoded;
}
Applying the generated QR to the RawImage filled in the field
public RawImage RI;
...
RI.texture = generateQR("https://test.link/123");
The output is a picture with large white edges.
QR code preview pic
Q1 - How to remove white edges;
Q2 - How to make a transparent background;
Q3 - How to change black color to any other

Q3: Sample for changing foreground and background color:
private static Color32[] Encode(string textForEncoding, int width, int height)
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions
{
Height = height,
Width = width
},
Renderer = new Color32Renderer
{
Background = new Color32(255, 0, 0, 0),
Foreground = new Color32(0, 255, 0, 0)
}
};
return writer.Write(textForEncoding);
}
Q2: I' not absolutely sure, but the following sample should create a transparent background:
private static Color32[] Encode(string textForEncoding, int width, int height)
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions
{
Height = height,
Width = width
},
Renderer = new Color32Renderer
{
Background = new Color32(0, 0, 0, 255)
}
};
return writer.Write(textForEncoding);
}
Q1: create the image as small as possible without a border and resize it manually
private static Color32[] Encode(string textForEncoding, int width, int height)
{
var writer = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new QrCodeEncodingOptions
{
Height = width,
Width = height,
Margin = 0
}
};
return writer.Write(textForEncoding);
}
public Texture2D generateQR(string text)
{
// create the image as small as possible without a white border by setting width an height to 1
var color32 = Encode(text, 1, 1);
var widthAndHeight = color32.Length / 2;
var encoded = new Texture2D(widthAndHeight, widthAndHeight);
encoded.SetPixels32(color32);
encoded.Apply();
//
// Attention: insert code for resizing to the desired size here
// I didn't try it myself. Not sure if it works.
//
encoded.Resize(256, 256);
return encoded;
}

Related

How to convert text to image using Win2D in a UWP Desktop application?

I have a UWP Desktop application in which I need to transform a few lines of text into an image and then use that image in other operations. How do I do this? Any help is most welcome. Thanks.
private Image TextToImage(string text, float width, float height)
{
CanvasDevice device = CanvasDevice.GetSharedDevice();
CanvasRenderTarget renderTarget = new CanvasRenderTarget(device, width, height, 96);
using (var ds = renderTarget.CreateDrawingSession())
{
ds.Clear(Colors.White);
using (var format = new CanvasTextFormat())
{
format.FontFamily = "Segoe UI";
format.FontSize = 18;
format.WordWrapping = CanvasWordWrapping.Wrap;
format.TrimmingGranularity = CanvasTextTrimmingGranularity.None;
format.HorizontalAlignment = CanvasHorizontalAlignment.Left;
ds.DrawText(text, 0, 0, Colors.Black, format);
}
}
return ?????;
}

Sporadical weird text while writing on bitmap

I am looking for some explanation about some weird texts that appears when I write on a bitmap and then upload it to azure blob.
Sometimes when I create an imagem, it comes with theses weird texts where there should be accents. But I recreate it right after and it works...
Here is the imagem gone wrong: https://www.dropbox.com/s/8an62ygys5nnwow/uploaded-image-636488352376069747.png?dl=0
And here is the correct image:
https://www.dropbox.com/s/q3sdsqo3d05skz8/uploaded-image-636493880034621618.png?dl=0
I convert the image url to bitmap:
var request = System.Net.WebRequest.Create(url);
var response = request.GetResponse();
using (var responseStream = response.GetResponseStream())
{
var bitmap = new Bitmap(responseStream);
return bitmap;
}
And then I write the text on it:
private void AddText(System.Drawing.Image image, string text, int x, int y, int width, int height, int fontSize, Color fontColor, Color borderColor, FontFamily fontFamily, FontStyle fontStyle, StringAlignment horizontalAligment, StringAlignment verticalAligment, bool autoFit, int shadowOffsetX, int shadowOffsetY, Color shadowColor, int? maxHeight, out float finalHeight, out float finalWidth)
{
var graphics = Graphics.FromImage(image);
graphics.SmoothingMode = SmoothingMode.AntiAlias;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
var rect = new Rectangle(x, y, width, height);
StringFormat stringFormat = new StringFormat
{
Alignment = horizontalAligment,
LineAlignment = verticalAligment
};
var font = new System.Drawing.Font(fontFamily, graphics.DpiY * fontSize / 72, fontStyle);
if (autoFit)
{
font = FindFont(graphics, text, rect.Size, font);
}
var hasShadow = shadowOffsetX > 0 && shadowOffsetY > 0;
var hasMaxHeight = maxHeight != null && maxHeight.Value > 0;
if (hasShadow)
{
var shadowGraphicsPath = new GraphicsPath();
var shadowRect = new Rectangle(x + shadowOffsetX, y + shadowOffsetY, width, height);
shadowGraphicsPath.AddString(text, fontFamily, (int)fontStyle, font.Size, shadowRect, stringFormat);
if (hasMaxHeight)
{
shadowGraphicsPath = GetTextWithMaxHeight(text, fontFamily, fontStyle, shadowRect, stringFormat, shadowGraphicsPath, font, maxHeight.Value, out float newFontSize);
font = new System.Drawing.Font(font.FontFamily, newFontSize);
}
graphics.FillPath(new SolidBrush(shadowColor), shadowGraphicsPath);
graphics.Flush();
shadowGraphicsPath.Dispose();
}
var graphicsPath = new GraphicsPath();
graphicsPath.AddString(text, fontFamily, (int)fontStyle, font.Size, rect, stringFormat);
if (hasMaxHeight && !hasShadow)
{
graphicsPath = GetTextWithMaxHeight(text, fontFamily, fontStyle, rect, stringFormat, graphicsPath, font, maxHeight.Value, out float newFontSize);
}
graphics.DrawPath(new Pen(borderColor), graphicsPath);
graphics.FillPath(new SolidBrush(fontColor), graphicsPath);
finalHeight = graphicsPath.GetBounds().Height;
finalWidth = graphicsPath.GetBounds().Width;
graphics.Flush();
graphicsPath.Dispose();
}
And then I upload to azure blob
var container = _blobClient.GetContainerReference(_imageConfiguration.BlobContainer);
var blockBlob = container.GetBlockBlobReference($"uploaded-image-{DateTime.Now.ToUniversalTime().Ticks}.png");
using (var imageStream = ConvertToStream(image, ImageFormat.Png))
{
blockBlob.UploadFromStream(imageStream);
var uri = blockBlob.Uri;
return uri;
}
Can someone help me find an explanation for this?

ZXing-Core BitMatrix to BitMap

I am using ZXing-Core(0.14.0.2) to create a barcode which gives me a BitMatrix, however I have not found documentation as to how to extract the image part from the BitMatrix and use it as BitMap so I can incorporate in my bigger image. Eventually what I would like to end up with would be something like this:
The code I currently have is:
img = new Bitmap(300, 375);
drawing = Graphics.FromImage(img);
var barCode = new Code128Writer().encode(packageModel.TrackingId.PrintValue, BarcodeFormat.CODE_128, 280, 70);
src = transform **barCode** to **Drawing.Image**
drawing.DrawImage(src, new Rectangle(10, 255, 280, 70));
UPDATE
I now have this code, however I am getting an error You have to set a renderer instance. I dont understand why the interface is not instantiating this class by itself. There is not documentation available revealing how this is supposed to work. I cant use the Write functions because the Rendering is set to null, however I am not sure how to instantiate it.
IBarcodeWriterGeneric<Image> barcodeWriterGeneric = new BarcodeWriterGeneric<Image>
{
Format = BarcodeFormat.CODE_128,
Options = new EncodingOptions
{
Width = 280,
Height = 70
},
Renderer = new PixelData() //HOW DOES THE RENDERER WORK????
};
var test = barcodeWriterGeneric.Write("WORKS");
drawing.DrawImage(test, new Rectangle(10, 255, 280, 70));
Create a renderer that implements IBarcodeRenderer<TOut>. This one works for me in iOS.
var writer = new BarcodeWriter<UIImage>()
{
Format = ZXing.BarcodeFormat.CODE_128,
Options = new EncodingOptions
{
Height = height,
Width = width,
Margin = 0
},
Renderer = new BarcodeRenderer()
};
var image = writer.Write(barcodeValue);
private class BarcodeRenderer : IBarcodeRenderer<UIImage>
{
public UIImage Render(BitMatrix matrix, ZXing.BarcodeFormat format, string content)
{
return RenderMatrix(matrix);
}
public UIImage Render(BitMatrix matrix, ZXing.BarcodeFormat format, string content, EncodingOptions options)
{
return RenderMatrix(matrix);
}
}
/// <summary>
/// Renders the bitmatrix.
/// </summary>
private static UIImage RenderMatrix(BitMatrix matrix)
{
var width = matrix.Width;
var height = matrix.Height;
var black = new CGColor(0f, 0f, 0f);
var white = new CGColor(1.0f, 1.0f, 1.0f);
UIGraphics.BeginImageContext(new CGSize(width, height));
var context = UIGraphics.GetCurrentContext();
for (var x = 0; x < width; x++)
{
for (var y = 0; y < height; y++)
{
context.SetFillColor(matrix[x, y] ? black : white);
context.FillRect(new CGRect(x, y, 1, 1));
}
}
var img = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
return img;
}
As far as I can see the ZXing-Core fork is missing the PixelDataRenderer class. It contains only the RawRenderer. You should switch to the original ZXing.Net package with the current version 0.15.0. That one contains the barcode writer class "BarcodeWriterPixelData" which does the necessary initialization of the Renderer property. Next version of ZXing.Net will contain some more specialized bindings to other .Net Core compatible imaging libraries like CoreCompat.System.Drawing, ImageSharp, OpenCV and more. With that bindings you can then generate other output formats besides PixelData.

Add custom image or text to QR code generated by ZXing.Net

I use ZXing.Net library to generate a QR code image -
At the top of my class:
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
My method:
protected void UpdateQRSource(String address)
{
QRCodeWriter qrcode = new QRCodeWriter();
BarcodeWriter barcodeWriter = new BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new EncodingOptions
{
Width = 300,
Height = 300,
Margin = 4
}
};
using (Bitmap bitmap = barcodeWriter.Write(address))
{
IntPtr hbmp = bitmap.GetHbitmap();
try
{
BitmapSource source = Imaging.CreateBitmapSourceFromHBitmap(
hbmp,
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
qrImage.Source = source; // set WPF image source
}
finally
{
DeleteObject(hbmp);
}
}
}
Please advise me how to add short text string or a custom image in the middle of the QR code - similar to the Wikipedia visual QR code below:
UPDATE:
Embedding custom logo in QR code (without breaking the latter!) seems to be not a trivial task as the scientific publication QR Images: Optimized Image Embedding in QR Codes shows...
But I still wonder if I could generate a QR code (as in the above source code), then overlay it with a custom text or logo, then validate the resulting image again by ZXing.Net.
Here we go (you can use any logo):
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using ZXing;
using ZXing.QrCode.Internal;
using ZXing.Rendering;
namespace Test
{
public partial class Form1 : Form
{
private string imagePath = #"YourPath";
private string url = #"https://en.WIKIPEDIA.ORG/";
private int size = 400;
public Form1()
{
InitializeComponent();
pictureBox1.Image = GenerateQR(size, size, url);
pictureBox1.Height = size;
pictureBox1.Width = size;
Console.WriteLine(checkQR(new Bitmap(pictureBox1.Image)));
}
public bool checkQR(Bitmap QrCode)
{
var reader = new BarcodeReader();
var result = reader.Decode(QrCode);
if (result == null)
return false;
return result.Text == url;
}
public Bitmap GenerateQR(int width, int height, string text)
{
var bw = new ZXing.BarcodeWriter();
var encOptions = new ZXing.Common.EncodingOptions
{
Width = width,
Height = height,
Margin = 0,
PureBarcode = false
};
encOptions.Hints.Add(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
bw.Renderer = new BitmapRenderer();
bw.Options = encOptions;
bw.Format = ZXing.BarcodeFormat.QR_CODE;
Bitmap bm = bw.Write(text);
Bitmap overlay = new Bitmap(imagePath);
int deltaHeigth = bm.Height - overlay.Height;
int deltaWidth = bm.Width - overlay.Width;
Graphics g = Graphics.FromImage(bm);
g.DrawImage(overlay, new Point(deltaWidth/2,deltaHeigth/2));
return bm;
}
}
The result:
And the output:
True
Since you get a bitmap out of ZXing you can use standard C# techniques to draw text. See this answer for more info:
c# write text on bitmap
For posterity here's some shamelessly copied code:
Bitmap bmp = //from ZXing;
RectangleF rectf = new RectangleF(70, 90, 90, 50);
Graphics g = Graphics.FromImage(bmp);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
g.DrawString("yourText", new Font("Tahoma",8), Brushes.Black, rectf);
g.Flush();

How to change the QR Code version from 3 to 10 in ZXing

I have created an application which generates me a qr code image with ZXing library, but it uses version 3 for the qr code and I want to know if I can change it to version 10...I am new to the ZXing library...
This is the code:
public void CreateQRImage(string inputData)
{
if (radioRH.Checked)
{
if (inputData.Trim() == String.Empty)
{
System.Windows.Forms.MessageBox.Show("Data must not be empty.");
}
BarcodeWriter qrcoder = new ZXing.BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new ZXing.QrCode.QrCodeEncodingOptions
{
ErrorCorrection = ZXing.QrCode.Internal.ErrorCorrectionLevel.H,
Height = 250,
Width = 250
}
};
string tempFileName = System.IO.Path.GetTempPath() + inputData + ".png";
Image image;
String data = inputData;
var result = qrcoder.Write(inputData);
image = new Bitmap(result);
image.Save(tempFileName);
System.Diagnostics.Process.Start(tempFileName);
var textRes = qrcoder.Write(inputData);
int textWidth = 230, textHeight = 20;
// creating new bitmap having imcreased width
var img = new Bitmap(textRes.Width + textWidth, textRes.Height);
using (var g = Graphics.FromImage(img))
using (var font = new Font(FontFamily.GenericMonospace, 14))
using (var brush = new SolidBrush(Color.Black))
using (var bgBrush = new SolidBrush(Color.White))
using (var format = new StringFormat() { Alignment = StringAlignment.Near })
{
// filling background with white color
g.FillRectangle(bgBrush, 0, 0, img.Width, img.Height);
// drawing the generated image over new one
g.DrawImage(textRes, new Point(0, 0));
// drawing text
g.DrawString(inputData, font, brush, textRes.Width, (result.Height - textHeight) / 2, format);
}
img.Save(tempFileName);
}
I want the QR Code image to be changed from this (version 3)
To this (version 10)
I know this is an old question, but I recently had the same problem.
I was asked by my company to generate version 4 QR codes (33 by 33), but Zxing was defaulting to a lower version.
This is not documented hardly at all on the net, but there is a way to force Zxing to generate a specific version of QR code. In your code sample, just add "QrVersion = 10" to the format options:
BarcodeWriter qrcoder = new ZXing.BarcodeWriter
{
Format = BarcodeFormat.QR_CODE,
Options = new ZXing.QrCode.QrCodeEncodingOptions
{
ErrorCorrection = ZXing.QrCode.Internal.ErrorCorrectionLevel.H,
Height = 250,
Width = 250,
QrVersion = 10
}
};
This will produce a version-10 QR code.
**Note: If you set a low QrVersion number (for example, 4), then try to put lots of data into the QR code, an error will be thrown.

Categories