diff --git a/cfg/font.cfg b/cfg/font.cfg index 4492952..a02eef4 100644 --- a/cfg/font.cfg +++ b/cfg/font.cfg @@ -42,4 +42,5 @@ align=left width=1200 height=1200 format=jpg +density=200 diff --git a/libs/progressbar.py b/libs/progressbar.py new file mode 100644 index 0000000..bf9c595 --- /dev/null +++ b/libs/progressbar.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# A Python Library to create a Progress Bar. +# Copyright (C) 2008 BJ Dierkes +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# +# This class is an improvement from the original found at: +# +# http://code.activestate.com/recipes/168639/ +# + +import sys,os + +class ProgressBar: + def __init__(self, min_value = 0, max_value = 100, width=77,**kwargs): + self.char = kwargs.get('char', '#') + self.mode = kwargs.get('mode', 'dynamic') # fixed or dynamic + if not self.mode in ['fixed', 'dynamic']: + self.mode = 'fixed' + + self.bar = '' + self.min = min_value + self.max = max_value + self.span = max_value - min_value + self.width = width + self.amount = 0 # When amount == max, we are 100% done + self.update_amount(0) + + + def increment_amount(self, add_amount = 1): + """ + Increment self.amount by 'add_ammount' or default to incrementing + by 1, and then rebuild the bar string. + """ + new_amount = self.amount + add_amount + if new_amount < self.min: new_amount = self.min + if new_amount > self.max: new_amount = self.max + self.amount = new_amount + self.build_bar() + + + def update_amount(self, new_amount = None): + """ + Update self.amount with 'new_amount', and then rebuild the bar + string. + """ + if not new_amount: new_amount = self.amount + if new_amount < self.min: new_amount = self.min + if new_amount > self.max: new_amount = self.max + self.amount = new_amount + self.build_bar() + + + def build_bar(self): + """ + Figure new percent complete, and rebuild the bar string base on + self.amount. + """ + diff = float(self.amount - self.min) + percent_done = int(round((diff / float(self.span)) * 100.0)) + + # figure the proper number of 'character' make up the bar + all_full = self.width - 2 + num_hashes = int(round((percent_done * all_full) / 100)) + + if self.mode == 'dynamic': + # build a progress bar with self.char (to create a dynamic bar + # where the percent string moves along with the bar progress. + self.bar = self.char * num_hashes + else: + # build a progress bar with self.char and spaces (to create a + # fixe bar (the percent string doesn't move) + self.bar = self.char * num_hashes + ' ' * (all_full-num_hashes) + + percent_str = str(percent_done) + "%" + self.bar = '[ ' + self.bar + ' ] ' + percent_str + + + def __str__(self): + return str(self.bar) + +def bufcount(filename): + if not os.path.exists(filename): + raise Exception + try: + fh = open(filename) + lines = 0 + buf_size = 1024 * 1024 + read_f = fh.read # loop optimization + + buf = read_f(buf_size) + while buf: + lines += buf.count('\n') + buf = read_f(buf_size) + finally: + fh.close() + return lines + +class EasyProgressBar(): + def __init__(self, filename=None, array=None, show=False): + if filename: + NumElems = bufcount(filename)-1 + if array: + NumElems = len(array) + if not array and not filename: + raise Exception + + # initialisiere Progressbar, wenn gewünscht + if show: + # zaehle alle Zeilen des Files, das verwendet wird + # die erste Zeile enthält dabei die Ueberschriften der Spalten + limit = NumElems-1 + self.prog = ProgressBar(0, limit, 77, mode='dynamic', char='-') + self.oldprog = str(self.prog) + else: + self.prog = False + def slide_progbar(self): + if self.prog: + prog = self.prog + oldprog = self.oldprog + prog.increment_amount() + if oldprog != str(prog): + print(prog, "\r", end=' ') + sys.stdout.flush() + oldprog=str(prog) + +def init_progbar(filename=None, array=None, init=False): + """ Initialisere die Progressbar + """ + from progressbar import ProgressBar, bufcount + + if filename: + NumElems = bufcount(filename)-1 + if array: + NumElems = len(array) + + # initialisiere Progressbar, wenn gewünscht + if init: + # zaehle alle Zeilen des Files, das verwendet wird + # die erste Zeile enthält dabei die Ueberschriften der Spalten + limit = NumElems-1 + prog = ProgressBar(0, limit, 77, mode='dynamic', char='-') + oldprog = str(prog) + return (prog, oldprog) + else: + return (None, None) + +def slide_progbar(prog, oldprog, init): + """ verschiebe die Progressbar + """ + if init: + prog.increment_amount() + if oldprog != str(prog): + print(prog, "\r", end=' ') + sys.stdout.flush() + oldprog=str(prog) + +def main(): + print() + limit = 1000000 + + print('Example 1: Fixed Bar') + prog = ProgressBar(0, limit, 77, mode='fixed') + oldprog = str(prog) + for i in range(limit+1): + prog.update_amount(i) + if oldprog != str(prog): + print(prog, "\r", end=' ') + sys.stdout.flush() + oldprog=str(prog) + + print('\n\n') + + print('Example 2: Dynamic Bar') + prog = ProgressBar(0, limit, 77, mode='dynamic', char='-') + oldprog = str(prog) + for i in range(limit+1): + prog.increment_amount() + if oldprog != str(prog): + print(prog, "\r", end=' ') + sys.stdout.flush() + oldprog=str(prog) + + print('\n\n') + +if __name__ == '__main__': + main() diff --git a/libs/svgconvert.py b/libs/svgconvert.py new file mode 100644 index 0000000..1afe517 --- /dev/null +++ b/libs/svgconvert.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python3.2 +# -*- 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 subprocess +import csv +from string import Template +from concurrent import futures +from progressbar import EasyProgressBar + + +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) + 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: + background = " -background " + pic_config['background'] + " " + resize = " -resize " + pic_config['width'] + "x" + pic_config['height'] + " " + density = " -density " + pic_config['density'] + cmd = "convert" + if not options.dry: + subprocess.check_call(cmd + density + background + inpath + resize + jpgpath, shell = True) + 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 = ''' + + + + + $sub + + + ''' + 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""" + #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', options.config)) + 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) + # 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', options.infile)) + 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='') 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()