Search code examples
pythonpython-3.xpython-imaging-libraryqr-code

Creating QR code containing both text and photo


It is possible to create a QR code which contains both some text and photo (which is small logo) in python?

I mean text, which is not part of the photo. But I will have separately text (string variable) and photo (e.g. *.png).

So far I saw only the examples where it was possible to create a QR code from text or photo. I couldn't find example with both used at the same time.

Basically when I scan my QR code, I would like for it to show my photo (logo) and text information.


Solution

  • Expanding on my comment. QR Codes are used to encode text. So you have to read in your image, convert to base64, append your string with some delimiter and then write out your QR code.

    Because we took special steps to encode the data (the image and the string) before storing in a QR code, we must also have a special application to read the QR code, split the base64 string by our delimiter, and then decode the base64 pieces into their appropriate media (writing the binary to a file for the image and printing out the decoded string).

    All in all this will look something like the following:

    import base64
    
    #open image and convert to b64 string
    with open("small.png", "rb") as img_file:
        my_string = base64.b64encode(img_file.read())
    
    #append a message to b64 encoded image
    my_string = my_string + b'\0' + base64.b64encode(b'some text')
    
    #write out the qrcode
    import qrcode
    qr = qrcode.QRCode(
        version=2,
        error_correction=qrcode.constants.ERROR_CORRECT_M,
    )
    qr.add_data(my_string, optimize=0)
    qr.make()
    qr.make_image().save("qrcode.png")
    
    #--------Now when reading the qr code:-------#
    #open qr code and read in with cv2 (as an example), decode with pyzbar
    from pyzbar.pyzbar import decode
    import cv2 #importing opencv
    img = cv2.imread('qrcode.png', 0) 
    barcodes = decode(img)
    
    for barcode in barcodes:
        barcodeData = barcode.data.decode("utf-8")
    
    #split the b64 string by the null byte we wrote
    data = barcodeData.split('\x00')
    
    #save image to file after decoding b64
    filename = 'some_image.jpg'  
    with open(filename, 'wb') as f:
        f.write(base64.b64decode(data[0]))
    
    #print out message after decoding
    print(base64.b64decode(data[1]))
    

    Obviously this is only going to work for a VERY small image and just a little bit of text. You quickly blow out the max size of a QR code, and even before you hit the limits for the standard, you'll hit the limits for qrcode and pyzbar modules.

    With this, you can start with a tiny image like:

    enter image description here

    And after encoding and appending text, have a qr code like:

    enter image description here

    And end up with the exact same picture and your appended text

    Ultimately this really isn't terribly useful though since you have to have a special application to decode your QR code. The more traditional method of creating a web page with the content you want to share along with a qr code containing a link to the page, is a more user-friendly and approachable method to solving this.