[Render_3D] Added option to auto-crop the resulting PNG

This commit is contained in:
Salvador E. Tropea 2022-10-30 14:35:18 -03:00
parent 5b19227625
commit 81ce2004d5
8 changed files with 100 additions and 20 deletions

View File

@ -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)

View File

@ -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/) [![Tool](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/llave-inglesa-22x22.png)](https://imagemagick.org/) [![Debian](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/debian-openlogo-22x22.png)](https://packages.debian.org/bullseye/imagemagick) ![Auto-download](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/auto_download-22x22.png)
- 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) [![Tool](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/llave-inglesa-22x22.png)](https://gitlab.gnome.org/GNOME/librsvg) [![Debian](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/debian-openlogo-22x22.png)](https://packages.debian.org/bullseye/librsvg2-bin) ![Auto-download](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/auto_download-22x22.png)
- 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/) [![Tool](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/llave-inglesa-22x22.png)](https://imagemagick.org/) [![Debian](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/debian-openlogo-22x22.png)](https://packages.debian.org/bullseye/imagemagick) ![Auto-download](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/auto_download-22x22.png)
- 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/) [![Tool](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/llave-inglesa-22x22.png)](https://www.ghostscript.com/) [![Debian](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/debian-openlogo-22x22.png)](https://packages.debian.org/bullseye/ghostscript) ![Auto-download](https://raw.githubusercontent.com/INTI-CMNB/KiBot/master/docs/images/auto_download-22x22.png)
- 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)

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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": [],\

View File

@ -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