Files
piccreate/libs/svgconvert.py
T
Michael StanglandClaude Opus 5.5 28f2bcdb32 svgconvert.sh ruft svgconvert.py auf, generationlib entfernt
- bin/svgconvert.sh ist jetzt ein Wrapper wie svgconvert.bat
  (gleiche Optionen unter Linux und Windows)
- svgconvert.py: Endung .cfg/.csv bei -c/-i optional
- bin/generationlib (nur von svgconvert.sh benutzt) entfernt
- doc/README.md angepasst

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 09:31:36 +02:00

261 lines
9.8 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__version__ = "0.0.1"
__author__ = "Kamil Bugajski (kamil@bugajski.de)"
__copyright__ = "Copyright 2012, Kamil bugajski"
__license__ = "BSD"
import os
import cProfile
import optparse
import configparser
import re
import shutil
import subprocess
import csv
from string import Template
from concurrent import futures
from progressbar import EasyProgressBar
from utils import CompleteEnding
# ImageMagick 7 heisst "magick"; unter Windows ist "convert" ein Systemprogramm
IMAGEMAGICK = shutil.which('magick') or shutil.which('convert')
def get_translation(cfg_path, sec_name):
""" lädt die Zuordnung zwischen einem .csv Eingabefile und den Attributen"""
config = configparser.RawConfigParser()
config.read(cfg_path, encoding='utf-8')
trans = dict(config.items(sec_name))
return dict([[v,k] for k,v in trans.items()])
def getfilelist(path):
""" Receives a path and returns a list with all svg-files in this path."""
svgnames = []
allfiles = os.listdir(path)
for i in allfiles:
if re.findall('.svg', i):
svgnames.append(os.path.splitext(i)[0])
return svgnames
def convertSVG(in_path,filename,pic_config):
"""Create a svg-file for conversion-testing"""
inpath = os.path.join(in_path,str(filename)+".svg")
jpgpath = os.path.join(in_path,str(filename)+"." + pic_config['format'])
if (not options.force) and os.path.isfile(jpgpath):
if options.verbose:
print (filename, 'already exist!')
else:
cmdline = [IMAGEMAGICK,
'-density', pic_config['density'],
'-background', pic_config['background'],
inpath,
'-resize', pic_config['width'] + "x" + pic_config['height'],
jpgpath]
if not options.dry:
subprocess.check_call(cmdline)
if options.verbose:
print ('start converting', filename)
Epb.slide_progbar()
def startThreading(filelist,pic_config,work_path):
"""Start the threads for the conversion"""
if not filelist:
print ('filelist is empty - nothing to convert')
return True
executor = futures.ThreadPoolExecutor(max_workers = int(options.jobs))
global Epb
Epb = EasyProgressBar(array = filelist, show=options.progress)
for svg in filelist:
executor.submit(convertSVG,work_path,svg,pic_config)
executor.shutdown(wait=True)
def createTestFiles(in_path,filenumber):
"""Create a svg-file for conversion-testing"""
if options.verbose:
print ('creating:',filenumber)
path = os.path.join(in_path,str(filenumber)+".svg")
svgfile = '''<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="531.49603"
height="531.49603"
id="svg2">
<defs
id="defs4" />
<g
transform="translate(0,-520.86597)"
id="layer1">
<text
x="174.28572"
y="806.64789"
id="text2985"
xml:space="preserve"
style="font-size:72px;font-style:normal;font-weight:normal;line-height:\
125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;\
stroke:none;font-family:Sans">
<tspan
x="174.28572"
y="806.64789"
id="tspan2987"
style="font-size:72px;font-style:normal;font-variant:normal;\
font-weight:normal;font-stretch:normal;font-family:Ubuntu;\
-inkscape-font-specification:Ubuntu">$sub</tspan></text>
</g>
</svg>
'''
s = Template(svgfile)
f = open(path,'w')
writefile = s.substitute(sub = filenumber)
f.write(writefile)
f.close
def main():
"""get all information from the switches an start the parallel conversion"""
if not IMAGEMAGICK and not options.dry:
print('ImageMagick not found. Please install it (https://imagemagick.org).')
return None
#set the workpath and the default config
work_path = os.path.expandvars('$PICCREATE_OUT')
if options.svgfolder:
work_path = os.path.expandvars(options.svgfolder)
if not os.path.exists(work_path):
print('\"'+ work_path +'\" does not exist. Please give the name of the folder with the svg-files!')
return None
pic_config = {
'width' : '600',
'height' : '200',
'format' : options.format,
'density' : '150',
'background' : 'white',
'folder' : work_path,
'customerid' : 'customerid'
}
if options.test:
filelist = []
if options.verbose:
print ('---- Start of test-sequence ----')
print ('---- creating testfiles: ----')
for filenumber in range(0, int(options.test),1):
createTestFiles(work_path,filenumber)
filelist.append(filenumber)
if options.verbose:
print ('---- starting the conversion: ----')
startThreading(filelist,pic_config,work_path)
if options.verbose:
print ('---- test completed ----')
return True
filelist = getfilelist(work_path)
#load and override the default config if we receive an config file
if options.config:
config_path = os.path.expandvars(os.path.join('$PICCREATE_CFG', CompleteEnding(options.config, 'cfg')))
if not os.path.exists(config_path):
print('\"'+ config_path +'\" does not exist. Please give the name of a config file!')
return None
config = configparser.RawConfigParser()
config.read(config_path, encoding='utf-8')
# fill the config
pic_config = dict(config.items(options.format))
if options.background:
pic_config['background'] = options.background
elif 'background' in pic_config:
pass
else:
pic_config['background'] = 'transparent'
#get the translation for reading the csv
Trans = get_translation(config_path, 'translation')
for origin,translation in Trans.items():
if re.match(translation,'customerid'):
pic_config['customerid'] = origin
#chek if all files from the csv were successfully created and in the workfolder
if options.infile:
csv_path = os.path.expandvars(os.path.join('$PICCREATE_IN', CompleteEnding(options.infile, 'csv')))
if not os.path.exists(csv_path):
print('\"'+ csv_path +'\" does not exist. Please give the correct name of a csv file!')
return None
if not options.config:
print ("you must give a config file for checking the svg files")
return None
svglist = []
with open(csv_path, newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(csvfile,delimiter = ';')
for row in reader:
if row[pic_config['customerid']] not in filelist:
print ('Bild', row[pic_config['customerid']], 'fehlt')
else:
svglist.append(row[pic_config['customerid']])
filelist = svglist
#start conversion in multiple threads
if options.verbose:
print ('---- starting the conversion: ----')
startThreading(filelist,pic_config,work_path)
if options.verbose:
print ("---- conversion completed ----")
if options.dry:
print ("Dry option selected. No file was converted!")
if __name__ == '__main__':
parser = optparse.OptionParser(usage="""%prog [options]
Example usage
-------------
If no switch is given all svg files in the output folder will be converted.
Full help:
$ %prog -h (or --help for possible options)
Read Confg, create wakeup and scale this kind of jiffy box
$ %prog -c test -i test
""", version='%prog ' + __version__)
parser.add_option("-b", "--background", dest="background",
help="set the backgroundcolor. 'none' for transparent",
action='store')
parser.add_option("-c", "--config", dest="config",
help="config file with all data for jobs",
action='store')
parser.add_option("-f", "--force", dest="force", default=False,
help="create the pictures, no matter if they alreads exist",
action='store_true')
parser.add_option("--format", dest="format", default='jpg',
help="format of the picture",
action='store')
parser.add_option("-i", "--infile", dest="infile",
help="csv file with input of names/content",
action='store')
parser.add_option("-j", "--jobs", dest="jobs", default=8,
help="number of parallel jobs. default is 8",
action='store')
parser.add_option("-p", "--progress", dest="progress",
help="print a progression bar",
action='store_true')
parser.add_option("-s", "--svgfolder", dest="svgfolder",
help="path to the folder with the svg-files",
action='store')
parser.add_option("-t", "--test", dest="test",
help="number of default svg-files that will be created and tested",
action='store')
parser.add_option("-v", "--verbose", dest="verbose",
help="print the status of the conversion",
action='store_true')
parser.add_option("-y", "--dry", dest="dry",
help="dont generate images. \
just try if the conversion would success",
action='store_true')
(options, args) = parser.parse_args()
if options.test:
cProfile.run('main()')
else:
main()