Julian Popov
Julian Popov

Reputation: 17461

Reportlab's Code128 Barcode as HTML Image Tag with Data URI Scheme in Python

I need to create an Code128 Barcodes with Python/Django which have to be embeded in HTML document.

I don't want to make any temporary (or cache) files on the disk. That's why I want to embed them as Data URI Scheme.

The result have to be something like this:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot">

Can you recommend me an easy way to do this?

Now I use ReportLab to create such a barcodes and embed them in PDF files, but I don't know how to export them as Data URI Scheme. If this is the recommended way to do this.

Upvotes: 8

Views: 8570

Answers (4)

Ehvince
Ehvince

Reputation: 18375

To fellow googlers: the suggested solution doesn't rely on ReportLab, we can include a barcode in our html template from its base64 representation, given we already have image created with another library:

data_uri = open("sample.png", "rb").read().encode("base64").replace("\n", "")
# HTML Image Element
img_tag = '<img alt="" src="data:image/png;base64,{0}">'.format(data_uri)
print img_tag
# CSS Background Image
css = 'background-image: url(data:image/png;base64,{0});'.format(data_uri)
print css

Upvotes: 0

Brian Anderson
Brian Anderson

Reputation: 1766

Have you tried assembling the barcode on the fly with each symbol represented with its own image data? Here's an example:

<img alt="105,{Start C}" title="105,{Start C}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/ACxgALsAjajKmzkAAAAASUVORK5CYII=" width="30" height="60"><img alt=" 00,A:{space},B:{space}" title=" 00,A:{space},B:{space}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/ACZgAK8Ah/KrWu0AAAAASUVORK5CYII=" width="30" height="60"><img alt=" 98,A:{Escape B},B:{Escape A}" title=" 98,A:{Escape B},B:{Escape A}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/AAugALkArBSbglwAAAAASUVORK5CYII=" width="30" height="60"><img alt=" 21,A:{5},B:{5}" title=" 21,A:{5},B:{5}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/ACNgAKkAhD/i5lYAAAAASUVORK5CYII=" width="30" height="60"><img alt=" 14,A:{.},B:{.}" title=" 14,A:{.},B:{.}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/AGYgAO8Ah9WahQgAAAAASUVORK5CYII=" width="30" height="60"><img alt=" 00,A:{space},B:{space}" title=" 00,A:{space},B:{space}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/ACZgAK8Ah/KrWu0AAAAASUVORK5CYII=" width="30" height="60"><img alt=" 14,A:{.},B:{.}" title=" 14,A:{.},B:{.}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/AGYgAO8Ah9WahQgAAAAASUVORK5CYII=" width="30" height="60"><img alt=" 64,A:{NUL},B:{}" title=" 64,A:{NUL},B:{}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/AF5gAR8Av0A69KoAAAAASUVORK5CYII=" width="30" height="60"><img alt=" 95,A:{US},B:{DEL}" title=" 95,A:{US},B:{DEL}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/AELgAWcBIz+IUR4AAAAASUVORK5CYII=" width="30" height="60"><img alt=" 07,A:{'},B:{'}" title=" 07,A:{'},B:{'}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/AGdgATEAyJ/9LboAAAAASUVORK5CYII=" width="30" height="60"><img alt=" 74,A:{LF},B:{j}" title=" 74,A:{LF},B:{j}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/AHmgAZUBGuCD0Y8AAAAASUVORK5CYII=" width="30" height="60"><img alt="101,A:{FNC 4},B:{Switch A},C:{Switch A}" title="101,A:{FNC 4},B:{Switch A},C:{Switch A}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/ABQgAEsANWhuDt4AAAAASUVORK5CYII=" width="30" height="60"><img alt=" 25,A:{9},B:{9}" title=" 25,A:{9},B:{9}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/ABpgAJcAex9glyQAAAAASUVORK5CYII=" width="30" height="60"><img alt=" 12,A:{,},B:{,}" title=" 12,A:{,},B:{,}" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAABAQMAAAAy+cYDAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/AExgAPsArevKOWsAAAAASUVORK5CYII=" width="30" height="60"><img alt="106,{Stop}"title="106,{Stop}"src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAABAQMAAAA/57ZEAAAABlBMVEUAAAD///+l2Z/dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAADklEQVQIHQEDAPz/ADigARMA2dpJzT8AAAAASUVORK5CYII=" width="30" height="60">
009821140014649507749

This represents the same barcode as your example, but requires no intermediate graphics and takes up about a third of the space. The data used to comprise the image can be accessed from an array and used to populate the target HTML with Javascript or another client or server-side application.

You can find a complete list of Code 128 symbols at http://notionovus.com/blog/code-128-barcode/

I am not sure about rotation. I haven't tried that yet.

Upvotes: 1

Julian Popov
Julian Popov

Reputation: 17461

This is my own solution:

from base64 import b64encode
from reportlab.lib import units
from reportlab.graphics import renderPM
from reportlab.graphics.barcode import createBarcodeDrawing
from reportlab.graphics.shapes import Drawing

def get_barcode(value, width, barWidth = 0.05 * units.inch, fontSize = 30, humanReadable = True):

    barcode = createBarcodeDrawing('Code128', value = value, barWidth = barWidth, fontSize = fontSize, humanReadable = humanReadable)

    drawing_width = width
    barcode_scale = drawing_width / barcode.width
    drawing_height = barcode.height * barcode_scale

    drawing = Drawing(drawing_width, drawing_height)
    drawing.scale(barcode_scale, barcode_scale)
    drawing.add(barcode, name='barcode')

    return drawing

def get_image():

    barcode = get_barcode(value = '01234567890', width = 600)
    data = b64encode(renderPM.drawToString(barcode, fmt = 'PNG'))
    print '<img src="data:image/png;base64,{0}">'.format(data)

And also you can get barcode rotated by 90°:

def get_barcode_rotated(value, width, barWidth = 0.05 * units.inch, fontSize = 30, humanReadable = True):

    barcode = createBarcodeDrawing('Code128', value = value, barWidth = barWidth, fontSize = fontSize, humanReadable = humanReadable)

    drawing_width = width
    barcode_scale = drawing_width / barcode.width
    drawing_height = barcode.height * barcode_scale

    drawing = Drawing(drawing_width, drawing_height)
    drawing.scale(barcode_scale, barcode_scale)
    drawing.add(barcode, name='barcode')

    drawing_rotated = Drawing(drawing_height, drawing_width)
    drawing_rotated.rotate(90)
    drawing_rotated.translate(0, -drawing_height)
    drawing_rotated.add(drawing, name='drawing')

    return drawing_rotated

Here is an example result:

http://pastehtml.com/view/ci7qei4k1.html

Upvotes: 13

Marwan Alsabbagh
Marwan Alsabbagh

Reputation: 26778

This should do the trick. I used the Code128 python module to generate the barcodes.

code

from Code128 import Code128
from base64 import b64encode

val = "9782212110708"
Code128().getImage(val, path="./")
data = b64encode(open(val + '.png').read())
print '<img src="data:image/png;base64,{0}">'.format(data)

output

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIMAAAAyAQAAAABXcFUb
AAAAjklEQVR4nGP8r2v6J/ihYotFKrs5qx9H2TwmBnQwKjIqMnRFGP+jCTzErkvS6IR80Yu5iScU
GBgYGFgYGP4b3j6t9Xn+ZG4jA6gIAxtDos26ROHFcF2M+32/XPjLwPCX8QLMnAOfXyz4xcDA8B+m
63/djHUCHxkYfkEt+///v8zHJg6GBpbi4/L///9/AADHAS8/nZ4QEQAAAABJRU5ErkJggg==">

UPDATE

there was a nice suggestion in the comments to modify the Code128 module so that it doesn't have to save the image to the filesystem. You can change Code128 so that it returns you the image object instead of saving it to a file. You would only need to change one line of code to achieve this. Change line 162 from:

im.save(path+value+"."+lower(extension), upper(extension))

to:

return im

Upvotes: 5

Related Questions