* stitch plan preview png: 300, 600 dpi
* add png export dpi option
pull/3046/head
Kaalleen 2024-07-03 07:09:06 +02:00 zatwierdzone przez GitHub
rodzic 6c166dca61
commit 2b390b908e
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
8 zmienionych plików z 92 dodań i 49 usunięć

Wyświetl plik

@ -13,6 +13,12 @@ from .png_simple import write_png_output
class PngRealistic(InkstitchExtension):
def __init__(self, *args, **kwargs):
InkstitchExtension.__init__(self)
self.arg_parser.add_argument('--notebook')
self.arg_parser.add_argument('--dpi', type=int, default=300, dest='dpi')
def effect(self):
if not self.get_elements():
return
@ -26,7 +32,7 @@ class PngRealistic(InkstitchExtension):
layer = render_stitch_plan(self.svg, stitch_plan, True, visual_commands=False, render_jumps=False)
write_png_output(self.svg, layer)
write_png_output(self.svg, layer, self.options.dpi)
# don't let inkex output the SVG!
sys.exit(0)

Wyświetl plik

@ -20,8 +20,9 @@ class PngSimple(InkstitchExtension):
def __init__(self, *args, **kwargs):
InkstitchExtension.__init__(self)
self.arg_parser.add_argument('--notebook', type=str, default='')
self.arg_parser.add_argument('--line_width', type=str, default='', dest='line_width')
self.arg_parser.add_argument('--notebook')
self.arg_parser.add_argument('--line_width', type=float, default=0.3, dest='line_width')
self.arg_parser.add_argument('--dpi', type=int, default=300, dest='dpi')
def effect(self):
if not self.get_elements():
@ -38,13 +39,13 @@ class PngSimple(InkstitchExtension):
layer = render_stitch_plan(self.svg, stitch_plan, False, visual_commands=False,
render_jumps=False, line_width=line_width)
write_png_output(self.svg, layer)
write_png_output(self.svg, layer, self.options.dpi)
# don't let inkex output the SVG!
sys.exit(0)
def write_png_output(svg, layer):
def write_png_output(svg, layer, dpi):
with TemporaryDirectory() as tempdir:
# Inkex's command functionality also writes files to temp directories like this.
temp_svg_path = f"{tempdir}/temp.svg"
@ -52,7 +53,7 @@ def write_png_output(svg, layer):
with open(temp_svg_path, "wb") as f:
f.write(svg.tostring())
generate_png(svg, layer, temp_svg_path, temp_png_path)
generate_png(svg, layer, temp_svg_path, temp_png_path, dpi)
# inkscape will read the file contents from stdout and copy
# to the destination file that the user chose
@ -60,13 +61,13 @@ def write_png_output(svg, layer):
sys.stdout.buffer.write(output_file.read())
def generate_png(svg, layer, input_path, output_path):
def generate_png(svg, layer, input_path, output_path, dpi):
inkscape(input_path, actions="; ".join([
f"export-id:{layer.get_id()}",
f"export-id: {layer.get_id()}",
"export-id-only",
"export-type:png",
f"export-dpi:{96*8}",
f"export-filename:{output_path}",
f"export-background:{get_pagecolor(svg.namedview)}",
f"export-dpi: {dpi}",
f"export-filename: {output_path}",
f"export-background: {get_pagecolor(svg.namedview)}",
"export-do" # Inkscape docs say this should be implicit at the end, but it doesn't seem to be.
]))

Wyświetl plik

@ -38,7 +38,7 @@ class StitchPlanPreview(InkstitchExtension):
self.arg_parser.add_argument("-o", "--overwrite", type=Boolean, default=True, dest="overwrite")
def effect(self):
realistic, raster_mult = self.parse_mode()
realistic, dpi = self.parse_mode()
# delete old stitch plan
self.remove_old()
@ -58,7 +58,7 @@ class StitchPlanPreview(InkstitchExtension):
layer = render_stitch_plan(svg, stitch_plan, realistic, visual_commands, render_jumps=self.options.render_jumps)
if self.options.ignore_layer and not self.options.mode[-1].isdigit():
add_layer_commands(layer, ["ignore_layer"])
layer = self.rasterize(svg, layer, raster_mult)
layer = self.rasterize(svg, layer, dpi)
# update layer visibility (unchanged, hidden, lower opacity)
groups = self.document.getroot().findall(SVG_GROUP_TAG)
@ -72,27 +72,27 @@ class StitchPlanPreview(InkstitchExtension):
def parse_mode(self) -> Tuple[bool, Optional[int]]:
"""
Parse the "mode" option and return a tuple of a bool indicating if realistic rendering should be used,
and an optional int indicating the resolution multiplier to use for rasterization, or None if rasterization should not be used.
and an optional int indicating the dpi value to use for rasterization, or None if rasterization should not be used.
"""
realistic = False
raster_mult: Optional[int] = None
dpi: Optional[int] = None
render_mode = self.options.mode
if render_mode == "simple":
pass
elif render_mode.startswith("realistic-"):
realistic = True
raster_option = render_mode.split('-')[1]
if raster_option != "vector":
dpi_option = render_mode.split('-')[1]
if dpi_option != "vector":
try:
raster_mult = int(raster_option)
dpi = int(dpi_option)
except ValueError:
errormsg(f"Invalid raster mode {raster_option}")
errormsg(f"Invalid raster mode {dpi_option}")
sys.exit(1)
else:
errormsg(f"Invalid render mode {render_mode}")
sys.exit(1)
return (realistic, raster_mult)
return (realistic, dpi)
def remove_old(self):
svg = self.document.getroot()
@ -104,8 +104,8 @@ class StitchPlanPreview(InkstitchExtension):
if layer is not None:
layer.set('id', svg.get_unique_id('inkstitch_stitch_plan_'))
def rasterize(self, svg: BaseElement, layer: BaseElement, raster_mult: Optional[int]) -> BaseElement:
if raster_mult is None:
def rasterize(self, svg: BaseElement, layer: BaseElement, dpi: Optional[int]) -> BaseElement:
if dpi is None:
# Don't rasterize if there's no reason to.
return layer
else:
@ -121,16 +121,17 @@ class StitchPlanPreview(InkstitchExtension):
# Instead, especially because we need to invoke Inkscape anyway to perform the rasterization, we get
# the bounding box with query commands before we perform the export. This is quite cheap.
out = inkscape(temp_svg_path, actions="; ".join([
f"select-by-id:{layer.get_id()}",
f"select-by-id: {layer.get_id()}",
"query-x",
"query-y",
"query-width",
"query-height",
f"export-id:{layer.get_id()}",
f"export-id: {layer.get_id()}",
"export-id-only",
"export-type:png",
f"export-dpi:{96*raster_mult}",
f"export-filename:{temp_png_path}",
"export-type: png",
f"export-dpi: {dpi}",
"export-png-color-mode: RGBA_16",
f"export-filename: {temp_png_path}",
"export-do" # Inkscape docs say this should be implicit at the end, but it doesn't seem to be.
]))

Wyświetl plik

@ -30,7 +30,7 @@ class Zip(InkstitchExtension):
def __init__(self, *args, **kwargs):
InkstitchExtension.__init__(self)
self.arg_parser.add_argument('--notebook', type=str, default='')
self.arg_parser.add_argument('--notebook')
self.arg_parser.add_argument('--custom-file-name', type=str, default='', dest='custom_file_name')
# it's kind of obnoxious that I have to do this...
@ -44,10 +44,12 @@ class Zip(InkstitchExtension):
self.formats.append('svg')
self.arg_parser.add_argument('--format-threadlist', type=Boolean, default=False, dest='threadlist')
self.formats.append('threadlist')
self.arg_parser.add_argument('--format-png_realistic', type=Boolean, default=False, dest='png_realistic')
self.arg_parser.add_argument('--format-png-realistic', type=Boolean, default=False, dest='png_realistic')
self.arg_parser.add_argument('--dpi-realistic', type=int, default='', dest='dpi_realistic')
self.formats.append('png_realistic')
self.arg_parser.add_argument('--format-png_simple', type=Boolean, default=False, dest='png_simple')
self.arg_parser.add_argument('--png_simple_line_width', type=float, default=0.3, dest='line_width')
self.arg_parser.add_argument('--format-png-simple', type=Boolean, default=False, dest='png_simple')
self.arg_parser.add_argument('--png-simple-line-width', type=float, default=0.3, dest='line_width')
self.arg_parser.add_argument('--dpi-simple', type=int, default='', dest='dpi_simple')
self.formats.append('png_simple')
self.arg_parser.add_argument('--x-repeats', type=int, default=1, dest='x_repeats', )
@ -131,21 +133,21 @@ class Zip(InkstitchExtension):
elif format == 'png_realistic':
output_file = os.path.join(path, f"{base_file_name}_realistic.png")
layer = render_stitch_plan(self.svg, stitch_plan, True, visual_commands=False, render_jumps=False)
self.generate_png_output(output_file, layer)
self.generate_png_output(output_file, layer, self.options.dpi_realistic)
elif format == 'png_simple':
output_file = os.path.join(path, f"{base_file_name}_simple.png")
line_width = convert_unit(f"{self.options.line_width}mm", self.svg.document_unit)
layer = render_stitch_plan(self.svg, stitch_plan, False, visual_commands=False,
render_jumps=False, line_width=line_width)
self.generate_png_output(output_file, layer)
self.generate_png_output(output_file, layer, self.options.dpi_simple)
else:
write_embroidery_file(output_file, stitch_plan, self.document.getroot())
files.append(output_file)
return files
def generate_png_output(self, output_file, layer):
def generate_png_output(self, output_file, layer, dpi):
with tempfile.TemporaryDirectory() as tempdir:
temp_svg_path = f"{tempdir}/temp.svg"
with open(temp_svg_path, "wb") as f:
f.write(self.svg.tostring())
generate_png(self.svg, layer, temp_svg_path, output_file)
generate_png(self.svg, layer, temp_svg_path, output_file, dpi)

Wyświetl plik

@ -10,6 +10,20 @@
<dataloss>true</dataloss>
</output>
<param name="extension" type="string" gui-hidden="true">png_realistic</param>
<param name="notebook" type="notebook">
<page name="settings" gui-text="Settings">
<param name="dpi" type="int" min="100" max="2000" gui-text="DPI">300</param>
</page>
<page name="info" gui-text="Help">
<label appearance="header">PNG file export</label>
<label>Export embroidery design to PNG</label>
<spacer />
<separator />
<spacer />
<label>Read more on our website</label>
<label appearance="url">https://inkstitch.org/docs/import-export/</label>
</page>
</param>
<script>
{{ command_tag | safe }}
</script>

Wyświetl plik

@ -13,6 +13,7 @@
<param name="notebook" type="notebook">
<page name="settings" gui-text="Settings">
<param name="line_width" type="float" precision="2" min="0.01" max="5" gui-text="Line width (mm)">0.3</param>
<param name="dpi" type="int" min="100" max="2000" gui-text="DPI">300</param>
</page>
<page name="info" gui-text="Help">
<label appearance="header">PNG file export</label>
@ -20,7 +21,7 @@
<spacer />
<separator />
<spacer />
<label>Read more on our webiste</label>
<label>Read more on our website</label>
<label appearance="url">https://inkstitch.org/docs/import-export/</label>
</page>
</param>

Wyświetl plik

@ -14,8 +14,8 @@
<param name="render-mode" type="optiongroup" appearance="combo" gui-text="Render Mode"
gui-description="Realistic modes will render to a raster image for performance reasons. Realistic Vector may cause Inkscape to slow down for complex designs.">
<option value="simple">Simple</option>
<option value="realistic-8">Realistic</option>
<option value="realistic-16">Realistic High Quality</option>
<option value="realistic-300">Realistic</option>
<option value="realistic-600">Realistic High Quality</option>
<option value="realistic-vector">Realistic Vector (slow)</option>
</param>
<spacer />

Wyświetl plik

@ -9,23 +9,41 @@
<filetypetooltip>Create a ZIP with multiple embroidery file formats using Ink/Stitch</filetypetooltip>
<dataloss>true</dataloss>
</output>
<param name="extension" type="string" gui-hidden="true">zip</param>
<param name="custom-file-name" type="string" gui-text="Custom file name"
gui-description="Defines the file names inside the zip archive. Leave empty for default file name."></param>
<spacer />
<param name="notebook" type="notebook">
<page name="file-formats" gui-text="File Formats">
<label>Output formats:</label>
{%- for format, description, mimetype, category in formats %}
{%- if category != "vector" and category != "debug" %}
<param name="format-{{ format }}" type="boolean" gui-text=".{{ format | upper }}: {{ description }}">false</param>
{%- endif %}
{%- endfor %}
<param name="format-threadlist" type="boolean" gui-text=".TXT: Threadlist [COLOR]">false</param>
<param name="format-png_realistic" type="boolean" gui-text=".PNG: Portable Network Graphics (Realistic) [IMAGE]">false</param>
<param name="format-png_simple" type="boolean" gui-text=".PNG: Portable Network Graphics (Simple) [IMAGE]">false</param>
<param name="png_simple_line_width" type="float" precision="2" min="0.01" max="5" gui-text="Line width (mm)" indent="4">0.3</param>
<param name="format-svg" type="boolean" gui-text=".SVG: Scalable Vector Graphic">false</param>
<param name="extension" type="string" gui-hidden="true">zip</param>
<hbox>
<vbox>
{%- for format, description, mimetype, category in formats %}
{%- if category != "vector" and category != "debug" %}
<param name="format-{{ format }}" type="boolean" gui-text=".{{ format | upper }}: {{ description }}">false</param>
{%- endif %}
{%- if loop.index == 13 %}
</vbox>
<spacer />
<separator />
<spacer />
<vbox>
{%- endif %}
{%- endfor %}
<param name="format-threadlist" type="boolean" gui-text=".TXT: Threadlist [COLOR]">false</param>
</vbox>
<spacer />
<separator />
<spacer />
<vbox>
<param name="format-svg" type="boolean" gui-text=".SVG: Scalable Vector Graphic">false</param>
<param name="format-png-realistic" type="boolean" gui-text=".PNG: Portable Network Graphics (Realistic) [IMAGE]">false</param>
<param name="dpi-realistic" type="int" min="100" max="2000" gui-text="DPI" indent="4">300</param>
<param name="format-png-simple" type="boolean" gui-text=".PNG: Portable Network Graphics (Simple) [IMAGE]">false</param>
<param name="png-simple-line-width" type="float" precision="2" min="0.01" max="5" gui-text="Line width (mm)" indent="4">0.3</param>
<param name="dpi-simple" type="int" min="100" max="2000" gui-text="DPI" indent="4">300</param>
</vbox>
</hbox>
</page>
<page name="panelization" gui-text="Panelization Options">
<label>For single design set horizontal and vertical repeats to 1</label>