qrpoc/qrpoc.py

115 lines
3.3 KiB
Python

from io import BytesIO, IOBase
import qrcode
import cairo
from gi.repository import PangoCairo as pangocairo
from gi.repository import Pango as pango
DPI = 300
INCH_PER_MM = 0.039
def separate_context(func):
def inner(self, *args, **kwargs):
self.context.save()
ret = func(self, *args, **kwargs)
self.context.restore()
return ret
return inner
class Image:
_ctx = None
def __init__(self, width, height, color=None):
self.width = int(width)
self.height = int(height)
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.width, self.height)
if color:
self.fill(color)
@property
def context(self):
if not self._ctx:
self._ctx = cairo.Context(self.surface)
return self._ctx
@separate_context
def fill(self, color):
self.rect(0, 0, self.width, self.height, color)
@separate_context
def rect(self, x, y, width, height, color=(0, 0, 0)):
self.context.rectangle(x, y, width, height)
self.context.set_source_rgb(*color)
self.context.fill()
@separate_context
def draw_text(self, text, x, y, width=None, height=None, size=25, font='arial 25', color=(0,0,0)):
width = width or self.width-x
height = height or self.height-y
self.context.set_source_rgb(*color)
self.context.rectangle(x, y, self.width, height)
font = pango.FontDescription(font)
layout = pangocairo.create_layout(self.context)
layout.set_width(width * pango.SCALE)
layout.set_text(text, -1)
layout.set_font_description(font)
pangocairo.update_layout(self.context, layout)
pangocairo.show_layout(self.context, layout)
def save(self, name_or_file):
self.surface.write_to_png(name_or_file)
if isinstance(name_or_file, IOBase):
name_or_file.seek(0)
def compose(self, image, x=0, y=0, width=None, height=None):
self.context.scale(width/image.width, height/image.height)
self.context.set_source_surface(image.surface, x, y)
self.context.paint()
class QRCairo(qrcode.image.base.BaseImage):
@staticmethod
def _map_color(color):
return {'white': (1, 1, 1),
'black': (0, 0, 0)}[color]
def new_image(self, **kwargs):
back_color = self._map_color(kwargs.get("fill_color", "white"))
fill_color = self._map_color(kwargs.get("back_color", "black"))
self.fill_color = fill_color
return Image(self.pixel_size, self.pixel_size, back_color)
def drawrect(self, row, col):
(x, y), (x2, y2) = self.pixel_box(row, col)
self._img.rect(x, y, self.box_size, self.box_size, self.fill_color)
def save(self, fobj):
self._img.save(fobj)
def make_qr(url, size=19):
size = DPI*INCH_PER_MM*size
q = qrcode.QRCode(version=6, error_correction=qrcode.ERROR_CORRECT_M, border=0)
q.add_data(url)
q.make()
img = q.make_image(image_factory=QRCairo)
return img
def make_label(text, url, dpi=DPI):
qr = make_qr(url)
dpm = dpi*INCH_PER_MM
img = Image(51*dpm, 19*dpm, (1, 1, 1))
img.draw_text(text, 19.5*dpm, 0)
qr_img = qr._img
img.compose(qr_img, 0, 0, int(19*dpm), int(19*dpm))
return img
io = BytesIO()
make_label('ebin xD', 'http://www.wykop.pl/').save('output.png')