user2739418 user2739418 - 6 months ago 62
Vb.net Question

QR-Code custom size

How to create custom size QR-Code image

I am using https://qrcodenet.codeplex.com/ to generate QR codes

I am using following function to generate qr code

Public Function GenerateQRCode(URL As String, DarkColor As System.Drawing.Color, LightColor As System.Drawing.Color) As Bitmap
Dim Encoder As New Gma.QrCodeNet.Encoding.QrEncoder(Gma.QrCodeNet.Encoding.ErrorCorrectionLevel.L)
Dim Code As Gma.QrCodeNet.Encoding.QrCode = Encoder.Encode(URL)
Dim TempBMP As New Bitmap(Code.Matrix.Width, Code.Matrix.Height)
For X As Integer = 0 To Code.Matrix.Width - 1
For Y As Integer = 0 To Code.Matrix.Height - 1
If Code.Matrix.InternalArray(X, Y) Then TempBMP.SetPixel(X, Y, DarkColor) Else TempBMP.SetPixel(X, Y, LightColor)
Next
Next
Return TempBMP
End Function


To make a call as below:

Dim obj As New QRGenerator()
Dim img = obj.GenerateQRCode("www.google.co.uk", Drawing.Color.Black, Drawing.Color.Aqua)
img.Save(Context.Server.MapPath("images/stars_5.png"))


And then it generates the QR code as below:

enter image description here

The image size is very small (e.g. 21*21) I would like to have a bigger size (custom) e.g. 300*300 pixels.

I tried to override the Matrix.Width/Height but it does not work. Is there any way to create QR code in custom size?

Answer

If you only want the QR code as a file, there is no need to go throuh a Bitmap and set every pixel by yourself. The library you are using are supporting writing to stream.

C# example:

public static void WriteQrToFile(string url, Brush darkColor, Brush lightColor, int size, string filePath) {
    var encoder = new QrEncoder(ErrorCorrectionLevel.L);
    var code = encoder.Encode(url);
    var renderer = new GraphicsRenderer(new FixedCodeSize(size, QuietZoneModules.Zero), darkColor, lightColor);
    using (var fs = new FileStream(filePath, FileMode.Create))
        renderer.WriteToStream(code.Matrix, ImageFormat.Png, fs);
}

Note that you can also set the QuietZoneModules, to allow a border around your QR-code.
Note also that I changed from System.Drawing.Color to System.Drawing.Brush.
Usage:

var filePath = Context.Server.MapPath("images/stars_5.png");
WriteQrToFile("www.google.co.uk", Brushes.Black, Brushes.Aqua, 300, filePath);

However, if you need the Bitmap object for some reason, and want to go through the Bitmap and set every pixel yourself, here is a solution (albeit not optimal):

C# code:

public static Bitmap GenerateQrCode(string url, System.Drawing.Color darkColor, System.Drawing.Color lightColor, int size) {
    var encoder = new QrEncoder(ErrorCorrectionLevel.L);
    var code = encoder.Encode(url);
    if (size % code.Matrix.Width != 0 || size % code.Matrix.Height != 0)
        throw new InvalidOperationException("Width/Height not divisible with size");
    var multiplier = size / code.Matrix.Width;
    var tempBmp = new Bitmap(size, size);
    for (int x = 0; x < size; x++) {
        for (int y = 0; y < size; y++) {
            var originalX = x / multiplier;
            var originalY = y / multiplier;
            if (code.Matrix.InternalArray[originalX, originalY])
                tempBmp.SetPixel(x, y, darkColor);
            else
                tempBmp.SetPixel(x, y, lightColor);
        }
    }
    return tempBmp;
}

Usage would be the same as in your original code.

One thing to note here, is that this code requires the resulting QrCode-width and height to be divisible with the input size. You could add code to add your own QuietZone, if you wanted to.


Edit: As plutonix pointed out, the bitmap can also be generated from a stream. The resulting method would then look like this:

public static Bitmap GenerateQrCode(string url, Brush darkColor, Brush lightColor, int size) {
    var encoder = new QrEncoder(ErrorCorrectionLevel.L);
    var code = encoder.Encode(url);
    var renderer = new GraphicsRenderer(new FixedCodeSize(size, QuietZoneModules.Zero), darkColor, lightColor);
    using (var ms = new MemoryStream()) {
        renderer.WriteToStream(code.Matrix, ImageFormat.Png, ms);
        return new Bitmap(ms);
    }
}