[PcbDraw] Removed PIL as dependency
- So now the save function only supports SVG as input and SVG/PNG as output. All other cases are handled from outside - This is because KiBot heavily uses ImageMagick and migrating to PIL is not something simple. - There is no point in using PIL just for file conversion, as we don't use `render` this is the only use.
This commit is contained in:
parent
f61ca58ffa
commit
207dd8f67c
|
|
@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Added
|
||||
- Diff:
|
||||
- Option to compare only the first schematic page. (See #319)
|
||||
- PcbDraw:
|
||||
- Support for BMP output
|
||||
|
||||
### Changed
|
||||
- Diff:
|
||||
|
|
|
|||
14
README.md
14
README.md
|
|
@ -173,16 +173,18 @@ Notes:
|
|||
- Create outputs preview for `navigate_results`
|
||||
- Create PNG icons for `navigate_results`
|
||||
- Create PDF, PNG, PS and EPS formats for `pcb_print`
|
||||
|
||||
[**Ghostscript**](https://www.ghostscript.com/) [](https://www.ghostscript.com/) [](https://packages.debian.org/bullseye/ghostscript) 
|
||||
- Optional to:
|
||||
- Create outputs preview for `navigate_results`
|
||||
- Create PNG, PS and EPS formats for `pcb_print`
|
||||
- Create PNG, JPG and BMP images for `pcbdraw`
|
||||
|
||||
[**ImageMagick**](https://imagemagick.org/) [](https://imagemagick.org/) [](https://packages.debian.org/bullseye/imagemagick) 
|
||||
- Optional to:
|
||||
- Create outputs preview for `navigate_results`
|
||||
- Create monochrome prints and scaled PNG files for `pcb_print`
|
||||
- Create JPG and BMP images for `pcbdraw`
|
||||
|
||||
[**Ghostscript**](https://www.ghostscript.com/) [](https://www.ghostscript.com/) [](https://packages.debian.org/bullseye/ghostscript) 
|
||||
- Optional to:
|
||||
- Create outputs preview for `navigate_results`
|
||||
- Create PNG, PS and EPS formats for `pcb_print`
|
||||
|
||||
[**Pandoc**](https://pandoc.org/) [](https://pandoc.org/) [](https://packages.debian.org/bullseye/pandoc)
|
||||
- Optional to create PDF/ODF/DOCX files for `report`
|
||||
|
|
@ -2557,7 +2559,7 @@ Notes:
|
|||
- **`options`**: [dict] Options for the `pcbdraw` output.
|
||||
* Valid keys:
|
||||
- **`bottom`**: [boolean=false] Render the bottom side of the board (default is top side).
|
||||
- **`format`**: [string='svg'] [svg,png,jpg] Output format. Only used if no `output` is specified.
|
||||
- **`format`**: [string='svg'] [svg,png,jpg,bmp] Output format. Only used if no `output` is specified.
|
||||
- **`mirror`**: [boolean=false] Mirror the board.
|
||||
- **`output`**: [string='%f-%i%I%v.%x'] Name for the generated file. Affected by global options.
|
||||
- **`show_components`**: [list(string)|string=none] [none,all] List of components to draw, can be also a string for none or all.
|
||||
|
|
|
|||
|
|
@ -1356,7 +1356,7 @@ outputs:
|
|||
dnf_filter: '_none'
|
||||
# [number=300] [10,1200] Dots per inch (resolution) of the generated image
|
||||
dpi: 300
|
||||
# [string='svg'] [svg,png,jpg] Output format. Only used if no `output` is specified
|
||||
# [string='svg'] [svg,png,jpg,bmp] Output format. Only used if no `output` is specified
|
||||
format: 'svg'
|
||||
# [list(string)=[]] List of components to highlight
|
||||
highlight: []
|
||||
|
|
|
|||
|
|
@ -17,6 +17,61 @@ Currently only the `plot` module is included.
|
|||
### convert.py
|
||||
|
||||
- Made the `pcbdraw` import relative
|
||||
- Removed PIL as dependency
|
||||
- So now the save function only supports SVG as input and SVG/PNG as output
|
||||
- All other cases are handled from outside
|
||||
- This is because KiBot heavily uses ImageMagick and migrating to PIL is not something simple
|
||||
- There is no point in using PIL just for file conversion, as we don't use `render` this is the only use
|
||||
|
||||
```diff
|
||||
diff --git a/kibot/PcbDraw/convert.py b/kibot/PcbDraw/convert.py
|
||||
index ba856a69..7fe64738 100644
|
||||
--- a/kibot/PcbDraw/convert.py
|
||||
+++ b/kibot/PcbDraw/convert.py
|
||||
@@ -6,7 +6,7 @@ import textwrap
|
||||
import os
|
||||
from typing import Union
|
||||
from tempfile import TemporaryDirectory
|
||||
-from PIL import Image
|
||||
+# from PIL import Image
|
||||
from lxml.etree import _ElementTree # type: ignore
|
||||
|
||||
# Converting SVG to bitmap is a hard problem. We used Wand (and thus
|
||||
@@ -66,17 +66,17 @@ def svgToPng(inputFilename: str, outputFilename: str, dpi: int=300) -> None:
|
||||
message += textwrap.indent(m, " ")
|
||||
raise RuntimeError(message)
|
||||
|
||||
-def save(image: Union[_ElementTree, Image.Image], filename: str, dpi: int=600) -> None:
|
||||
+def save(image: _ElementTree, filename: str, dpi: int=600, format: str=None) -> None:
|
||||
"""
|
||||
Given an SVG tree or an image, save to a filename. The format is deduced
|
||||
from the extension.
|
||||
"""
|
||||
- ftype = os.path.splitext(filename)[1][1:].lower()
|
||||
- if isinstance(image, Image.Image):
|
||||
- if ftype not in ["jpg", "jpeg", "png", "bmp"]:
|
||||
- raise TypeError(f"Cannot save bitmap image into {ftype}")
|
||||
- image.save(filename)
|
||||
- return
|
||||
+ ftype = os.path.splitext(filename)[1][1:].lower() if format is None else format
|
||||
+# if isinstance(image, Image.Image):
|
||||
+# if ftype not in ["jpg", "jpeg", "png", "bmp"]:
|
||||
+# raise TypeError(f"Cannot save bitmap image into {ftype}")
|
||||
+# image.save(filename)
|
||||
+# return
|
||||
if isinstance(image, _ElementTree):
|
||||
if ftype == "svg":
|
||||
image.write(filename)
|
||||
@@ -91,6 +91,6 @@ def save(image: Union[_ElementTree, Image.Image], filename: str, dpi: int=600) -
|
||||
svgToPng(svg_filename, png_filename, dpi=dpi)
|
||||
if ftype == "png":
|
||||
return
|
||||
- Image.open(png_filename).convert("RGB").save(filename)
|
||||
- return
|
||||
+# Image.open(png_filename).convert("RGB").save(filename)
|
||||
+# return
|
||||
raise TypeError(f"Unknown image type: {type(image)}")
|
||||
```
|
||||
|
||||
### convert_common.py
|
||||
|
||||
|
|
@ -32,7 +87,9 @@ No current changes
|
|||
|
||||
### unit.py
|
||||
|
||||
No current changes
|
||||
- Replaced `unit` code.
|
||||
- So we have only one units conversion
|
||||
- I think the only difference is that KiBot code currently supports the locales decimal point
|
||||
|
||||
### plot.py
|
||||
|
||||
|
|
@ -183,6 +240,3 @@ index f8990722..17f90185 100644
|
|||
- Find the index of the smaller element (1 line code)
|
||||
- I added a replacemt for the `array` function, it just makes all matrix elements float
|
||||
|
||||
- Replaced `unit` code.
|
||||
- So we have only one units conversion
|
||||
- I think the only difference is that KiBot code currently supports the locales decimal point
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import textwrap
|
|||
import os
|
||||
from typing import Union
|
||||
from tempfile import TemporaryDirectory
|
||||
from PIL import Image
|
||||
# from PIL import Image
|
||||
from lxml.etree import _ElementTree # type: ignore
|
||||
|
||||
# Converting SVG to bitmap is a hard problem. We used Wand (and thus
|
||||
|
|
@ -66,17 +66,17 @@ def svgToPng(inputFilename: str, outputFilename: str, dpi: int=300) -> None:
|
|||
message += textwrap.indent(m, " ")
|
||||
raise RuntimeError(message)
|
||||
|
||||
def save(image: Union[_ElementTree, Image.Image], filename: str, dpi: int=600) -> None:
|
||||
def save(image: _ElementTree, filename: str, dpi: int=600, format: str=None) -> None:
|
||||
"""
|
||||
Given an SVG tree or an image, save to a filename. The format is deduced
|
||||
from the extension.
|
||||
"""
|
||||
ftype = os.path.splitext(filename)[1][1:].lower()
|
||||
if isinstance(image, Image.Image):
|
||||
if ftype not in ["jpg", "jpeg", "png", "bmp"]:
|
||||
raise TypeError(f"Cannot save bitmap image into {ftype}")
|
||||
image.save(filename)
|
||||
return
|
||||
ftype = os.path.splitext(filename)[1][1:].lower() if format is None else format
|
||||
# if isinstance(image, Image.Image):
|
||||
# if ftype not in ["jpg", "jpeg", "png", "bmp"]:
|
||||
# raise TypeError(f"Cannot save bitmap image into {ftype}")
|
||||
# image.save(filename)
|
||||
# return
|
||||
if isinstance(image, _ElementTree):
|
||||
if ftype == "svg":
|
||||
image.write(filename)
|
||||
|
|
@ -91,6 +91,6 @@ def save(image: Union[_ElementTree, Image.Image], filename: str, dpi: int=600) -
|
|||
svgToPng(svg_filename, png_filename, dpi=dpi)
|
||||
if ftype == "png":
|
||||
return
|
||||
Image.open(png_filename).convert("RGB").save(filename)
|
||||
return
|
||||
# Image.open(png_filename).convert("RGB").save(filename)
|
||||
# return
|
||||
raise TypeError(f"Unknown image type: {type(image)}")
|
||||
|
|
|
|||
|
|
@ -3,19 +3,18 @@
|
|||
# Copyright (c) 2020-2022 Instituto Nacional de Tecnología Industrial
|
||||
# License: GPL-3.0
|
||||
# Project: KiBot (formerly KiPlot)
|
||||
# TODO: PIL dependency?
|
||||
# TODO: Package resources
|
||||
# TODO: wxApp messages
|
||||
# """
|
||||
# Dependencies:
|
||||
# - from: RSVG
|
||||
# role: Create PNG and JPG images
|
||||
# - from: ImageMagick
|
||||
# role: Create JPG images
|
||||
# - from: PcbDraw
|
||||
# role: mandatory
|
||||
# """
|
||||
"""
|
||||
Dependencies:
|
||||
- from: RSVG
|
||||
role: Create PNG, JPG and BMP images
|
||||
- from: ImageMagick
|
||||
role: Create JPG and BMP images
|
||||
"""
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
from tempfile import NamedTemporaryFile
|
||||
# Here we import the whole module to make monkeypatch work
|
||||
from .error import KiPlotConfigurationError
|
||||
|
|
@ -37,6 +36,26 @@ def pcbdraw_warnings(tag, msg):
|
|||
logger.warning('{}({}) {}'.format(W_PCBDRAW, tag, msg))
|
||||
|
||||
|
||||
def _get_tmp_name(ext):
|
||||
with NamedTemporaryFile(mode='w', suffix=ext, delete=False) as f:
|
||||
f.close()
|
||||
return f.name
|
||||
|
||||
|
||||
def _run_command(cmd):
|
||||
logger.debug('Executing: '+shlex.join(cmd))
|
||||
try:
|
||||
cmd_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
|
||||
except subprocess.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)
|
||||
out = cmd_output.decode()
|
||||
if out.strip():
|
||||
logger.debug('Output from command:\n'+out)
|
||||
|
||||
|
||||
class PcbDrawStyle(Optionable):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
|
@ -140,7 +159,7 @@ class PcbDrawOptions(VariantOptions):
|
|||
self.dpi = 300
|
||||
""" [10,1200] Dots per inch (resolution) of the generated image """
|
||||
self.format = 'svg'
|
||||
""" *[svg,png,jpg] Output format. Only used if no `output` is specified """
|
||||
""" *[svg,png,jpg,bmp] Output format. Only used if no `output` is specified """
|
||||
self.output = GS.def_global_output
|
||||
""" *Name for the generated file """
|
||||
super().__init__()
|
||||
|
|
@ -260,6 +279,19 @@ class PcbDrawOptions(VariantOptions):
|
|||
|
||||
def run(self, name):
|
||||
super().run(name)
|
||||
# Select a name and format that PcbDraw can handle
|
||||
save_output_name = name
|
||||
save_output_format = self.format
|
||||
self.convert_command = None
|
||||
# Check we have the tools needed for the output format
|
||||
if self.format != 'svg':
|
||||
# We need RSVG for anything other than SVG
|
||||
self.ensure_tool('RSVG')
|
||||
# We need ImageMagick for anything other than SVG and PNG
|
||||
if self.format != 'png':
|
||||
self.convert_command = self.ensure_tool('ImageMagick')
|
||||
save_output_name = _get_tmp_name('.png')
|
||||
save_output_format = 'png'
|
||||
|
||||
try:
|
||||
# TODO: Avoid loading the PCB again
|
||||
|
|
@ -311,7 +343,15 @@ class PcbDrawOptions(VariantOptions):
|
|||
if tmp_style:
|
||||
os.remove(tmp_style)
|
||||
|
||||
save(image, name, self.dpi)
|
||||
save(image, save_output_name, self.dpi, format=save_output_format)
|
||||
# Do we need to convert the saved file?
|
||||
if self.convert_command is not None:
|
||||
cmd = [self.convert_command, save_output_name]
|
||||
if self.format == 'jpg':
|
||||
cmd += ['-quality', '85%']
|
||||
cmd.append(name)
|
||||
_run_command(cmd)
|
||||
os.remove(save_output_name)
|
||||
return
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ deps = '{\
|
|||
],\
|
||||
"extra_deb": null,\
|
||||
"help_option": "--version",\
|
||||
"importance": 2,\
|
||||
"importance": 3,\
|
||||
"in_debian": true,\
|
||||
"is_kicad_plugin": false,\
|
||||
"is_python": false,\
|
||||
|
|
@ -183,6 +183,13 @@ deps = '{\
|
|||
"max_version": null,\
|
||||
"output": "pcb_print",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": "Create JPG and BMP images",\
|
||||
"mandatory": false,\
|
||||
"max_version": null,\
|
||||
"output": "pcbdraw",\
|
||||
"version": null\
|
||||
}\
|
||||
],\
|
||||
"tests": [],\
|
||||
|
|
@ -719,7 +726,7 @@ deps = '{\
|
|||
"extra_arch": null,\
|
||||
"extra_deb": null,\
|
||||
"help_option": "--version",\
|
||||
"importance": 3,\
|
||||
"importance": 4,\
|
||||
"in_debian": true,\
|
||||
"is_kicad_plugin": false,\
|
||||
"is_python": false,\
|
||||
|
|
@ -750,6 +757,13 @@ deps = '{\
|
|||
"max_version": null,\
|
||||
"output": "pcb_print",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": "Create PNG, JPG and BMP images",\
|
||||
"mandatory": false,\
|
||||
"max_version": null,\
|
||||
"output": "pcbdraw",\
|
||||
"version": null\
|
||||
}\
|
||||
],\
|
||||
"tests": [\
|
||||
|
|
|
|||
Loading…
Reference in New Issue