11

I use ZXing.Net library to generate a QR code image -

app screenshot

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:

Wikipedia

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.

Alexander Farber
  • 21,519
  • 75
  • 241
  • 416
  • 1
    I don't know the libs but this is not text, this is an image, you should look in this direction – Thomas Ayoub Jun 25 '15 at 15:09
  • Yes, sure the final output is an image - but I am after any methods in ZXing library to add custom text or images inside of the generated QR. Also, I can not just put my image on top of the QR and then just hope it is still readable thanks to error correction (as some blogs suggest) - because my QR is dynamically generated and contains (variable) Bluetooth address + more stuff. – Alexander Farber Jun 25 '15 at 16:13
  • What I meant is that there is no method to add text, there is just a method to add image in your qrcode, like wikipedia put the wikipedia logo and not the text `wikipedia` – Thomas Ayoub Jun 25 '15 at 17:26

2 Answers2

18

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:

enter image description here

And the output:

True

Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
  • 1
    It is great code, thanks (+1) but is missing the validation of the resulting bitmap... (i.e. if `bm` is still being a valid QR-code) – Alexander Farber Jun 26 '15 at 10:28
  • Wouldn't `return result.Text == url` throw an exception if decoding fails (I am C# newbie)? Shouldn't it better be written as `return result != null && result.Text == url`? – Alexander Farber Jun 26 '15 at 11:01
  • 1
    Isn't `result.Text == url` just comparing string addresses? Shouldn't you better call `url.Equals(result.Text)` to compare string contents? – Alexander Farber Jun 26 '15 at 11:07
  • 1
    @AlexanderFarber you [can](http://stackoverflow.com/questions/814878/c-sharp-difference-between-and-equals) but that's not an obligation for strings – Thomas Ayoub Jun 26 '15 at 11:10
  • @ThomasAyoub Whats the purpose of the "PureBarcode" property? In the documentation is says: " Don't put the content string into the output image." That's not very clear! – pmeyer Jun 05 '17 at 14:27
2

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();
Community
  • 1
  • 1
Ian Newson
  • 7,679
  • 2
  • 47
  • 80