Background is now white, export to png or pdf is possible

This commit is contained in:
Beat Jäckle 2021-12-19 08:39:14 +01:00
parent 29a7a66085
commit 308ccd5a6c
3 changed files with 69 additions and 38 deletions

View file

@ -1,4 +1,4 @@
# qrr-py # qrr.py
Erstelle ein vektorisierter QR Code für die [QR Rechnung]( Erstelle ein vektorisierter QR Code für die [QR Rechnung](
https://www.einfach-zahlen.ch/de/home/issuer/qr-bill.html). https://www.einfach-zahlen.ch/de/home/issuer/qr-bill.html).
@ -9,9 +9,10 @@ SVG Datei daraus.
## Installationsanleitung ## Installationsanleitung
Zuerst müssen Sie Python3 für Ihr Betriebssystem installieren. Zuerst müssen Sie [Python3](https://www.python.org/)
für Ihr Betriebssystem installieren.
Mit `pip3 install --user qrcode svgutils` können sie sich die Mit `pip3 install --user qrcode svgutils cairosvg` können sie sich die
notwendigen Pakete herunterladen. notwendigen Pakete herunterladen.
## Ausführen des Programms ## Ausführen des Programms
@ -21,8 +22,8 @@ gestartet.
Wenn das Programm keinen Output generiert, so gab es keine Fehler und Wenn das Programm keinen Output generiert, so gab es keine Fehler und
die SVG Datei sollte erstellt sein. die SVG Datei sollte erstellt sein.
# `CH-Kreuz_7mm.svg` Datei # CH-Kreuz
Diese Datei ist von [SIX Group AG]( Diese Graphik ist von [SIX Group AG](
https://www.paymentstandards.ch/de/home/software-partner.html) zur https://www.paymentstandards.ch/de/home/software-partner.html) zur
Verfügung gestellt. Der direkte Download ist dieser: Verfügung gestellt. Der direkte Download ist dieser:
https://www.paymentstandards.ch/dam/downloads/swiss-cross.zip https://www.paymentstandards.ch/dam/downloads/swiss-cross.zip

View file

@ -5,16 +5,20 @@ import svgutils.transform as st
def swisscross(): def swisscross():
return st.fromstring( return st.fromstring(
'<?xml version="1.0" encoding="utf-8"?>\ '<svg width="49.5mm" height="49.5mm" version="1.1" viewBox="0 0 49.5 49.5" xmlns="http://www.w3.org/2000/svg">\
<svg width="7mm" height="7mm" version="1.1" id="Ebene_2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"\ <style type="text/css">.st0{fill:#FFFFFF;}\
viewBox="0 0 19.8 19.8" style="enable-background:new 0 0 19.8 19.8;" xml:space="preserve">\ .st1{fill:none;stroke:#FFFFFF;stroke-width:1.4357;stroke-miterlimit:10;}</style>\
<style type="text/css">\ <style type="text/css">.st0{fill:#FFFFFF;}\
.st0{fill:#FFFFFF;}\ .st1{fill:none;stroke:#FFFFFF;stroke-width:1.4357;stroke-miterlimit:10;}</style>\
.st1{fill:none;stroke:#FFFFFF;stroke-width:1.4357;stroke-miterlimit:10;}\ <polygon transform="matrix(.34905 0 0 .34905 21.294 21.294)" points="0.7 18.3 0.7 19.1 1.6 19.1 18.3 19.1 19.1 19.1 19.1 18.3 19.1 1.6 19.1 0.7 18.3 0.7 1.6 0.7 0.7 0.7 0.7 1.6"/>\
</style>\ <rect class="st0" x="24.192" y="22.691" width="1.1519" height="3.8396" stroke-width=".34905"/>\
<polygon points="18.3,0.7 1.6,0.7 0.7,0.7 0.7,1.6 0.7,18.3 0.7,19.1 1.6,19.1 18.3,19.1 19.1,19.1 19.1,18.3 19.1,1.6 19.1,0.7 "/>\ <rect class="st0" x="22.83" y="24.052" width="3.8396" height="1.1519" stroke-width=".34905"/>\
<rect x="8.3" y="4" class="st0" width="3.3" height="11"/>\ <polygon class="st1" transform="matrix(.34905 0 0 .34905 21.294 21.294)" points="18.3 19.1 19.1 19.1 19.1 18.3 19.1 1.6 19.1 0.7 18.3 0.7 1.6 0.7 0.7 0.7 0.7 1.6 0.7 18.3 0.7 19.1 1.6 19.1"/>\
<rect x="4.4" y="7.9" class="st0" width="11" height="3.3"/>\ </svg>'
<polygon class="st1" points="0.7,1.6 0.7,18.3 0.7,19.1 1.6,19.1 18.3,19.1 19.1,19.1 19.1,18.3 19.1,1.6 19.1,0.7 18.3,0.7 1.6,0.7 0.7,0.7 "/>\ )
</svg>'
).getroot() def white():
return st.fromstring(
'<svg width="49.5mm" height="49.5mm" version="1.1" viewBox="0 0 49.5 49.5" xmlns="http://www.w3.org/2000/svg">\
<rect x="0" y="0" width="49.5" height="49.5" fill="#fff"/>\
</svg>')

66
qrr.py
View file

@ -5,6 +5,10 @@ import qrcode
import qrcode.image.svg import qrcode.image.svg
from svgutils import transform as st from svgutils import transform as st
from ch_kreuz import swisscross as get_swisscross from ch_kreuz import swisscross as get_swisscross
from ch_kreuz import white as get_white
from svgutils.compose import Figure
from cairosvg import (svg2pdf, svg2png)
class qr_rechnung(): class qr_rechnung():
data = '' data = ''
@ -26,7 +30,6 @@ class qr_rechnung():
mode = 'w' if force else 'x' mode = 'w' if force else 'x'
try: try:
assert force or not os.path.isfile(filepath) assert force or not os.path.isfile(filepath)
factory = qrcode.image.svg.SvgPathImage
img = qrcode.make( img = qrcode.make(
self.data, self.data,
error_correction=qrcode.constants.ERROR_CORRECT_M, error_correction=qrcode.constants.ERROR_CORRECT_M,
@ -38,28 +41,29 @@ class qr_rechnung():
return 1 return 1
qrcode = st.fromfile(filepath) qrcode = st.fromfile(filepath)
offset = self.calc_move_offset(qrcode.get_size()[0]) try:
swisscross = get_swisscross() assert qrcode.width[-2:] == 'mm'
swisscross.moveto( qr_scale = 49.5/float(qrcode.width[:-2])
x=offset['offset'], except AssertionError as e:
y=offset['offset'], print(f"ERROR: Ein unerwarteter Fall in der Skallierung.")
scale_x=offset['scale'], print(e)
scale_y=offset['scale'] return 1
)
qrcode.append(swisscross)
qrcode.save(filepath)
def calc_move_offset(self, size): qrr = Figure(
org = float(size[:-2]) '49.5mm', '49.5mm',
return { get_white().getroot(),
'offset': org*0.427935156, qrcode.getroot().scale(qr_scale),
'scale': org/137.364857143 get_swisscross().getroot()
} )
qrr.save(filepath)
def help(args): def help(args):
return '{0}: Ungültige Eingabe\nAufruf: \ return '\n'.join([
{0} TEXTDATEI [SVG-ZIELDATEI]'.format(args[0]) '{0}: Ungültige Eingabe',
'Aufruf: {0} TEXTDATEI [SVG-ZIELDATEI]',
'Alternativ kann die ZIELDATEI auch mit .pdf oder .png enden.'
]).format(args[0])
def main(args): def main(args):
@ -69,7 +73,19 @@ def main(args):
print(help(args)) print(help(args))
return 1 return 1
try: try:
output_format = 'svg'
svgfile = args[2] svgfile = args[2]
if svgfile[-4:] == '.svg':
pass
elif svgfile[-4:] == '.png':
svgfile = svgfile[:-4]+'.svg'
output_format = 'png'
elif svgfile[-4:] == '.pdf':
svgfile = svgfile[:-4]+'.svg'
output_format = 'pdf'
else:
svgfile += '.svg'
except IndexError: except IndexError:
try: try:
assert textfile[-4:] == '.txt' assert textfile[-4:] == '.txt'
@ -83,7 +99,17 @@ def main(args):
except (PermissionError, FileNotFoundError) as e: except (PermissionError, FileNotFoundError) as e:
print(e) print(e)
return 1 return 1
return 0 if output_format == 'svg':
return 0
elif output_format == 'png':
svg2png(url=svgfile, write_to=svgfile[:-4]+'.png', dpi=600)
return 0
elif output_format == 'pdf':
svg2pdf(url=svgfile, write_to=svgfile[:-4]+'.pdf')
return 0
else:
print(f"ERROR: Unbekanntes Output_format: {output_format}")
return 1
if __name__ == '__main__': if __name__ == '__main__':