[Render_3D] Added option to auto-crop the resulting PNG
This commit is contained in:
parent
5b19227625
commit
81ce2004d5
|
|
@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- Option to control the *SVG precision* (units scale)
|
||||
- Render_3D:
|
||||
- Option to render only some components (like in PcbDraw)
|
||||
- Option to auto-crop the resulting PNG
|
||||
- SVG:
|
||||
- Option to control the *SVG precision* (units scale)
|
||||
|
||||
|
|
|
|||
20
README.md
20
README.md
|
|
@ -171,6 +171,13 @@ Notes:
|
|||
- Find commit hash and/or date for `sch_replace`
|
||||
- Find commit hash and/or date for `set_text_variables`
|
||||
|
||||
[**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`
|
||||
- Automatically crop images for `render_3d`
|
||||
|
||||
[**RSVG tools**](https://gitlab.gnome.org/GNOME/librsvg) [](https://gitlab.gnome.org/GNOME/librsvg) [](https://packages.debian.org/bullseye/librsvg2-bin) 
|
||||
- Optional to:
|
||||
- Create outputs preview for `navigate_results`
|
||||
|
|
@ -178,12 +185,6 @@ Notes:
|
|||
- Create PDF, 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`
|
||||
|
|
@ -3092,6 +3093,10 @@ Notes:
|
|||
- **`view`**: [string='top'] [top,bottom,front,rear,right,left,z,Z,y,Y,x,X] Point of view.
|
||||
- **`zoom`**: [number=0] Zoom steps. Use positive to enlarge, get closer, and negative to reduce.
|
||||
Same result as using the mouse wheel in the 3D viewer.
|
||||
- `auto_crop`: [boolean=false] When enabled the image will be post-processed to make the background transparent and then remove the
|
||||
empty space around the image. In this mode the `background1` and `background2` colors are ignored.
|
||||
- `auto_crop_color`: [string='#ff70b7'] Color used for the chroma key. Adjust it if some regions of the board becomes transparent.
|
||||
- `auto_crop_fuzz`: [number=15] [0,100] Chroma key tolerance (percent). Bigger values will remove more pixels.
|
||||
- `background1`: [string='#66667F'] First color for the background gradient.
|
||||
- `background2`: [string='#CCCCE5'] Second color for the background gradient.
|
||||
- `board`: [string='#332B16'] Color for the board without copper or solder mask.
|
||||
|
|
@ -4519,4 +4524,5 @@ relative paths. So you can move the new PCB file to any place, as long as the `3
|
|||
- **Chip in assembly_simple.svg**: [oNline Web Fonts](https://www.onlinewebfonts.com/)
|
||||
- **Wrench**: [Freepik - Flaticon](https://www.flaticon.es/iconos-gratis/llave-inglesa)
|
||||
- **Most icons for the navigate_results output**: The KiCad project
|
||||
- **PTV09A 3D Model**: Dmitry Levin (https://grabcad.com/dmitry.levin-6)
|
||||
- **PTV09A 3D Model**: Dmitry Levin ([GrabCad](https://grabcad.com/dmitry.levin-6))
|
||||
- **PcbDraw PCB example**: [Arduino Learning Kit Starter](https://github.com/RoboticsBrno/ArduinoLearningKitStarter)
|
||||
|
|
|
|||
|
|
@ -1923,4 +1923,5 @@ relative paths. So you can move the new PCB file to any place, as long as the `3
|
|||
- **Chip in assembly_simple.svg**: [oNline Web Fonts](https://www.onlinewebfonts.com/)
|
||||
- **Wrench**: [Freepik - Flaticon](https://www.flaticon.es/iconos-gratis/llave-inglesa)
|
||||
- **Most icons for the navigate_results output**: The KiCad project
|
||||
- **PTV09A 3D Model**: Dmitry Levin (https://grabcad.com/dmitry.levin-6)
|
||||
- **PTV09A 3D Model**: Dmitry Levin ([GrabCad](https://grabcad.com/dmitry.levin-6))
|
||||
- **PcbDraw PCB example**: [Arduino Learning Kit Starter](https://github.com/RoboticsBrno/ArduinoLearningKitStarter)
|
||||
|
|
|
|||
|
|
@ -1829,6 +1829,13 @@ outputs:
|
|||
type: 'render_3d'
|
||||
dir: 'Example/render_3d_dir'
|
||||
options:
|
||||
# [boolean=false] When enabled the image will be post-processed to make the background transparent and then remove the
|
||||
# empty space around the image. In this mode the `background1` and `background2` colors are ignored
|
||||
auto_crop: false
|
||||
# [string='#ff70b7'] Color used for the chroma key. Adjust it if some regions of the board becomes transparent
|
||||
auto_crop_color: '#ff70b7'
|
||||
# [number=15] [0,100] Chroma key tolerance (percent). Bigger values will remove more pixels
|
||||
auto_crop_fuzz: 15
|
||||
# [string='#66667F'] First color for the background gradient
|
||||
background1: '#66667F'
|
||||
# [string='#CCCCE5'] Second color for the background gradient
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ from .misc import W_UNKOPS
|
|||
from . import log
|
||||
|
||||
logger = log.get_logger()
|
||||
HEX_DIGIT = '[A-Fa-f0-9]{2}'
|
||||
|
||||
|
||||
def do_filter(v):
|
||||
|
|
@ -31,8 +32,10 @@ class Optionable(object):
|
|||
_str_values_re = compile(r"string=.*\] \[([^\]]+)\]")
|
||||
_num_range_re = compile(r"number=.*\] \[(-?\d+),(-?\d+)\]")
|
||||
_default = None
|
||||
_color_re = re.compile(r"#[A-Fa-f0-9]{6}$")
|
||||
_color_re_a = re.compile(r"#[A-Fa-f0-9]{8}$")
|
||||
|
||||
_color_re = re.compile(r"#("+HEX_DIGIT+"){3}$")
|
||||
_color_re_a = re.compile(r"#("+HEX_DIGIT+"){4}$")
|
||||
_color_re_component = re.compile(HEX_DIGIT)
|
||||
|
||||
def __init__(self):
|
||||
self._unkown_is_error = False
|
||||
|
|
@ -372,15 +375,36 @@ class Optionable(object):
|
|||
def get_default(cls):
|
||||
return cls._default
|
||||
|
||||
def validate_color_str(self, color):
|
||||
return self._color_re.match(color) or self._color_re_a.match(color)
|
||||
|
||||
def validate_color(self, name):
|
||||
color = getattr(self, name)
|
||||
if not self._color_re.match(color) and not self._color_re_a.match(color):
|
||||
if not self.validate_color_str(getattr(self, name)):
|
||||
raise KiPlotConfigurationError('Invalid color for `{}` use `#rrggbb` or `#rrggbbaa` with hex digits'.format(name))
|
||||
|
||||
def validate_colors(self, names):
|
||||
for color in names:
|
||||
self.validate_color(color)
|
||||
|
||||
def parse_one_color(self, color):
|
||||
res = self._color_re_component.findall(color)
|
||||
alpha = 1.0
|
||||
if len(res) > 3:
|
||||
alpha = int(res[3], 16)/255.0
|
||||
return (int(res[0], 16)/255.0, int(res[1], 16)/255.0, int(res[2], 16)/255.0, alpha)
|
||||
|
||||
def color_to_rgb(self, color):
|
||||
index = 4 if len(color) > 4 else 0
|
||||
alpha = color[index+3]
|
||||
if alpha == 1.0:
|
||||
return "rgb({}, {}, {})".format(round(color[index]*255.0), round(color[index+1]*255.0),
|
||||
round(color[index+2]*255.0))
|
||||
return "rgba({}, {}, {}, {})".format(round(color[index]*255.0), round(color[index+1]*255.0),
|
||||
round(color[index+2]*255.0), alpha)
|
||||
|
||||
def color_str_to_rgb(self, color):
|
||||
return self.color_to_rgb(self.parse_one_color(color))
|
||||
|
||||
|
||||
class BaseOptions(Optionable):
|
||||
""" A class to validate and hold output options.
|
||||
|
|
|
|||
|
|
@ -9,9 +9,13 @@ Dependencies:
|
|||
- from: KiAuto
|
||||
role: mandatory
|
||||
version: 2.0.4
|
||||
- from: ImageMagick
|
||||
role: Automatically crop images
|
||||
"""
|
||||
import os
|
||||
import shlex
|
||||
from shutil import rmtree
|
||||
import subprocess
|
||||
from .misc import (RENDER_3D_ERR, PCB_MAT_COLORS, PCB_FINISH_COLORS, SOLDER_COLORS, SILK_COLORS,
|
||||
KICAD_VERSION_6_0_2, MISSING_TOOL)
|
||||
from .gs import GS
|
||||
|
|
@ -24,6 +28,19 @@ from . import log
|
|||
logger = log.get_logger()
|
||||
|
||||
|
||||
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(RENDER_3D_ERR)
|
||||
if cmd_output.strip():
|
||||
logger.debug('- Output from command:\n'+cmd_output.decode())
|
||||
|
||||
|
||||
class Render3DOptions(Base3DOptions):
|
||||
_colors = {'background1': 'bg_color_1',
|
||||
'background2': 'bg_color_2',
|
||||
|
|
@ -107,6 +124,13 @@ class Render3DOptions(Base3DOptions):
|
|||
self.show_components = Optionable
|
||||
""" *[list(string)|string=all] [none,all] List of components to draw, can be also a string for `none` or `all`.
|
||||
Unlike the `pcbdraw` output, the default is `all` """
|
||||
self.auto_crop = False
|
||||
""" When enabled the image will be post-processed to make the background transparent and then remove the
|
||||
empty space around the image. In this mode the `background1` and `background2` colors are ignored """
|
||||
self.auto_crop_color = "#ff70b7"
|
||||
""" Color used for the chroma key. Adjust it if some regions of the board becomes transparent """
|
||||
self.auto_crop_fuzz = 15
|
||||
""" [0,100] Chroma key tolerance (percent). Bigger values will remove more pixels """
|
||||
super().__init__()
|
||||
self._expand_ext = 'png'
|
||||
|
||||
|
|
@ -147,7 +171,7 @@ class Render3DOptions(Base3DOptions):
|
|||
self.copper = "#"+color
|
||||
break
|
||||
super().config(parent)
|
||||
self.validate_colors(self._colors.keys())
|
||||
self.validate_colors(list(self._colors.keys())+['auto_crop_color'])
|
||||
view = self._views.get(self.view, None)
|
||||
if view is not None:
|
||||
self.view = view
|
||||
|
|
@ -232,6 +256,9 @@ class Render3DOptions(Base3DOptions):
|
|||
"Please upgrade KiCad to 6.0.2 or newer")
|
||||
exit(MISSING_TOOL)
|
||||
command = self.ensure_tool('KiAuto')
|
||||
if self.auto_crop:
|
||||
self.background1 = self.background2 = self.auto_crop_color
|
||||
convert_command = self.ensure_tool('ImageMagick')
|
||||
# Base command with overwrite
|
||||
cmd = [command, '--rec_w', str(self.width+2), '--rec_h', str(self.height+85),
|
||||
'3d_view', '--output_name', output]
|
||||
|
|
@ -255,6 +282,12 @@ class Render3DOptions(Base3DOptions):
|
|||
video_name = os.path.join(self.expand_filename_pcb(GS.out_dir), 'pcbnew_3d_view_screencast.ogv')
|
||||
if os.path.isfile(video_name):
|
||||
os.remove(video_name)
|
||||
if self.auto_crop:
|
||||
_run_command([convert_command, output, '-fuzz', str(self.auto_crop_fuzz)+'%', '-transparent',
|
||||
self.color_str_to_rgb(self.auto_crop_color), output])
|
||||
# Don't ask me why I need 2 passes
|
||||
_run_command([convert_command, output, '-trim', '+repage', output])
|
||||
_run_command([convert_command, output, '-trim', '+repage', output])
|
||||
|
||||
|
||||
@output_class
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ deps = '{\
|
|||
],\
|
||||
"extra_deb": null,\
|
||||
"help_option": "--version",\
|
||||
"importance": 3,\
|
||||
"importance": 4,\
|
||||
"in_debian": true,\
|
||||
"is_kicad_plugin": false,\
|
||||
"is_python": false,\
|
||||
|
|
@ -190,6 +190,13 @@ deps = '{\
|
|||
"max_version": null,\
|
||||
"output": "pcbdraw",\
|
||||
"version": null\
|
||||
},\
|
||||
{\
|
||||
"desc": "Automatically crop images",\
|
||||
"mandatory": false,\
|
||||
"max_version": null,\
|
||||
"output": "render_3d",\
|
||||
"version": null\
|
||||
}\
|
||||
],\
|
||||
"tests": [],\
|
||||
|
|
|
|||
|
|
@ -2,18 +2,19 @@
|
|||
kibot:
|
||||
version: 1
|
||||
|
||||
global:
|
||||
solder_mask_color: blue
|
||||
pcb_finish: ENIG
|
||||
|
||||
outputs:
|
||||
- name: render_list
|
||||
comment: "Render with only some components"
|
||||
type: render_3d
|
||||
options:
|
||||
width: 800
|
||||
height: 600
|
||||
width: 1280
|
||||
height: 960
|
||||
orthographic: true
|
||||
zoom: 4
|
||||
show_components: ["RV1", "RV2", "U1", "U2", "U3"]
|
||||
ray_tracing: true
|
||||
background1: "#ff70b7"
|
||||
background2: "#ff70b7"
|
||||
# background1: "#ffffff"
|
||||
# background2: "#ffffff"
|
||||
auto_crop: true
|
||||
|
|
|
|||
Loading…
Reference in New Issue