#!/usr/bin/env python3
# ---------------------------------------------------------------------------- #
## \file img3gcode.py
## \author Sebastien Beaugrand
## \sa http://beaugrand.chez.com/
## \copyright CeCILL 2.1 Free Software license
# ---------------------------------------------------------------------------- #
import sys
from PIL import Image
if len(sys.argv) <= 8:
print(
'Usage: {} <png> <width-in-mm> <gap-in-px> <margin-in-mm> <smin> <smax> <fmin> <fmax> [-d]'
.format(sys.argv[0]),
file=sys.stderr)
exit(1)
srcName = sys.argv[1]
WIDTH = float(sys.argv[2])
GAP = int(sys.argv[3])
MARGIN = int(sys.argv[4])
SMIN = int(sys.argv[5]) # Puissance du laser 15W en pourmille
SMAX = int(sys.argv[6])
FMIN = int(sys.argv[7]) # Vitesse de deplacement en mm/min
FMAX = int(sys.argv[8])
if len(sys.argv) > 9 and sys.argv[9] == '-d':
debug = True
else:
debug = False
# ---------------------------------------------------------------------------- #
## \fn line
# ---------------------------------------------------------------------------- #
def line(image, i, j, pixels):
global lastVal
global lastNum
global lastG0
global speed
try:
sat = image.getpixel((i, image.height - 1 - j))
except:
print('i={} j={}'.format(i, j), file=sys.stderr)
raise
if lastVal == sat:
lastNum += 1
else:
if debug and lastVal >= 0 and lastVal < 255:
print('{} v={}'.format(lastNum, lastVal), file=sys.stderr)
if lastVal < 255:
if lastG0 != '':
if speed > 0:
speed = 0
print('S0')
print(lastG0)
lastG0 = ''
s = SMAX - int(((SMAX - SMIN) * lastVal) / 255)
if speed != s:
speed = s
print('S{}'.format(speed))
if FMIN != FMAX:
f = FMIN + int(((FMAX - FMIN) * lastVal) / 255)
print('G1 X{:.2f} Y{:.2f} F{}'.format(
MARGIN + i * WIDTH / image.width,
MARGIN + j * HEIGHT / image.height, f))
else:
print('G1 X{:.2f} Y{:.2f}'.format(
MARGIN + i * WIDTH / image.width,
MARGIN + j * HEIGHT / image.height))
else:
lastG0 = str('G0 X{:.2f} Y{:.2f} F{}'.format(
MARGIN + i * WIDTH / image.width,
MARGIN + j * HEIGHT / image.height, FMAX))
lastNum = 1
lastVal = sat
pixels[i, image.height - 1 - j] = sat
# ---------------------------------------------------------------------------- #
## \fn convert
# ---------------------------------------------------------------------------- #
def convert(image):
global lastVal
width, height = image.size
print('width: {:4d} px => {:3d} mm'.format(width, int(WIDTH)),
file=sys.stderr)
print('height: {:4d} px => {:3d} mm'.format(height, int(HEIGHT)),
file=sys.stderr)
dst = Image.new("L", image.size, "white")
pixels = dst.load()
dir = 1
for x in range(int((width - 1) / GAP) * GAP, -1, -GAP):
lastVal = 255
if dir == 1:
i = x
for y in range(0, width - x):
line(image, i, y, pixels)
i += 1
else:
i -= 1
for y in range(y + GAP, -1, -1):
line(image, i, y, pixels)
i -= 1
dir = -dir
dir = 1
for y in range(GAP, int((height - 1) / GAP) * GAP, GAP):
lastVal = 255
if dir == 1:
j = y
for x in range(0, min(height - y, width)):
line(image, x, j, pixels)
j += 1
else:
j -= 1
for x in range(x - GAP, -1, -1):
line(image, x, j, pixels)
j -= 1
dir = -dir
return dst
# ---------------------------------------------------------------------------- #
# main
# ---------------------------------------------------------------------------- #
lastVal = 255
lastNum = 0
lastG0 = ''
speed = 0
# Portrait
src = Image.open(srcName)
if src.height < src.width:
src = src.transpose(method=Image.ROTATE_90)
HEIGHT = src.height * WIDTH / src.width
print('G21') # Programmation en mm
print('S0')
print('M3')
dst = convert(src)
print('M5')
print('G0 X0 Y0')
print('M2')
dst.show()