img2gcode 1.0.0__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.
- img2gcode-1.0.0/LICENSE +21 -0
- img2gcode-1.0.0/MANIFEST.in +2 -0
- img2gcode-1.0.0/PKG-INFO +36 -0
- img2gcode-1.0.0/README.md +17 -0
- img2gcode-1.0.0/img2gcode/__init__.py +3 -0
- img2gcode-1.0.0/img2gcode/__main__.py +304 -0
- img2gcode-1.0.0/img2gcode.egg-info/PKG-INFO +36 -0
- img2gcode-1.0.0/img2gcode.egg-info/SOURCES.txt +13 -0
- img2gcode-1.0.0/img2gcode.egg-info/dependency_links.txt +1 -0
- img2gcode-1.0.0/img2gcode.egg-info/entry_points.txt +2 -0
- img2gcode-1.0.0/img2gcode.egg-info/requires.txt +5 -0
- img2gcode-1.0.0/img2gcode.egg-info/top_level.txt +1 -0
- img2gcode-1.0.0/requirements.txt +4 -0
- img2gcode-1.0.0/setup.cfg +4 -0
- img2gcode-1.0.0/setup.py +40 -0
img2gcode-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CBH
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
img2gcode-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: img2gcode
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Convert image to gcode for laser printing
|
|
5
|
+
Home-page: https://github.com/0CBH0/img2gcode
|
|
6
|
+
Author: 0CBH0
|
|
7
|
+
Author-email: maodatou88@163.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Platform: UNKNOWN
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python
|
|
12
|
+
Classifier: Programming Language :: Python :: 2
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Requires-Python: >=3.6
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
|
|
18
|
+
# img2gcode
|
|
19
|
+
|
|
20
|
+
Convert image to gcode for laser printing.
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
~~~
|
|
24
|
+
python3 -m pip install --upgrade img2gcode
|
|
25
|
+
~~~
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
~~~
|
|
29
|
+
# Basic usage
|
|
30
|
+
img2gcode [options] -i <image_file>
|
|
31
|
+
|
|
32
|
+
# For more information
|
|
33
|
+
img2gcode -h
|
|
34
|
+
~~~
|
|
35
|
+
|
|
36
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# img2gcode
|
|
2
|
+
|
|
3
|
+
Convert image to gcode for laser printing.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
~~~
|
|
7
|
+
python3 -m pip install --upgrade img2gcode
|
|
8
|
+
~~~
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
~~~
|
|
12
|
+
# Basic usage
|
|
13
|
+
img2gcode [options] -i <image_file>
|
|
14
|
+
|
|
15
|
+
# For more information
|
|
16
|
+
img2gcode -h
|
|
17
|
+
~~~
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import os, sys, getopt
|
|
2
|
+
from PIL import Image
|
|
3
|
+
from collections import defaultdict
|
|
4
|
+
|
|
5
|
+
from img2gcode import __version__
|
|
6
|
+
|
|
7
|
+
class ArgumentList:
|
|
8
|
+
def __init__(self):
|
|
9
|
+
self.src = ""
|
|
10
|
+
self.dst = ""
|
|
11
|
+
self.mx = 1
|
|
12
|
+
self.my = 1
|
|
13
|
+
self.sx = 20000
|
|
14
|
+
self.sy = 20000
|
|
15
|
+
self.p = 30
|
|
16
|
+
self.t = 1
|
|
17
|
+
self.pi = 0
|
|
18
|
+
self.po = 0
|
|
19
|
+
self.ps = 0
|
|
20
|
+
self.pe = 1
|
|
21
|
+
self.ll = 10
|
|
22
|
+
self.ind = 4
|
|
23
|
+
self.link = 1
|
|
24
|
+
self.gapx = 0
|
|
25
|
+
self.gapy = 0
|
|
26
|
+
self.fill = 3
|
|
27
|
+
self.flip = 0
|
|
28
|
+
self.zz = 0
|
|
29
|
+
|
|
30
|
+
def path_fix(inp, dir):
|
|
31
|
+
terms = inp.split("\n")
|
|
32
|
+
res_fix = []
|
|
33
|
+
for i in range(len(terms)):
|
|
34
|
+
if i < len(terms) - 1 and terms[i][:3] == "G1 " and terms[i + 1][:3] == "G1 " and len(terms[i].split(" ")) == len(terms[i + 1].split(" ")):
|
|
35
|
+
merge = True
|
|
36
|
+
ts = {}
|
|
37
|
+
for t in terms[i].split(" "):
|
|
38
|
+
ts[t[0]] = t[1:]
|
|
39
|
+
for t in terms[i + 1].split(" "):
|
|
40
|
+
if t[0] not in ts or t[1:] != ts[t[0]]:
|
|
41
|
+
#if t[0] not in ts or (t[1:] != ts[t[0]] and t[0] == dir):
|
|
42
|
+
merge = False
|
|
43
|
+
break
|
|
44
|
+
if merge:
|
|
45
|
+
continue
|
|
46
|
+
res_fix.append(terms[i])
|
|
47
|
+
return "\n".join(res_fix)
|
|
48
|
+
|
|
49
|
+
def handle_line(img, mx, my, sx, sy, p, pi, po, t, ps, pe, ll, ind, link, gapx, gapy, fill, flip, zz):
|
|
50
|
+
pause = f"G4 P0.01\n"
|
|
51
|
+
# print vline
|
|
52
|
+
SX = "Y" if flip else "X"
|
|
53
|
+
SY = "X" if flip else "Y"
|
|
54
|
+
gcs = defaultdict(lambda: defaultdict(list))
|
|
55
|
+
mskx = [[0 for y in range(img.size[1])] for x in range(img.size[0])]
|
|
56
|
+
line = [0 for _ in range(img.size[1])]
|
|
57
|
+
for x in range(img.size[0]):
|
|
58
|
+
pt = x
|
|
59
|
+
for y in range(img.size[1]):
|
|
60
|
+
line[y] = 1 if img.getpixel((x, y)) < 128 else 0
|
|
61
|
+
ps = 0
|
|
62
|
+
for i in range(1, len(line)+1):
|
|
63
|
+
if i == len(line) or line[i] != line[ps]:
|
|
64
|
+
pe = i - 1
|
|
65
|
+
if line[ps] == 1 and pe - ps > ll:
|
|
66
|
+
mskx[x][ps:pe + 1] = [1 for _ in range(pe - ps + 1)]
|
|
67
|
+
if pe - ps - gapy*2 < gapy * 4:
|
|
68
|
+
print("???")
|
|
69
|
+
gtt = [f"G1 {SX}{round(pt*mx, 3)} {SY}{round((ps+gapy)*my, 3)} S0\n"]
|
|
70
|
+
gtt.append(f"G1 {SY}{round((pe-ind)*my, 3)} S{p}\n")
|
|
71
|
+
gtt.append(f"G1 {SX}{round(pt*mx, 3)} {SY}{round((pe-gapy)*my, 3)} S0\n")
|
|
72
|
+
gtt.append(f"G1 {SY}{round((ps+ind)*my, 3)} S{p}\n")
|
|
73
|
+
gcs[pt][ps] = ["".join([gtt[0], pause, gtt[1], gtt[2]]), "".join([gtt[2], pause, gtt[3], gtt[0]])]
|
|
74
|
+
ps = i
|
|
75
|
+
# fill vline
|
|
76
|
+
for x in range(1, img.size[0]):
|
|
77
|
+
for y in range(img.size[1]):
|
|
78
|
+
line[y] = 1 if mskx[x - 1][y] == 1 and mskx[x][y] == 1 else 0
|
|
79
|
+
for k in range(1, fill):
|
|
80
|
+
pt = x - 1 + k / fill
|
|
81
|
+
ps = 0
|
|
82
|
+
for i in range(1, len(line)+1):
|
|
83
|
+
if i == len(line) or line[i] != line[ps]:
|
|
84
|
+
pe = i - 1
|
|
85
|
+
if line[ps] == 1:
|
|
86
|
+
if pe - ps - gapy*2 < gapy * 4:
|
|
87
|
+
print("???")
|
|
88
|
+
gtt = [f"G1 {SX}{round(pt*mx, 3)} {SY}{round((ps+gapy+zz*(k%2)/2)*my, 3)} S0\n"]
|
|
89
|
+
gtt.append(f"G1 {SY}{round((pe-ind)*my, 3)} S{p}\n")
|
|
90
|
+
gtt.append(f"G1 {SX}{round(pt*mx, 3)} {SY}{round((pe-gapy-zz*(k%2)/2)*my, 3)} S0\n")
|
|
91
|
+
gtt.append(f"G1 {SY}{round((ps+ind)*my, 3)} S{p}\n")
|
|
92
|
+
gcs[pt][ps] = ["".join([gtt[0], pause, gtt[1], gtt[2]]), "".join([gtt[2], pause, gtt[3], gtt[0]])]
|
|
93
|
+
ps = i
|
|
94
|
+
gc_x = ""
|
|
95
|
+
for ki, vi in sorted(gcs.items(), key=lambda x: x[0]):
|
|
96
|
+
for kj, vj in sorted(vi.items(), key=lambda x: x[0]):
|
|
97
|
+
gc_x += vj[0]
|
|
98
|
+
for kj, vj in sorted(vi.items(), key=lambda x: x[0], reverse=True):
|
|
99
|
+
gc_x += vj[1]
|
|
100
|
+
gc_x = path_fix(gc_x, "X")
|
|
101
|
+
# print hline
|
|
102
|
+
links = defaultdict(list)
|
|
103
|
+
linke = defaultdict(list)
|
|
104
|
+
gcs = defaultdict(lambda: defaultdict(list))
|
|
105
|
+
msky = [[0 for x in range(img.size[0])] for y in range(img.size[1])]
|
|
106
|
+
line = [0 for _ in range(img.size[0])]
|
|
107
|
+
for y in range(img.size[1]):
|
|
108
|
+
pt = y
|
|
109
|
+
for x in range(img.size[0]):
|
|
110
|
+
line[x] = 1 if img.getpixel((x, y)) < 128 else 0
|
|
111
|
+
ps = 0
|
|
112
|
+
for i in range(1, len(line)+1):
|
|
113
|
+
if i == len(line) or line[i] != line[ps]:
|
|
114
|
+
pe = i - 1
|
|
115
|
+
ms = [mskx[k][y] for k in range(ps, pe + 1)]
|
|
116
|
+
if line[ps] == 1 and pe - ps + 1 > ms.count(1):
|
|
117
|
+
links[ps].append(pt)
|
|
118
|
+
linke[pe].append(pt)
|
|
119
|
+
msky[y][ps:pe + 1] = [1 for _ in range(pe - ps + 1)]
|
|
120
|
+
gtt = [f"G1 {SX}{round((ps+gapx)*mx, 3)} {SY}{round(pt*my, 3)} S0\n"]#+1
|
|
121
|
+
gtt.append(f"G1 {SX}{round((pe-ind)*mx, 3)} S{p}\n")
|
|
122
|
+
gtt.append(f"G1 {SX}{round((pe-gapx)*mx, 3)} {SY}{round(pt*my, 3)} S0\n")
|
|
123
|
+
gtt.append(f"G1 {SX}{round((ps+ind)*mx, 3)} S{p}\n")
|
|
124
|
+
gcs[pt][ps] = ["".join([gtt[0], pause, gtt[1], gtt[2]]), "".join([gtt[2], pause, gtt[3], gtt[0]])]
|
|
125
|
+
ps = i
|
|
126
|
+
# fill hline
|
|
127
|
+
for y in range(1, img.size[1]):
|
|
128
|
+
for x in range(img.size[0]):
|
|
129
|
+
line[x] = 1 if msky[y - 1][x] == 1 and msky[y][x] == 1 else 0
|
|
130
|
+
for k in range(1, fill):
|
|
131
|
+
pt = y - 1 + k / fill
|
|
132
|
+
ps = 0
|
|
133
|
+
for i in range(1, len(line)+1):
|
|
134
|
+
if i == len(line) or line[i] != line[ps]:
|
|
135
|
+
pe = i - 1
|
|
136
|
+
if line[ps] == 1:
|
|
137
|
+
gtt = [f"G1 {SX}{round((ps+gapx+zz*(k%2)/2)*mx, 3)} {SY}{round(pt*my, 3)} S0\n"]#+1
|
|
138
|
+
gtt.append(f"G1 {SX}{round((pe-ind)*mx, 3)} S{p}\n")
|
|
139
|
+
gtt.append(f"G1 {SX}{round((pe-gapx-zz*(k%2)/2)*mx, 3)} {SY}{round(pt*my, 3)} S0\n")
|
|
140
|
+
gtt.append(f"G1 {SX}{round((ps+ind)*mx, 3)} S{p}\n")
|
|
141
|
+
gcs[pt][ps] = ["".join([gtt[0], pause, gtt[1], gtt[2]]), "".join([gtt[2], pause, gtt[3], gtt[0]])]
|
|
142
|
+
ps = i
|
|
143
|
+
gc_y = ""
|
|
144
|
+
for ki, vi in sorted(gcs.items(), key=lambda x: x[0]):
|
|
145
|
+
for kj, vj in sorted(vi.items(), key=lambda x: x[0]):
|
|
146
|
+
gc_y += vj[0]
|
|
147
|
+
for kj, vj in sorted(vi.items(), key=lambda x: x[0], reverse=True):
|
|
148
|
+
gc_y += vj[1]
|
|
149
|
+
gc_y = path_fix(gc_y, "Y")
|
|
150
|
+
# fill links
|
|
151
|
+
gcs = defaultdict(lambda: defaultdict(list))
|
|
152
|
+
for hx, hys in sorted(links.items(), key=lambda x: x[0]):
|
|
153
|
+
lines = []
|
|
154
|
+
s = 0
|
|
155
|
+
for i in range(1, len(hys)):
|
|
156
|
+
if hys[i] - hys[i - 1] > 1:
|
|
157
|
+
lines.append([hys[s], hys[i - 1]])
|
|
158
|
+
s = i
|
|
159
|
+
lines.append([hys[s], hys[-1]])
|
|
160
|
+
for ps, pe in lines:
|
|
161
|
+
for k in range(1, fill * 3):
|
|
162
|
+
pt = hx + k / fill
|
|
163
|
+
gtt = ["", ""]
|
|
164
|
+
if img.getpixel((hx, min(pe + 1, img.size[1] - 1))) < 128 and img.getpixel((min(hx + 1, img.size[0]), min(pe + 1, img.size[1] - 1))) >= 128:
|
|
165
|
+
gtt[0] = f"G1 {SX}{round(pt*mx, 3)} {SY}{round((ps+gapy)*my, 3)} S0\n" + pause
|
|
166
|
+
gtt[0] += f"G1 {SY}{round((pe+link)*my, 3)} S{p}\n"
|
|
167
|
+
gtt[0] += f"G1 {SX}{round(pt*mx, 3)} {SY}{round((pe+link*2)*my, 3)} S0\n"
|
|
168
|
+
if img.getpixel((hx, max(ps - 1, 0))) < 128 and img.getpixel((min(hx + 1, img.size[0] - 1), max(ps - 1, 0))) >= 128:
|
|
169
|
+
gtt[1] = f"G1 {SX}{round(pt*mx, 3)} {SY}{round((pe-gapy)*my, 3)} S0\n" + pause
|
|
170
|
+
gtt[1] += f"G1 {SY}{round((ps-link)*my, 3)} S{p}\n"
|
|
171
|
+
gtt[1] += f"G1 {SX}{round(pt*mx, 3)} {SY}{round((ps-link*2)*my, 3)} S0\n"
|
|
172
|
+
if gtt != ["", ""]:
|
|
173
|
+
gcs[pt][ps] = gtt
|
|
174
|
+
# fill linke
|
|
175
|
+
for hx, hys in sorted(linke.items(), key=lambda x: x[0]):
|
|
176
|
+
lines = []
|
|
177
|
+
s = 0
|
|
178
|
+
for i in range(1, len(hys)):
|
|
179
|
+
if hys[i] - hys[i - 1] > 1:
|
|
180
|
+
lines.append([hys[s], hys[i - 1]])
|
|
181
|
+
s = i
|
|
182
|
+
lines.append([hys[s], hys[-1]])
|
|
183
|
+
for ps, pe in lines:
|
|
184
|
+
for k in range(1, fill * 2):
|
|
185
|
+
pt = hx - k / fill
|
|
186
|
+
gtt = ["", ""]
|
|
187
|
+
if img.getpixel((hx, min(pe + 1, img.size[1] - 1))) < 128 and img.getpixel((max(hx - 1, 0), min(pe + 1, img.size[1] - 1))) >= 128:
|
|
188
|
+
gtt[0] = f"G1 {SX}{round(pt*mx, 3)} {SY}{round((ps+gapy)*my, 3)} S0\n" + pause
|
|
189
|
+
gtt[0] += f"G1 {SY}{round((pe+link)*my, 3)} S{p}\n"
|
|
190
|
+
gtt[0] += f"G1 {SX}{round(pt*mx, 3)} {SY}{round((pe+link*2)*my, 3)} S0\n"
|
|
191
|
+
if img.getpixel((hx, max(ps - 1, 0))) < 128 and img.getpixel((max(hx - 1, 0), max(ps - 1, 0))) >= 128:
|
|
192
|
+
gtt[1] = f"G1 {SX}{round(pt*mx, 3)} {SY}{round((pe-gapy)*my, 3)} S0\n" + pause
|
|
193
|
+
gtt[1] += f"G1 {SY}{round((ps-link)*my, 3)} S{p}\n"
|
|
194
|
+
gtt[1] += f"G1 {SX}{round(pt*mx, 3)} {SY}{round((ps-link*2)*my, 3)} S0\n"
|
|
195
|
+
if gtt != ["", ""]:
|
|
196
|
+
gcs[pt][ps] = gtt
|
|
197
|
+
gc_l = ""
|
|
198
|
+
for ki, vi in sorted(gcs.items(), key=lambda x: x[0]):
|
|
199
|
+
for kj, vj in sorted(vi.items(), key=lambda x: x[0]):
|
|
200
|
+
if vj[0] != "":
|
|
201
|
+
gc_l += vj[0]
|
|
202
|
+
for kj, vj in sorted(vi.items(), key=lambda x: x[0], reverse=True):
|
|
203
|
+
if vj[1] != "":
|
|
204
|
+
gc_l += vj[1]
|
|
205
|
+
gc_l = path_fix(gc_l, "X")
|
|
206
|
+
res = "G0\nG17\nG40\nG21\nG54\nG90\nM3\nM8\nM3\nM8\nM9\nG90\n"
|
|
207
|
+
res += f"G0 {SX}0 {SY}0 S0 F0\nG1 {SX}0 {SY}0 S0 F{sx}\n"
|
|
208
|
+
res += "".join([gc_y for _ in range(t)])
|
|
209
|
+
res += f"G0 {SX}0 {SY}0 S0 F0\nG1 {SX}0 {SY}0 S0 F{sy}\n"
|
|
210
|
+
res += "".join([gc_x for _ in range(t)])
|
|
211
|
+
res += f"G0 {SX}0 {SY}0 S0 F0\nG1 {SX}0 {SY}0 S0 F{sy}\n"
|
|
212
|
+
res += "".join([gc_l for _ in range(t)])
|
|
213
|
+
res += f"G0 {SX}0 {SY}0 S0\nM5\nG90\n"
|
|
214
|
+
return res
|
|
215
|
+
|
|
216
|
+
def img2gcode(args):
|
|
217
|
+
img = Image.open(args.src).convert("L")
|
|
218
|
+
res = handle_line(img, args.mx, args.my, args.sx, args.sy, args.p, args.pi, args.po, args.t, args.ps, args.pe, args.ll, args.ind, args.link, args.gapx, args.gapy, args.fill, args.flip, args.zz)
|
|
219
|
+
gc = open(args.dst, "w")
|
|
220
|
+
r = gc.write(res)
|
|
221
|
+
gc.close()
|
|
222
|
+
img.close()
|
|
223
|
+
|
|
224
|
+
def main():
|
|
225
|
+
opts, terms = getopt.getopt(sys.argv[1:], "hi:o:n:k:x:y:c:d:p:t:a:b:s:e:l:g:j:m:fz",
|
|
226
|
+
["help", "input=", "output=", "indent=", "link=", "step_x=", "step_y=", "speed_x=", "speed_y=", "power=", "times=", "pause_in=", "pause_out=", "start=", "end=", "limit=", "gap_x=", "gap_y=", "fill=", "flip", "zigzag"])
|
|
227
|
+
args = ArgumentList()
|
|
228
|
+
help_flag = False
|
|
229
|
+
help_info = "Usage:\nimg2gcode [options] -i <image>\nArguments:\n"\
|
|
230
|
+
+"--help, -h\t\tShow this help information\n"\
|
|
231
|
+
+"--input, -i\t\tThe path of source image file\n"\
|
|
232
|
+
+"--output, -o\t\tThe path of generated gcode file (default: same as input)\n"\
|
|
233
|
+
+"--indent, -n\t\tThe end indentation of lines (pixel, default: 4)\n"\
|
|
234
|
+
+"--link, -k\t\tThe length of links (pixel, default: 1)\n"\
|
|
235
|
+
+"--step_x, -x\t\tStep on x-axis (step/pixel, default: 1)\n"\
|
|
236
|
+
+"--step_y, -y\t\tStep on y-axis (step/pixel, default: 1)\n"\
|
|
237
|
+
+"--speed_x, -c\t\tSpeed on x-axis (1-20000, default: 20000)\n"\
|
|
238
|
+
+"--speed_y, -d\t\tSpeed on y-axis (1-20000, default: 20000)\n"\
|
|
239
|
+
+"--power, -p\t\tPower of laser (0-1000, default: 30)\n"\
|
|
240
|
+
+"--times, -t\t\tNumber of exposures (default: 1)\n"\
|
|
241
|
+
+"--pause_in, -a\t\tPause time before laser on (sec, default: 0)\n"\
|
|
242
|
+
+"--pause_out, -b\t\tPause time after laser off (sec, default: 0)\n"\
|
|
243
|
+
+"--start, -s\t\tStart y position for test (default: 0)\n"\
|
|
244
|
+
+"--end, -e\t\tEnd y position for test (default: 1)\n"\
|
|
245
|
+
+"--limit, -l\t\tThe min length of line to draw (default: 10)\n"\
|
|
246
|
+
+"--gap_x, -g\t\tThe gap for matching x-axis (pixel, default: 0)\n"\
|
|
247
|
+
+"--gap_y, -j\t\tThe gap for matching y-axis (pixel, default: 0)\n"\
|
|
248
|
+
+"--fill, -m\t\tThe padding times for blocks (default: 3)\n"\
|
|
249
|
+
+"--flip, -f\t\tFlip image\n"\
|
|
250
|
+
+"--zigzag, -z\t\tUsing zigzag padding\n"
|
|
251
|
+
for opt, arg in opts:
|
|
252
|
+
if opt in ("--help", "-h"):
|
|
253
|
+
help_flag = True
|
|
254
|
+
elif opt in ("--input", "-i"):
|
|
255
|
+
args.src = arg
|
|
256
|
+
elif opt in ("--output", "-o"):
|
|
257
|
+
args.dst = arg
|
|
258
|
+
elif opt in ("--indent", "-n"):
|
|
259
|
+
args.ind = max(round(float(arg), 3), 0)
|
|
260
|
+
elif opt in ("--link", "-k"):
|
|
261
|
+
args.link = max(round(float(arg), 3), 0)
|
|
262
|
+
elif opt in ("--step_x", "-x"):
|
|
263
|
+
args.mx = max(float(arg), 0)
|
|
264
|
+
elif opt in ("--step_y", "-y"):
|
|
265
|
+
args.my = max(float(arg), 0)
|
|
266
|
+
elif opt in ("--speed_x", "-c"):
|
|
267
|
+
args.sx = max(int(arg), 1)
|
|
268
|
+
elif opt in ("--speed_y", "-d"):
|
|
269
|
+
args.sy = max(int(arg), 1)
|
|
270
|
+
elif opt in ("--power", "-p"):
|
|
271
|
+
args.p = max(int(arg), 0)
|
|
272
|
+
elif opt in ("--times", "-t"):
|
|
273
|
+
args.t = max(int(arg), 1)
|
|
274
|
+
elif opt in ("--pause_in", "-a"):
|
|
275
|
+
args.pi = max(round(float(arg), 3), 0)
|
|
276
|
+
elif opt in ("--pause_out", "-b"):
|
|
277
|
+
args.po = max(round(float(arg), 3), 0)
|
|
278
|
+
elif opt in ("--start", "-s"):
|
|
279
|
+
args.ps = min(max(round(float(arg), 3), 0), 1)
|
|
280
|
+
elif opt in ("--end", "-e"):
|
|
281
|
+
args.pe = min(max(round(float(arg), 3), 0), 1)
|
|
282
|
+
elif opt in ("--limit", "-l"):
|
|
283
|
+
args.ll = max(0, int(arg))
|
|
284
|
+
elif opt in ("--gap_x", "-g"):
|
|
285
|
+
args.gapx = round(float(arg), 3)
|
|
286
|
+
elif opt in ("--gap_y", "-j"):
|
|
287
|
+
args.gapy = round(float(arg),3)
|
|
288
|
+
elif opt in ("--fill", "-m"):
|
|
289
|
+
args.fill = max(0, int(arg))
|
|
290
|
+
elif opt in ("--flip", "-f"):
|
|
291
|
+
args.flip = 1
|
|
292
|
+
elif opt in ("--zigzag", "-z"):
|
|
293
|
+
args.zz = 1
|
|
294
|
+
args.dst = os.path.splitext(args.src)[0] + ".gcode" if args.dst == "" else args.dst
|
|
295
|
+
print("img2gcode - Version: "+__version__)
|
|
296
|
+
if help_flag or args.src == "":
|
|
297
|
+
print(help_info)
|
|
298
|
+
sys.exit()
|
|
299
|
+
print(f"Converting {args.src} ...")
|
|
300
|
+
img2gcode(args)
|
|
301
|
+
print(f"Done!")
|
|
302
|
+
|
|
303
|
+
if __name__ == "__main__":
|
|
304
|
+
main()
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: img2gcode
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Convert image to gcode for laser printing
|
|
5
|
+
Home-page: https://github.com/0CBH0/img2gcode
|
|
6
|
+
Author: 0CBH0
|
|
7
|
+
Author-email: maodatou88@163.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Platform: UNKNOWN
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python
|
|
12
|
+
Classifier: Programming Language :: Python :: 2
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Requires-Python: >=3.6
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
|
|
18
|
+
# img2gcode
|
|
19
|
+
|
|
20
|
+
Convert image to gcode for laser printing.
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
~~~
|
|
24
|
+
python3 -m pip install --upgrade img2gcode
|
|
25
|
+
~~~
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
~~~
|
|
29
|
+
# Basic usage
|
|
30
|
+
img2gcode [options] -i <image_file>
|
|
31
|
+
|
|
32
|
+
# For more information
|
|
33
|
+
img2gcode -h
|
|
34
|
+
~~~
|
|
35
|
+
|
|
36
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
requirements.txt
|
|
5
|
+
setup.py
|
|
6
|
+
img2gcode/__init__.py
|
|
7
|
+
img2gcode/__main__.py
|
|
8
|
+
img2gcode.egg-info/PKG-INFO
|
|
9
|
+
img2gcode.egg-info/SOURCES.txt
|
|
10
|
+
img2gcode.egg-info/dependency_links.txt
|
|
11
|
+
img2gcode.egg-info/entry_points.txt
|
|
12
|
+
img2gcode.egg-info/requires.txt
|
|
13
|
+
img2gcode.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
img2gcode
|
img2gcode-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'''Setup script for img2gcode'''
|
|
2
|
+
|
|
3
|
+
from __future__ import absolute_import
|
|
4
|
+
|
|
5
|
+
import os.path
|
|
6
|
+
from setuptools import setup
|
|
7
|
+
from img2gcode import __version__
|
|
8
|
+
|
|
9
|
+
# The directory containing this file
|
|
10
|
+
HERE = os.path.abspath(os.path.dirname(__file__))
|
|
11
|
+
|
|
12
|
+
# The text of the README file
|
|
13
|
+
with open(os.path.join(HERE, 'README.md')) as fid:
|
|
14
|
+
README = fid.read()
|
|
15
|
+
|
|
16
|
+
# This call to setup() does all the work
|
|
17
|
+
setup(
|
|
18
|
+
name='img2gcode',
|
|
19
|
+
version=__version__,
|
|
20
|
+
description='Convert image to gcode for laser printing',
|
|
21
|
+
long_description=README,
|
|
22
|
+
long_description_content_type='text/markdown',
|
|
23
|
+
url='https://github.com/0CBH0/img2gcode',
|
|
24
|
+
author='0CBH0',
|
|
25
|
+
author_email='maodatou88@163.com',
|
|
26
|
+
license='MIT',
|
|
27
|
+
classifiers=[
|
|
28
|
+
'License :: OSI Approved :: MIT License',
|
|
29
|
+
'Programming Language :: Python',
|
|
30
|
+
'Programming Language :: Python :: 2',
|
|
31
|
+
'Programming Language :: Python :: 3',
|
|
32
|
+
],
|
|
33
|
+
packages=['img2gcode'],
|
|
34
|
+
include_package_data=True,
|
|
35
|
+
install_requires=[
|
|
36
|
+
'pysam', 'pandas', 'numpy', 'plotnine', 'Pillow'
|
|
37
|
+
],
|
|
38
|
+
python_requires='>=3.6',
|
|
39
|
+
entry_points={'console_scripts': ['img2gcode=img2gcode.__main__:main']},
|
|
40
|
+
)
|