From ee69de6e7d82afcb3aef8e2e343e87c06c8f7aac Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Tue, 25 Aug 2020 13:16:49 -0300 Subject: [PATCH] Problems with PcbDraw when generating PNG and JPG. Currently the script uses ImageMagick library. But the SVG conversion is handled unreliably. ImageMagick has various backends to do it and some of them don't work. I saw this problem many times, and is now affecting my system. A more reliable conversion can be achieved using `rsvg-convert`. Isn't as good as InkScape, but is smaller and works well. In the process I'm trimming the extra blank space generated by PcbDraw when we have objects in layers like "User Drawings" that extends beyond the PCB size. I'm also compressing JPGs more aggressively, this makes a real difference between PNG and JPG outputs. Otherwise the difference is too small. --- CHANGELOG.md | 2 ++ debian/control | 2 +- kibot/out_pcbdraw.py | 67 ++++++++++++++++++++++++++++++++++---------- 3 files changed, 55 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ecde9fd..73eb7b1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 more than one variant. - Removed warnings about malformed values for DNF components indicating it in its value. +- Problems with PcbDraw when generating PNG and JPG outputs. Now we use a more + reliable conversion methode when available. ## [0.6.1] - 2020-08-20 ### Added diff --git a/debian/control b/debian/control index fd1c75de..8d6edc7e 100644 --- a/debian/control +++ b/debian/control @@ -11,7 +11,7 @@ Package: kibot Architecture: all Multi-Arch: foreign Depends: ${misc:Depends}, ${python3:Depends}, python3-yaml, kicad (>= 5.1.0), python3-wxgtk4.0 -Recommends: kibom.inti-cmnb (>= 1.8.0), kicad-automation-scripts.inti-cmnb (>= 1.1.2), interactivehtmlbom.inti-cmnb, pcbdraw, python3-xlsxwriter +Recommends: kibom.inti-cmnb (>= 1.8.0), kicad-automation-scripts.inti-cmnb (>= 1.1.2), interactivehtmlbom.inti-cmnb, pcbdraw, imagemagick, librsvg2-bin, python3-xlsxwriter Description: KiCad Bot KiBot is a program which helps you to automate the generation of KiCad output documents easily, repeatable, and most of all, scriptably. diff --git a/kibot/out_pcbdraw.py b/kibot/out_pcbdraw.py index fe45e63d..628304df 100644 --- a/kibot/out_pcbdraw.py +++ b/kibot/out_pcbdraw.py @@ -5,6 +5,7 @@ # Project: KiBot (formerly KiPlot) import os import re +from shutil import which from tempfile import (NamedTemporaryFile) from subprocess import (check_output, STDOUT, CalledProcessError) from .misc import (PCBDRAW, PCBDRAW_ERR) @@ -15,6 +16,8 @@ from .macros import macros, document, output_class # noqa: F401 from . import log logger = log.get_logger(__name__) +SVG2PNG = 'rsvg-convert' +CONVERT = 'convert' class PcbDrawStyle(Optionable): @@ -76,6 +79,29 @@ class PcbDrawRemap(Optionable): pass +def _get_tmp_name(ext): + with NamedTemporaryFile(mode='w', suffix=ext, delete=False) as f: + f.close() + return f.name + + +def _run_command(cmd, tmp_remap=False, tmp_style=False): + logger.debug('Executing: '+str(cmd)) + try: + cmd_output = check_output(cmd, stderr=STDOUT) + except CalledProcessError as e: + logger.error('Failed to run %s, error %d', cmd[0], e.returncode) + if e.output: + logger.debug('Output from command: '+e.output.decode()) + exit(PCBDRAW_ERR) + finally: + if tmp_remap: + os.remove(tmp_remap) + if tmp_style: + os.remove(tmp_style) + logger.debug('Output from command:\n'+cmd_output.decode()) + + class PcbDrawOptions(BaseOptions): def __init__(self): with document: @@ -218,22 +244,33 @@ class PcbDrawOptions(BaseOptions): tmp_remap = None # The board & output cmd.append(GS.pcb_file) - cmd.append(output) + svg = None + if self.format == 'svg': + cmd.append(output) + else: + # PNG and JPG outputs are unreliable + if which(SVG2PNG) is None: + logger.warning('`{}` not installed, using unreliable PNG/JPG conversion'.format(SVG2PNG)) + logger.warning('If you experiment problems install `librsvg2-bin` or equivalent') + cmd.append(output) + elif which(CONVERT) is None: + logger.warning('`{}` not installed, using unreliable PNG/JPG conversion'.format(CONVERT)) + logger.warning('If you experiment problems install `imagemagick` or equivalent') + cmd.append(output) + else: + svg = _get_tmp_name('.svg') + cmd.append(svg) # Execute and inform is successful - logger.debug('Executing: '+str(cmd)) - try: - cmd_output = check_output(cmd, stderr=STDOUT) - except CalledProcessError as e: - logger.error('Failed to run %s, error %d', PCBDRAW, e.returncode) - if e.output: - logger.debug('Output from command: '+e.output.decode()) - exit(PCBDRAW_ERR) - finally: - if tmp_remap: - os.remove(tmp_remap) - if tmp_style: - os.remove(tmp_style) - logger.debug('Output from command:\n'+cmd_output.decode()) + _run_command(cmd, tmp_remap, tmp_style) + if svg is not None: + # Manually convert the SVG to PNG + png = _get_tmp_name('.png') + _run_command([SVG2PNG, '-d', str(self.dpi), '-p', str(self.dpi), svg, '-o', png], svg) + cmd = [CONVERT, '-trim', png] + if self.format == 'jpg': + cmd += ['-quality', '85%'] + cmd.append(output) + _run_command(cmd, png) @output_class