Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Position the number below the barcode, using pyBarcode

Tags:

python

django

I'm using pyBarcode to generate PNGs and the number below the barcode is getting cut off on the right. How do I nudge it left a few pixels?

the number is getting cut off

According to the documentation I need to do something like this:

barcode.writer.BaseWriter(paint_text=my_callback)

And define a callback like this:

my_callback(xpos, ypos)

and:

use self.text as text

How exactly do I apply all of that to my Django view (below)?

def barcode(request):
    import barcode
    from barcode.writer import ImageWriter
    from cStringIO import StringIO

    def mm2px(mm, dpi=300):
        return (mm * dpi) / 25.4

    class MyImageWriter(ImageWriter):
        def calculate_size(self, modules_per_line, number_of_lines, dpi=300):
            width = 2 * self.quiet_zone + modules_per_line * self.module_width
            height = 1.0 + self.module_height * number_of_lines
            if self.text:
                height += (self.font_size + self.text_distance) / 3

            return int(mm2px(width, dpi)), int(mm2px(height, dpi))

    f = BarcodeForm(request.GET)
    if f.is_valid():
        try:
            i = StringIO()
            bc_factory = barcode.get_barcode_class(f.PYBARCODE_TYPE[f.cleaned_data['barcode_type']])
            bc_factory.default_writer_options['quiet_zone'] = 1.0
            bc_factory.default_writer_options['text_distance'] = 1.0
            bc_factory.default_writer_options['module_height'] = 15.0
            bc_factory.default_writer_options['module_width'] = 0.3
            bc_factory.default_writer_options['font_size'] = 46

            bc = bc_factory(f.cleaned_data['text'], writer=MyImageWriter())
            bc.write(i)
            return HttpResponse(i.getvalue(), mimetype='image/png')
        except Exception, e:
            return HttpResponseBadRequest(str(e))
    else:
        return HttpResponseBadRequest('Missing text or unsupported barcode type: %s' % f.errors)
like image 221
ram1 Avatar asked Nov 14 '22 20:11

ram1


1 Answers

Edit: After answering I noticed you've got a factory that's setting the quiet_zone to 1.0. Change that back to 6.5 and I'd imagine it will look fine.

Edit2: I misunderstood the exact problem you were experiencing.

For whatever reason the author of pyBarcode is putting the text centered in the middle of the bar code. When the render method calls _paint_text() it passes in xpos/2, which sets it in the middle of the barcode. I guess this is okay with the default font he's using, but when you increased the font, it no longer fits.

Instead I was able to place it on the left side, by overriding the _paint_text() method. In the last line below, the variable pos is just a tuple containing an (x,y) coordinate that tells PIL where to draw the text on the bar code. So I've made sure x is lined up with the bar code. If you need it right aligned, you could play around with the xpos variable to get it where you need.

Give this a shot:

class MyImageWriter(ImageWriter):
    def calculate_size(self, modules_per_line, number_of_lines, dpi=300):
        width = 2 * self.quiet_zone + modules_per_line * self.module_width
        height = 1.0 + self.module_height * number_of_lines
        if self.text:
            height += (self.font_size + self.text_distance) / 3

        return int(mm2px(width, dpi)), int(mm2px(height, dpi))

    def _paint_text(self, xpos, ypos):
        # this should align your font to the left side of the bar code:
        xpos = self.quiet_zone
        pos = (mm2px(xpos, self.dpi), mm2px(ypos, self.dpi))
        font = ImageFont.truetype(FONT, self.font_size)
        self._draw.text(pos, self.text, font=font, fill=self.foreground)
like image 170
Josh Avatar answered Dec 18 '22 11:12

Josh