svg2gcode 3.3.7__tar.gz → 4.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. svg2gcode-3.3.7/README.md → svg2gcode-4.0.2/PKG-INFO +88 -24
  2. svg2gcode-3.3.7/PKG-INFO → svg2gcode-4.0.2/README.md +71 -40
  3. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/pyproject.toml +6 -6
  4. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/__init__.py +1 -1
  5. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/__main__.py +51 -37
  6. svg2gcode-4.0.2/svg2gcode/svg_examples/README.md +26 -0
  7. svg2gcode-4.0.2/svg2gcode/svg_examples/gcode_output.zip +0 -0
  8. svg2gcode-4.0.2/svg2gcode/svg_examples/kye_circle_paws_orig copy.svg +354 -0
  9. svg2gcode-4.0.2/svg2gcode/svg_examples/kye_circle_paws_orig.svg +348 -0
  10. svg2gcode-4.0.2/svg2gcode/svg_examples/letterandsigns.svg +43 -0
  11. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/__init__.py +17 -6
  12. svg2gcode-4.0.2/svg2gcode/svg_to_gcode/compiler/_compiler.py +1034 -0
  13. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/compiler/interfaces/_gcode.py +9 -3
  14. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/css_color.py +29 -23
  15. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/formulas.py +5 -3
  16. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_line.py +47 -12
  17. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_line_segment_chain.py +41 -29
  18. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/svg_parser/_parser_methods.py +14 -11
  19. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/svg_parser/_path.py +1 -1
  20. svg2gcode-3.3.7/svg2gcode/svg_to_gcode/compiler/_compiler.py +0 -1148
  21. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/LICENSE +0 -0
  22. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/LICENSE +0 -0
  23. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/compiler/__init__.py +0 -0
  24. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/compiler/interfaces/__init__.py +0 -0
  25. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/compiler/interfaces/_abstract_interface.py +0 -0
  26. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/compiler/interfaces/_fan_controlled_gcode.py +0 -0
  27. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/__init__.py +0 -0
  28. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_abstract_chain.py +0 -0
  29. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_abstract_curve.py +0 -0
  30. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_circular_arc.py +0 -0
  31. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_cubic_bazier.py +0 -0
  32. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_elliptical_arc.py +0 -0
  33. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_matrix.py +0 -0
  34. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_quadratic_bazier.py +0 -0
  35. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_raster_image.py +0 -0
  36. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_smooth_arc_chain.py +0 -0
  37. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/geometry/_vector.py +0 -0
  38. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/svg_parser/__init__.py +0 -0
  39. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/svg_parser/_transformation.py +0 -0
  40. {svg2gcode-3.3.7 → svg2gcode-4.0.2}/svg2gcode/svg_to_gcode/svg_parser/debug_methods.py +0 -0
@@ -1,8 +1,55 @@
1
+ Metadata-Version: 2.5
2
+ Name: svg2gcode
3
+ Version: 4.0.2
4
+ Summary: svg2gcode: convert an SVG (Scalable Vector Graphic) image to gcode.
5
+ Keywords: scalable vector graphics,svg,image,laser cutter,laser engraving
6
+ Author-email: Johannes Noordanus <mailjohannes.mailnoordanus@gmail.com>
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Requires-Dist: numpy >= 1.24.3, <= 2.4.6
12
+ Requires-Dist: Pillow >= 12.2.0
13
+ Requires-Dist: image2gcode >= 2.9.17
14
+ Project-URL: Home, https://github.com/johannesnoordanus/svg2gcode
15
+ Import-Name: svg2gcode
16
+
1
17
  # svg2gcode
2
18
 
3
- *svg2gcode* is a *WYSIWYG* converter of Scalable Vector Graphic *(SVG)* drawings. It is based on library *SvgToGcode* (*https://github.com/johannesnoordanus/SvgToGcode*)<sup>(*)</sup>.
19
+ ### svg2gcode <small>is a *WYSIWYG* converter of Scalable Vector Graphic *(.svg)* drawings.</small>
20
+
21
+ It is based on library *SvgToGcode* (*https://github.com/johannesnoordanus/SvgToGcode*)<sup>(1)</sup>.
22
+ ### Version 4.0 is out now!
23
+ **svg2gcode 4.0** has a vastly improved *stroke* and *fill* and is even easier to control.
24
+ Lines with a certain width are now drawn almost perfectly in a vector like manner.
25
+ *fill* is also a vector (line) fill now.
26
+ Both types of fill *evenodd* and *nonzero* are supported and use a complete new render engine that directly renders to gcode.
27
+
28
+ It is very easy to convert text to gcode now, just create a *.svg* file using Inkscape for example, type in some text and convert it via ```object to path``` to a path.
29
+ Save this file in say *letters.svg* and type the following: <sup>(2)</sup>
30
+ ```
31
+ > svg2gcode --color_coded "allothercolors = engrave" letters.svg letters.gc
32
+ ```
33
+ This will generate a gcode file *letters.gc* which produces an exact copy of the text on your laser engraver.<br>
34
+ Option *--color_coded* is enhanced and accepts apart from *color* names, ```#hex```, ```rgb```, ```rgba```, ```hsl``` and ```hsla``` color codes.
35
+
36
+ As can be seen above a special 'color' ```allothercolors``` is added, which means what you think it means. So we can now name all colors we do not explicitly mention in the option to be able to *'ignore', 'cut' or 'engrave'* all other colors.<br>
37
+ More info on *--color_coded* and other program options and can be found below.
38
+
39
+ Fan control has also improved, it is now possible - apart from setting it on or off globally - to have fan on for ```engraving``` or ```cut``` only.
40
+
41
+ I put a lot of work into this program to get it right, but it might be that you encounter errors in which case you can contact me or put in an issue at *https://github.com/johannesnoordanus/svg2gcode*. You can also do a feature request in the same manner.
42
+
43
+ Have fun using it.
44
+
45
+ Johannes
46
+
47
+ <sup>(2)</sup> It is also possible to leave out option *--color-coded* because engraving is the default.
48
+
49
+ -----
50
+ ### General description
4
51
 
5
- Drawings and images can be composed using Inkscape (or other *SVG* image software), saved to a *.svg* file and - *WYSIWYG* - converted to gcode.
52
+ Drawings and images can be composed using Inkscape (or other *SVG* image software), saved to a *.svg* file and *WYSIWYG* converted to gcode.
6
53
  Color coding can be used to mark what part(s) of the drawing to cut, engrave or even ignore.
7
54
 
8
55
  Raster elements within a *SVG* drawing are converted pixel perfect, vector elements are drawn at the specified resolution.
@@ -17,15 +64,13 @@ More info can be obtained by looking at the documentation and examples below and
17
64
 
18
65
  *svg2gcode* has three related programs: *image2gcode* mentioned above has similar capabilities but handles raster image files (like *png* and *jpg*) directly, *gcode2image* performs the inverse function and is capable of showing multiple writes (burns) to the same location and last *grblhud* which gives full control over gcode execution.
19
66
 
20
- <sup>(*)</sup> Note that an upgraded and corrected version of this library is included.
67
+ <sup>(1)</sup> Note that an upgraded and corrected version of this library is included.
21
68
 
22
69
  -----
23
70
 
24
71
  If you find this application useful, please consider donating, so I can continue maintaining and enhancing it.<br>
25
72
  <http://paypal.me/johannesnoordanus/5,00>
26
73
 
27
- My next update will add *fill-rule* 'nonzero' (see information on *fill-rule* below).
28
-
29
74
  -----
30
75
 
31
76
  ### Supported SVG elements and attributes
@@ -33,11 +78,16 @@ My next update will add *fill-rule* 'nonzero' (see information on *fill-rule* be
33
78
  *SVG* *path* and *image* elements (specific: ```<svg:path ..>```tags and images```<svg:image ..>```tags) are supported. Other drawing objects must be converted to a *path* first to be able to translate them to a gcode sequence.
34
79
 
35
80
  Attributes *stroke* (color), *stroke-width*, *stroke_alpha*, *fill* (color), *fill-rule*, *fill_alpha* are supported.
36
- Currently only value *evenodd* of *fill-rule* is supported.
81
+ *fill-rule* is currently fully supported and accepts values *evenodd* and *nonzero* of which the latter is default.
82
+ With option ```svg2gcode --fillrule "evenodd|nonzero"``` you can set your own preference from the commandline.
37
83
 
38
84
  ### *WYSIWYG*
39
85
 
40
- As seen above, not all *svg* elements are directly supported, but they are after a *path* conversion within the composer (Inkscape: ```menu Path->Object/Stroke to Path```). Without a *path* conversion *svg2gcode* simply ignores all elements except *path* and *image*. Text (fonts) require another step after *selecting* all text and clicking menu ```Object to Path```. Clicking menu```Object->Ungroup``` <sup>(**)</sup> generates a separate *path* for each letter which contains all relevant attributes. (Otherwise Inkscape uses a group tag ```<g``` to set some attributes for all letters within the text that are not repeated for each individual letter.)
86
+ As seen above, not all *svg* elements are directly supported, but they are after a *path* conversion within the composer (Inkscape: ```menu Path->Object/Stroke to Path```). Without a *path* conversion *svg2gcode* simply ignores all elements except *path* and *image*.
87
+
88
+ Depending on your preference text (fonts) require another step in Inkscape after *selecting* all text and clicking menu ```Object to Path```. Clicking menu```Object->Ungroup``` <sup>(3)</sup> generates a separate *path* for each letter which contains all relevant attributes. (Otherwise Inkscape uses a group tag ```<g``` to set some attributes for all letters within the text that are not repeated for each individual letter.)
89
+
90
+ If you *Ungroup* each character is rendered separately to gcode and this means that *stroke* and *fill* is done per character. Version 4.0 of *svg2gcode* has no problem rendering - do *stroke* and *fill* - for all text combined but note that it is a different situation.
41
91
 
42
92
  You can use *gcode2image* to check the conversion result:
43
93
  ```
@@ -48,27 +98,37 @@ The image shown should be the same as the one shown by the composer (Inkscape).
48
98
 
49
99
  #### Contour & fill
50
100
 
51
- Inkscape translates a contour of a raster image to an outline and fill. So, if you create a contour via (select bitmap first) ```Path->Trace Bitmap...``` slide the ```Treshold``` of the Trace Bitmap menu to almost 1 (0,995) to make the entire bitmap image black (this is a bit *trial and error*, use ```Update preview``` to get the highest slider value before the whole images is black).
101
+ Inkscape translates a contour of a raster image to an outline and fill. So, if you create a contour using Inkscape via (select bitmap first) ```Path->Trace Bitmap...``` slide the ```Treshold``` of the Trace Bitmap menu to almost 1 (0,995) to make the entire bitmap image black (this is a bit *trial and error*, use ```Update preview``` to get the highest slider value before the whole images is black), the style attribute will look like:
52
102
 
53
- You can look at the result xml tree via Inkscapes ```XML editor``` which now shows a path for the outline of the raster image and a style attribue like this:
54
103
  ```
55
104
  style fill:#000000;stroke-width:0.172652
56
105
  ```
106
+
107
+ You see this in the ```.svg``` file or the xml tree via Inkscapes ```XML editor``` which now shows a path for the outline of the raster image and a style attribute.
108
+
57
109
  To cut this outline, you can set the *fill* attribute to *none* (via the ```XML editor``` or menu ```Fill and Stroke```) and set a specific *stroke* color, for example *red*. The following command generates gcode to cut the outline.
58
110
  ```
59
111
  > svg2gcode --color_coded "red = cut" contour.svg contour.gc
112
+
113
+ ```
114
+ You can also engrave the whole bitmap image by setting a specific fill color (via menu ```Fill and Stroke```); in this case there is no need to use option ```color_coded``` because engraving is the default. But remember that is it possible to ignore (or engrave or cut) all other colors by using the special keyword ```allothercolors```.
115
+
116
+ For example if you have the following:
117
+
118
+ ```
119
+ svg2gcode --showimage --fillrule evenodd --color_coded "#0F0F0F = engrave, green = cut, allothercolors = ignore" some.svg some.gc
60
120
  ```
61
- You can also engrave the whole bitmap image by setting a specific fill color (via menu ```Fill and Stroke```) (in this case there is no need to use option ```color_coded```)
121
+ Lines having color code *#0F0F0F* will be engraved and line having color name 'green' will be cut, while all other colors you might have in your drawing will be ignored.
62
122
 
63
123
  #### Notes
64
124
 
65
125
  - drawing objects - within the composer - must be converted to a```path```to be translated to a gcode sequence
66
126
  - image objects should **not** be converted to a ```path```
67
- - images must be linked or embedded using base64 (Inkscape default).
127
+ - images must be linked or embedded using base64 (Inkscape default)
68
128
  - images can be in several formats (my tests included *.png* and *.jpg* image files)
69
- - *SVG* source documents must be in unit 'mm' and set to ```1 'user unit' is 1 mm``` (Inkscape default)
129
+ - vector graphics (*.svg*) source documents must be in unit 'mm' and set to ```1 'user unit' is 1 mm``` (Inkscape default)
70
130
 
71
- <sup>(**)</sup> Note that the latest version of *svg2gcode* (3.3.4) has support for ```<g``` tags (attribute inheritance) and is able to correctly convert text without ```Ungroup```.
131
+ <sup>(3)</sup> Note that the latest version of *svg2gcode* (4.0.0) has support for ```<g``` tags (attribute inheritance) and is able to correctly convert text without ```Ungroup```.
72
132
 
73
133
  ### Important Commandline options
74
134
 
@@ -78,7 +138,7 @@ For example:
78
138
  > svg2gcode --color_coded "black = ignore red = cut blue = engrave" paws.svg paws.gc
79
139
  ```
80
140
  As a consequence all 'black' path elements will be ignored and will not appear after conversion, all red paths will be cut and all blue paths will be engraved (having color blue).
81
- The corresponding gcode file contains lines like below to indicated which 'black path' is skipped:
141
+ The corresponding gcode (*.gc*) file contains lines like below to indicated which 'black path' is skipped:
82
142
  ```
83
143
  ; svg2gcode 3.2.8 (2024-07-28 11:39:27)
84
144
  ; arguments:
@@ -131,7 +191,7 @@ Note that these attributes override explicit or default commandline settings.
131
191
 
132
192
  ### gcode optimizations
133
193
 
134
- Optimized gcode
194
+ Optimized gcode for images
135
195
  - draw pixels in one go until change of power
136
196
  - emit X/Y coordinates only when they change
137
197
  - emit linear move 'G1/G0' code minimally
@@ -139,7 +199,7 @@ Optimized gcode
139
199
 
140
200
  General optimizations
141
201
  - laser head has deferred and sparse moves.
142
- (XY locations are virtual, head does not always follow)
202
+ (XY locations are virtual, head does not always follow)
143
203
  - moves at high speed (G0) over 10mm (default) or more zero pixels
144
204
  - low burn levels (stray pixels) can be suppressed (default off)
145
205
  - default --constantburn mode *gcode M3*
@@ -160,12 +220,11 @@ Some linux distributions use a managed environment in which you cannot install p
160
220
  ### Usage:
161
221
  ```
162
222
  > svg2gcode --help
163
- usage: runsvg2gcode [-h] [--showimage] [--selfcenter] [--pixelsize <default:0.1>] [--imagespeed <default:800>] [--cuttingspeed <default:1000>] [--imagepower <default:300>]
164
- [--poweroffset <default:0>] [--cuttingpower <default:850>] [--passes <default:1>] [--pass_depth <default:0>] [--rapidmove <default:10>]
165
- [--noise <default:0>] [--overscan <default:0>] [--showoverscan] [--constantburn | --no-constantburn] [--origin delta-x delta-y] [--scale factor-x factor-y]
166
- [--rotate <default:0>] [--splitfile] [--pathcut] [--nofill] [--xmaxtravel <default:300>] [--ymaxtravel <default:400>] [--color_coded <default:"">] [--fan]
167
- [-V]
168
- svg gcode
223
+ usage: svg2gcode [-h] [--showimage] [--selfcenter] [--pixelsize <default:0.1>] [--imagespeed <default:800>] [--cuttingspeed <default:1000>] [--imagepower <default:300>] [--poweroffset <default:0>]
224
+ [--cuttingpower <default:850>] [--passes <default:1>] [--pass_depth <default:0>] [--rapidmove <default:10>] [--noise <default:0>] [--overscan <default:0>] [--showoverscan]
225
+ [--constantburn | --no-constantburn] [--origin delta-x delta-y] [--scale factor-x factor-y] [--rotate <default:0>] [--splitfile] [--pathcut] [--nofill] [--fillrule <default:"nonzero">]
226
+ [--xmaxtravel <default:300>] [--ymaxtravel <default:400>] [--color_coded <default:"">] [--fan <default:"off">] [-V]
227
+ svg gcode
169
228
 
170
229
  Convert svg to gcode for GRBL v1.1 compatible diode laser engravers.
171
230
 
@@ -208,13 +267,17 @@ options:
208
267
  --splitfile split gcode output of SVG path and image objects
209
268
  --pathcut alway cut SVG path objects! (use laser power set with option --cuttingpower)
210
269
  --nofill ignore SVG fill attribute
270
+ --fillrule <default:"nonzero">
271
+ set fill rule to [nonzero|evenodd]
211
272
  --xmaxtravel <default:300>
212
273
  machine x-axis lengh in mm
213
274
  --ymaxtravel <default:400>
214
275
  machine y-axis lengh in mm
215
276
  --color_coded <default:"">
216
- set action for path with specific stroke color "[color = [cut|engrave|ignore] *]*", example: --color_coded "black = ignore purple = cut blue = engrave"
217
- --fan set machine fan on
277
+ set action for path with specific stroke color "[[color|allothercolors] = [cut|engrave|ignore] *]*", example: --color_coded "black = ignore purple = cut blue = engrave allothercolors
278
+ = ignore"
279
+ --fan <default:"off">
280
+ set fan [on|off|on_engrave|on_cut]
218
281
  -V, --version show version number and exit
219
282
  ```
220
283
 
@@ -368,3 +431,4 @@ One containing the drawings of the .svg, the other containing the images:
368
431
 
369
432
  Default *svg2gcode* uses constant burn mode *M3*. This can be changed by setting option *--no-constantburn* which selects burn mode *M4*. Mode *M4* is not suitable for engravings because it automatically compensates (laser)power for speed. This conflicts with the specific gcode settings given by *image2gcode* (called by *svg2gcode*) for each pixel. In fact some experiments show that *M4* causes loss of quality and image deterioration when speed is increased. On white oak images had too much black and grey which did not go away for substantially higher speed. When switched back to constant burn (*M3*) mode, the same high speed gave excellent images having a sepia (licht yellow brown) color tone.
370
433
 
434
+
@@ -1,23 +1,39 @@
1
- Metadata-Version: 2.4
2
- Name: svg2gcode
3
- Version: 3.3.7
4
- Summary: svg2gcode: convert an SVG (Scalable Vector Graphic) image to gcode.
5
- Keywords: scalable vector graphics,svg,image,laser cutter,laser engraving
6
- Author-email: Johannes Noordanus <mailjohannes.mailnoordanus@gmail.com>
7
- Requires-Python: >=3.11
8
- Description-Content-Type: text/markdown
9
- Classifier: License :: OSI Approved :: MIT License
10
- License-File: LICENSE
11
- Requires-Dist: numpy >= 1.24.3
12
- Requires-Dist: Pillow >= 9.5.0
13
- Requires-Dist: image2gcode >= 2.9.8
14
- Project-URL: Home, https://github.com/johannesnoordanus/svg2gcode
15
-
16
1
  # svg2gcode
17
2
 
18
- *svg2gcode* is a *WYSIWYG* converter of Scalable Vector Graphic *(SVG)* drawings. It is based on library *SvgToGcode* (*https://github.com/johannesnoordanus/SvgToGcode*)<sup>(*)</sup>.
3
+ ### svg2gcode <small>is a *WYSIWYG* converter of Scalable Vector Graphic *(.svg)* drawings.</small>
4
+
5
+ It is based on library *SvgToGcode* (*https://github.com/johannesnoordanus/SvgToGcode*)<sup>(1)</sup>.
6
+ ### Version 4.0 is out now!
7
+ **svg2gcode 4.0** has a vastly improved *stroke* and *fill* and is even easier to control.
8
+ Lines with a certain width are now drawn almost perfectly in a vector like manner.
9
+ *fill* is also a vector (line) fill now.
10
+ Both types of fill *evenodd* and *nonzero* are supported and use a complete new render engine that directly renders to gcode.
11
+
12
+ It is very easy to convert text to gcode now, just create a *.svg* file using Inkscape for example, type in some text and convert it via ```object to path``` to a path.
13
+ Save this file in say *letters.svg* and type the following: <sup>(2)</sup>
14
+ ```
15
+ > svg2gcode --color_coded "allothercolors = engrave" letters.svg letters.gc
16
+ ```
17
+ This will generate a gcode file *letters.gc* which produces an exact copy of the text on your laser engraver.<br>
18
+ Option *--color_coded* is enhanced and accepts apart from *color* names, ```#hex```, ```rgb```, ```rgba```, ```hsl``` and ```hsla``` color codes.
19
+
20
+ As can be seen above a special 'color' ```allothercolors``` is added, which means what you think it means. So we can now name all colors we do not explicitly mention in the option to be able to *'ignore', 'cut' or 'engrave'* all other colors.<br>
21
+ More info on *--color_coded* and other program options and can be found below.
22
+
23
+ Fan control has also improved, it is now possible - apart from setting it on or off globally - to have fan on for ```engraving``` or ```cut``` only.
24
+
25
+ I put a lot of work into this program to get it right, but it might be that you encounter errors in which case you can contact me or put in an issue at *https://github.com/johannesnoordanus/svg2gcode*. You can also do a feature request in the same manner.
26
+
27
+ Have fun using it.
28
+
29
+ Johannes
30
+
31
+ <sup>(2)</sup> It is also possible to leave out option *--color-coded* because engraving is the default.
32
+
33
+ -----
34
+ ### General description
19
35
 
20
- Drawings and images can be composed using Inkscape (or other *SVG* image software), saved to a *.svg* file and - *WYSIWYG* - converted to gcode.
36
+ Drawings and images can be composed using Inkscape (or other *SVG* image software), saved to a *.svg* file and *WYSIWYG* converted to gcode.
21
37
  Color coding can be used to mark what part(s) of the drawing to cut, engrave or even ignore.
22
38
 
23
39
  Raster elements within a *SVG* drawing are converted pixel perfect, vector elements are drawn at the specified resolution.
@@ -32,15 +48,13 @@ More info can be obtained by looking at the documentation and examples below and
32
48
 
33
49
  *svg2gcode* has three related programs: *image2gcode* mentioned above has similar capabilities but handles raster image files (like *png* and *jpg*) directly, *gcode2image* performs the inverse function and is capable of showing multiple writes (burns) to the same location and last *grblhud* which gives full control over gcode execution.
34
50
 
35
- <sup>(*)</sup> Note that an upgraded and corrected version of this library is included.
51
+ <sup>(1)</sup> Note that an upgraded and corrected version of this library is included.
36
52
 
37
53
  -----
38
54
 
39
55
  If you find this application useful, please consider donating, so I can continue maintaining and enhancing it.<br>
40
56
  <http://paypal.me/johannesnoordanus/5,00>
41
57
 
42
- My next update will add *fill-rule* 'nonzero' (see information on *fill-rule* below).
43
-
44
58
  -----
45
59
 
46
60
  ### Supported SVG elements and attributes
@@ -48,11 +62,16 @@ My next update will add *fill-rule* 'nonzero' (see information on *fill-rule* be
48
62
  *SVG* *path* and *image* elements (specific: ```<svg:path ..>```tags and images```<svg:image ..>```tags) are supported. Other drawing objects must be converted to a *path* first to be able to translate them to a gcode sequence.
49
63
 
50
64
  Attributes *stroke* (color), *stroke-width*, *stroke_alpha*, *fill* (color), *fill-rule*, *fill_alpha* are supported.
51
- Currently only value *evenodd* of *fill-rule* is supported.
65
+ *fill-rule* is currently fully supported and accepts values *evenodd* and *nonzero* of which the latter is default.
66
+ With option ```svg2gcode --fillrule "evenodd|nonzero"``` you can set your own preference from the commandline.
52
67
 
53
68
  ### *WYSIWYG*
54
69
 
55
- As seen above, not all *svg* elements are directly supported, but they are after a *path* conversion within the composer (Inkscape: ```menu Path->Object/Stroke to Path```). Without a *path* conversion *svg2gcode* simply ignores all elements except *path* and *image*. Text (fonts) require another step after *selecting* all text and clicking menu ```Object to Path```. Clicking menu```Object->Ungroup``` <sup>(**)</sup> generates a separate *path* for each letter which contains all relevant attributes. (Otherwise Inkscape uses a group tag ```<g``` to set some attributes for all letters within the text that are not repeated for each individual letter.)
70
+ As seen above, not all *svg* elements are directly supported, but they are after a *path* conversion within the composer (Inkscape: ```menu Path->Object/Stroke to Path```). Without a *path* conversion *svg2gcode* simply ignores all elements except *path* and *image*.
71
+
72
+ Depending on your preference text (fonts) require another step in Inkscape after *selecting* all text and clicking menu ```Object to Path```. Clicking menu```Object->Ungroup``` <sup>(3)</sup> generates a separate *path* for each letter which contains all relevant attributes. (Otherwise Inkscape uses a group tag ```<g``` to set some attributes for all letters within the text that are not repeated for each individual letter.)
73
+
74
+ If you *Ungroup* each character is rendered separately to gcode and this means that *stroke* and *fill* is done per character. Version 4.0 of *svg2gcode* has no problem rendering - do *stroke* and *fill* - for all text combined but note that it is a different situation.
56
75
 
57
76
  You can use *gcode2image* to check the conversion result:
58
77
  ```
@@ -63,27 +82,37 @@ The image shown should be the same as the one shown by the composer (Inkscape).
63
82
 
64
83
  #### Contour & fill
65
84
 
66
- Inkscape translates a contour of a raster image to an outline and fill. So, if you create a contour via (select bitmap first) ```Path->Trace Bitmap...``` slide the ```Treshold``` of the Trace Bitmap menu to almost 1 (0,995) to make the entire bitmap image black (this is a bit *trial and error*, use ```Update preview``` to get the highest slider value before the whole images is black).
85
+ Inkscape translates a contour of a raster image to an outline and fill. So, if you create a contour using Inkscape via (select bitmap first) ```Path->Trace Bitmap...``` slide the ```Treshold``` of the Trace Bitmap menu to almost 1 (0,995) to make the entire bitmap image black (this is a bit *trial and error*, use ```Update preview``` to get the highest slider value before the whole images is black), the style attribute will look like:
67
86
 
68
- You can look at the result xml tree via Inkscapes ```XML editor``` which now shows a path for the outline of the raster image and a style attribue like this:
69
87
  ```
70
88
  style fill:#000000;stroke-width:0.172652
71
89
  ```
90
+
91
+ You see this in the ```.svg``` file or the xml tree via Inkscapes ```XML editor``` which now shows a path for the outline of the raster image and a style attribute.
92
+
72
93
  To cut this outline, you can set the *fill* attribute to *none* (via the ```XML editor``` or menu ```Fill and Stroke```) and set a specific *stroke* color, for example *red*. The following command generates gcode to cut the outline.
73
94
  ```
74
95
  > svg2gcode --color_coded "red = cut" contour.svg contour.gc
96
+
97
+ ```
98
+ You can also engrave the whole bitmap image by setting a specific fill color (via menu ```Fill and Stroke```); in this case there is no need to use option ```color_coded``` because engraving is the default. But remember that is it possible to ignore (or engrave or cut) all other colors by using the special keyword ```allothercolors```.
99
+
100
+ For example if you have the following:
101
+
102
+ ```
103
+ svg2gcode --showimage --fillrule evenodd --color_coded "#0F0F0F = engrave, green = cut, allothercolors = ignore" some.svg some.gc
75
104
  ```
76
- You can also engrave the whole bitmap image by setting a specific fill color (via menu ```Fill and Stroke```) (in this case there is no need to use option ```color_coded```)
105
+ Lines having color code *#0F0F0F* will be engraved and line having color name 'green' will be cut, while all other colors you might have in your drawing will be ignored.
77
106
 
78
107
  #### Notes
79
108
 
80
109
  - drawing objects - within the composer - must be converted to a```path```to be translated to a gcode sequence
81
110
  - image objects should **not** be converted to a ```path```
82
- - images must be linked or embedded using base64 (Inkscape default).
111
+ - images must be linked or embedded using base64 (Inkscape default)
83
112
  - images can be in several formats (my tests included *.png* and *.jpg* image files)
84
- - *SVG* source documents must be in unit 'mm' and set to ```1 'user unit' is 1 mm``` (Inkscape default)
113
+ - vector graphics (*.svg*) source documents must be in unit 'mm' and set to ```1 'user unit' is 1 mm``` (Inkscape default)
85
114
 
86
- <sup>(**)</sup> Note that the latest version of *svg2gcode* (3.3.4) has support for ```<g``` tags (attribute inheritance) and is able to correctly convert text without ```Ungroup```.
115
+ <sup>(3)</sup> Note that the latest version of *svg2gcode* (4.0.0) has support for ```<g``` tags (attribute inheritance) and is able to correctly convert text without ```Ungroup```.
87
116
 
88
117
  ### Important Commandline options
89
118
 
@@ -93,7 +122,7 @@ For example:
93
122
  > svg2gcode --color_coded "black = ignore red = cut blue = engrave" paws.svg paws.gc
94
123
  ```
95
124
  As a consequence all 'black' path elements will be ignored and will not appear after conversion, all red paths will be cut and all blue paths will be engraved (having color blue).
96
- The corresponding gcode file contains lines like below to indicated which 'black path' is skipped:
125
+ The corresponding gcode (*.gc*) file contains lines like below to indicated which 'black path' is skipped:
97
126
  ```
98
127
  ; svg2gcode 3.2.8 (2024-07-28 11:39:27)
99
128
  ; arguments:
@@ -146,7 +175,7 @@ Note that these attributes override explicit or default commandline settings.
146
175
 
147
176
  ### gcode optimizations
148
177
 
149
- Optimized gcode
178
+ Optimized gcode for images
150
179
  - draw pixels in one go until change of power
151
180
  - emit X/Y coordinates only when they change
152
181
  - emit linear move 'G1/G0' code minimally
@@ -154,7 +183,7 @@ Optimized gcode
154
183
 
155
184
  General optimizations
156
185
  - laser head has deferred and sparse moves.
157
- (XY locations are virtual, head does not always follow)
186
+ (XY locations are virtual, head does not always follow)
158
187
  - moves at high speed (G0) over 10mm (default) or more zero pixels
159
188
  - low burn levels (stray pixels) can be suppressed (default off)
160
189
  - default --constantburn mode *gcode M3*
@@ -175,12 +204,11 @@ Some linux distributions use a managed environment in which you cannot install p
175
204
  ### Usage:
176
205
  ```
177
206
  > svg2gcode --help
178
- usage: runsvg2gcode [-h] [--showimage] [--selfcenter] [--pixelsize <default:0.1>] [--imagespeed <default:800>] [--cuttingspeed <default:1000>] [--imagepower <default:300>]
179
- [--poweroffset <default:0>] [--cuttingpower <default:850>] [--passes <default:1>] [--pass_depth <default:0>] [--rapidmove <default:10>]
180
- [--noise <default:0>] [--overscan <default:0>] [--showoverscan] [--constantburn | --no-constantburn] [--origin delta-x delta-y] [--scale factor-x factor-y]
181
- [--rotate <default:0>] [--splitfile] [--pathcut] [--nofill] [--xmaxtravel <default:300>] [--ymaxtravel <default:400>] [--color_coded <default:"">] [--fan]
182
- [-V]
183
- svg gcode
207
+ usage: svg2gcode [-h] [--showimage] [--selfcenter] [--pixelsize <default:0.1>] [--imagespeed <default:800>] [--cuttingspeed <default:1000>] [--imagepower <default:300>] [--poweroffset <default:0>]
208
+ [--cuttingpower <default:850>] [--passes <default:1>] [--pass_depth <default:0>] [--rapidmove <default:10>] [--noise <default:0>] [--overscan <default:0>] [--showoverscan]
209
+ [--constantburn | --no-constantburn] [--origin delta-x delta-y] [--scale factor-x factor-y] [--rotate <default:0>] [--splitfile] [--pathcut] [--nofill] [--fillrule <default:"nonzero">]
210
+ [--xmaxtravel <default:300>] [--ymaxtravel <default:400>] [--color_coded <default:"">] [--fan <default:"off">] [-V]
211
+ svg gcode
184
212
 
185
213
  Convert svg to gcode for GRBL v1.1 compatible diode laser engravers.
186
214
 
@@ -223,13 +251,17 @@ options:
223
251
  --splitfile split gcode output of SVG path and image objects
224
252
  --pathcut alway cut SVG path objects! (use laser power set with option --cuttingpower)
225
253
  --nofill ignore SVG fill attribute
254
+ --fillrule <default:"nonzero">
255
+ set fill rule to [nonzero|evenodd]
226
256
  --xmaxtravel <default:300>
227
257
  machine x-axis lengh in mm
228
258
  --ymaxtravel <default:400>
229
259
  machine y-axis lengh in mm
230
260
  --color_coded <default:"">
231
- set action for path with specific stroke color "[color = [cut|engrave|ignore] *]*", example: --color_coded "black = ignore purple = cut blue = engrave"
232
- --fan set machine fan on
261
+ set action for path with specific stroke color "[[color|allothercolors] = [cut|engrave|ignore] *]*", example: --color_coded "black = ignore purple = cut blue = engrave allothercolors
262
+ = ignore"
263
+ --fan <default:"off">
264
+ set fan [on|off|on_engrave|on_cut]
233
265
  -V, --version show version number and exit
234
266
  ```
235
267
 
@@ -383,4 +415,3 @@ One containing the drawings of the .svg, the other containing the images:
383
415
 
384
416
  Default *svg2gcode* uses constant burn mode *M3*. This can be changed by setting option *--no-constantburn* which selects burn mode *M4*. Mode *M4* is not suitable for engravings because it automatically compensates (laser)power for speed. This conflicts with the specific gcode settings given by *image2gcode* (called by *svg2gcode*) for each pixel. In fact some experiments show that *M4* causes loss of quality and image deterioration when speed is increased. On white oak images had too much black and grey which did not go away for substantially higher speed. When switched back to constant burn (*M3*) mode, the same high speed gave excellent images having a sepia (licht yellow brown) color tone.
385
417
 
386
-
@@ -1,20 +1,20 @@
1
1
  [build-system]
2
- requires = ["flit_core >=3.2,<4"]
2
+ requires = ["flit_core >=3.11,<5"]
3
3
  build-backend = "flit_core.buildapi"
4
4
 
5
5
  [project]
6
6
  name = "svg2gcode"
7
7
  authors = [{name = "Johannes Noordanus", email = "mailjohannes.mailnoordanus@gmail.com"}]
8
8
  readme = "README.md"
9
- license = {file = "LICENSE"}
10
- classifiers = ["License :: OSI Approved :: MIT License"]
9
+ license = "MIT"
10
+ license-files = ["LICENSE"]
11
11
  dynamic = ["version", "description"]
12
12
 
13
13
  keywords = ["scalable vector graphics", "svg", "image", "laser cutter", "laser engraving"]
14
14
  dependencies = [
15
- "numpy >= 1.24.3",
16
- "Pillow >= 9.5.0",
17
- "image2gcode >= 2.9.8",
15
+ "numpy >= 1.24.3, <= 2.4.6",
16
+ "Pillow >= 12.2.0",
17
+ "image2gcode >= 2.9.17",
18
18
  ]
19
19
  requires-python = ">=3.11"
20
20
 
@@ -1,4 +1,4 @@
1
1
  """
2
2
  svg2gcode: convert an SVG (Scalable Vector Graphic) image to gcode.
3
3
  """
4
- __version__ = "3.3.7"
4
+ __version__ = "4.0.2"
@@ -5,6 +5,8 @@ svg2gcode: convert an image to gcode.
5
5
  import os
6
6
  import sys
7
7
  import re
8
+ import logging
9
+ import warnings
8
10
  try:
9
11
  import tomllib
10
12
  except ImportError:
@@ -21,6 +23,14 @@ from svg2gcode.svg_to_gcode import css_color
21
23
 
22
24
  config_file = os.path.expanduser('~/.config/svg2gcode.toml')
23
25
 
26
+ # Set logging global disable flag
27
+ ##logging.disable(logging.CRITICAL + 1)
28
+
29
+ # Set warnings disable flag (use python option -W to enable warnings)
30
+ if not sys.warnoptions:
31
+ warnings.simplefilter("ignore")
32
+
33
+
24
34
  # Notes:
25
35
  # - drawing objects (when using Inkscape for example) must be converted to a 'path' to be translated in a gcode sequence
26
36
  # - images objects should NOT be converted a 'path'
@@ -37,25 +47,11 @@ def svg2gcode(args) -> int:
37
47
  'maximum_image_laser_power':args.imagepower, 'image_movement_speed':args.imagespeed, 'fan':args.fan,'rapid_move':args.rapidmove,
38
48
  'showimage':args.showimage, 'x_axis_maximum_travel':args.xmaxtravel,'y_axis_maximum_travel':args.ymaxtravel, 'image_noise':args.noise,
39
49
  'pass_depth':args.pass_depth, 'laser_mode':"constant" if args.constantburn else "dynamic", 'splitfile':args.splitfile, 'pathcut':args.pathcut,
40
- 'nofill':args.nofill, 'image_poweroffset':args.poweroffset, 'image_overscan':args.overscan, 'image_showoverscan':args.showoverscan,
50
+ 'nofill':args.nofill, 'fillrule':args.fillrule, 'image_poweroffset':args.poweroffset, 'image_overscan':args.overscan, 'image_showoverscan':args.showoverscan,
41
51
  'color_coded': args.color_coded,})
42
52
 
43
53
  compiler = init_compiler(args)
44
54
 
45
- if args.color_coded != "":
46
- # check color_coded argument validity (2)
47
- pathignore, pathcut, pathengrave = compiler.color_coded_paths(True)
48
-
49
- # a path color should be in one set only
50
- for i in pathignore:
51
- if i in pathcut or i in pathengrave:
52
- print(f"argument error: '--color_coded \"{args.color_coded}\"' has a path color '{i}' set in multiple categories (cut|engrave|ignore) .")
53
- return 1
54
- for i in pathcut:
55
- if i in pathengrave:
56
- print(f"argument error: '--color_coded \"{args.color_coded}\"' has a path color '{i}' set in multiple categories (cut|engrave|ignore) .")
57
- return 1
58
-
59
55
  # emit gcode for svg
60
56
  if args.selfcenter:
61
57
  print("pass 1")
@@ -109,8 +105,10 @@ def main() -> int:
109
105
  "pass_depth_default": 0,
110
106
  "passes_default": 1,
111
107
  "rotate_default": 0,
108
+ "fillrule_default": "nonzero",
112
109
  "colorcoded_default": "",
113
110
  "constantburn_default": True,
111
+ "fan_default": "off"
114
112
  }
115
113
 
116
114
  if os.path.exists(config_file):
@@ -156,14 +154,17 @@ def main() -> int:
156
154
  parser.add_argument('--splitfile', action='store_true', default=False, help='split gcode output of SVG path and image objects' )
157
155
  parser.add_argument('--pathcut', action='store_true', default=False, help='alway cut SVG path objects! (use laser power set with option --cuttingpower)' )
158
156
  parser.add_argument('--nofill', action='store_true', default=False, help='ignore SVG fill attribute' )
157
+ parser.add_argument('--fillrule', action = 'store', default=cfg["fillrule_default"], metavar="<default:\"" + str(cfg["fillrule_default"])+ "\">",
158
+ type = str, help = 'set fill rule to [nonzero|evenodd]')
159
159
  parser.add_argument('--xmaxtravel', default=cfg["xmaxtravel_default"], metavar="<default:" +str(cfg["xmaxtravel_default"])+ ">",
160
160
  type=int, help="machine x-axis lengh in mm")
161
161
  parser.add_argument('--ymaxtravel', default=cfg["ymaxtravel_default"], metavar="<default:" +str(cfg["ymaxtravel_default"])+ ">",
162
162
  type=int, help="machine y-axis lengh in mm")
163
- parser.add_argument( '--color_coded', action = 'store', default=cfg["colorcoded_default"], metavar="<default:\"" + str(cfg["colorcoded_default"])+ "\">",
164
- type = str, help = 'set action for path with specific stroke color "[color = [cut|engrave|ignore] *]*"'
165
- ', example: --color_coded "black = ignore purple = cut blue = engrave"' )
166
- parser.add_argument('--fan', action='store_true', default=False, help='set machine fan on' )
163
+ parser.add_argument('--color_coded', action = 'store', default=cfg["colorcoded_default"], metavar="<default:\"" + str(cfg["colorcoded_default"])+ "\">",
164
+ type = str, help = 'set action for path with specific stroke color "[[color|allothercolors] = [cut|engrave|ignore] *]*"'
165
+ ', example: --color_coded "black = ignore purple = cut blue = engrave allothercolors = ignore"' )
166
+ parser.add_argument('--fan', action = 'store', default=cfg["fan_default"], metavar="<default:\"" + str(cfg["fan_default"])+ "\">",
167
+ type = str, help = 'set fan [on|on_engrave|on_cut]')
167
168
  parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + __version__, help="show version number and exit")
168
169
 
169
170
  args = parser.parse_args()
@@ -173,25 +174,37 @@ def main() -> int:
173
174
  if args.pathcut:
174
175
  print("options --color_coded and --pathcut cannot be used at the same time, program abort")
175
176
  return 1
176
- # check argument validity (1)
177
177
 
178
- # category names
179
- category = ["cut", "engrave", "ignore"]
180
- # get css color names
181
- colors = str([*css_color.css_color_keywords])
182
- colors = re.sub("(,|\[|\]|\'| )", '', colors.replace(",", "|"))
178
+ # check color_coded argument validity (1)
183
179
 
184
- # make a color list
185
- colors = colors.split("|")
180
+ # do a full match to validate the syntax
181
+ cc = re.sub(",", '', args.color_coded)
182
+ fm = re.fullmatch("( *[^ ]* *= *(cut|engrave|ignore))+", cc)
183
+ if not fm:
184
+ print(f"syntax error in argument: '--color_coded {args.color_coded}', argument should be similar to: "
185
+ f"'--color_coded \"black = ignore purple = cut blue = engrave\"'")
186
+ return 1
187
+
188
+ cc = fm.group(0)
186
189
 
187
- # get all names from color_coded
188
- names_regex = "[a-zA-Z]+"
189
- match = re.findall(names_regex, args.color_coded)
190
- names = [i for i in match]
190
+ # check color_coded argument validity (2)
191
+ pathignore, pathcut, pathengrave = Compiler.color_coded(cc)
191
192
 
192
- for name in names:
193
- if not (name in colors or name in category):
194
- print(f"argument error: '--color_coded {args.color_coded}' has a name '{name}' that does not correspond to a css color or category (cut|engrave|ignore).")
193
+ # a path color should be in one set only
194
+ for i in pathignore:
195
+ if i in pathcut or i in pathengrave:
196
+ print(f"error in argument: '--color_coded \"{args.color_coded}\"' has a path color '{i}' set in multiple categories (cut|engrave|ignore).")
197
+ return 1
198
+ for i in pathcut:
199
+ if i in pathengrave:
200
+ print(f"error in argument: '--color_coded \"{args.color_coded}\"' has a path color '{i}' set in multiple categories (cut|engrave|ignore).")
201
+ return 1
202
+
203
+ # check validity of color argument, either "allothercolors" or a valid color value e.g. one of '#hex', 'rgb(', 'rgba(', 'hsl(' and 'hsla(' color schemes.
204
+ for i in pathignore + pathcut + pathengrave:
205
+ if not (i == "allothercolors" or css_color.parse_css_color(i, fallback = False, warning = False)):
206
+ print(f"error in argument: '--color_coded \"{args.color_coded}\"':")
207
+ print(f"- invalid color '{i}', color must be of scheme '#hex', 'rgb', 'rgba', 'hsl', 'hsla' or set to 'allothercolors'.")
195
208
  return 1
196
209
 
197
210
  if args.origin is not None and args.selfcenter:
@@ -199,12 +212,13 @@ def main() -> int:
199
212
  return 1
200
213
 
201
214
  return svg2gcode(args)
215
+
202
216
  except KeyboardInterrupt:
203
- print(f"svg2gcode aborted!")
217
+ print("svg2gcode aborted!")
218
+ return 1
204
219
  except Exception as error:
205
220
  print(error)
206
-
207
- return 1
221
+ return 1
208
222
 
209
223
  if __name__ == '__main__':
210
224
  sys.exit(main())
@@ -0,0 +1,26 @@
1
+ ## RUN test files.
2
+
3
+ The vector graphics *.svg* files in this directory are used by me to verify the validity of *svg2gcode*.
4
+ The outcome of the invocations below - the Gcode *.gc* files - should be similar for the same version of *svg2gcode*, in this case version 4.0.
5
+ Note that you can see the version of *svg2gcode* that produced the *.gc* file by looking at the header within this file.
6
+
7
+ ```
8
+ > svg2gcode --showimage kye_circle_paws_orig.svg kye_circle_paws_orig.gc
9
+ > svg2gcode --showimage kye_circle_paws_orig\ copy.svg kye_circle_paws_orig\ copy.gc
10
+ > svg2gcode letterandsigns.svg letterandsigns.gc
11
+ ```
12
+
13
+ After running the above you can check the results against the accompanied zip file: *gcode_output.zip*. <br>
14
+ The result should be similar apart from things like the date etc.
15
+ It is also possible to check the result visually by running *gcode2image* and in a web-browser using ncviwer.com.
16
+ ### In the first case run it so:
17
+ ```
18
+ > gcode2image --showimage --flip kye_circle_paws_orig.gc kye_circle_paws_orig.png
19
+ > gcode2image --showimage --flip kye_circle_paws_orig\ copy.gc kye_circle_paws_orig.png
20
+ > gcode2image --showimage --flip letterandsigns.gc letterandsigns.png
21
+ ```
22
+
23
+ ### In the second case, type *ncviewer.com* in your browser search bar and type *enter*.
24
+
25
+ You can now drop any Gcode file on the left code pane (window) and look at the result.
26
+ This view is very precise and you can zoom in to see the very fine details, like exact line spacing and joining of the end point and exact fill in of the objects.