bitmap_plot.py

Sat, 23 Sep 2017 13:07:51 +0200

author
mdd
date
Sat, 23 Sep 2017 13:07:51 +0200
changeset 35
72c4cbf64211
parent 1
0c9798d91427
permissions
-rwxr-xr-x

Final bugfixes, SVG working like a charm now

#!/usr/bin/env python

ENGRAVE_SPEED = 20 * 60 # mm/min
TRAVEL_SPEED = 130 * 60
E_FACTOR = 0.1
INVERT_PALETTE = True

DPI = 300
GREY_THRESHOLD = 0
CHANGE_DIRECTION = True


# DO NOT CHANGE WORLD's RULES!
INCH = 25.4 # mm
MM_PIXEL = round(INCH / DPI, 4)
STEPS_PIXEL = MM_PIXEL * 80 # mine is 80 steps/mm on XY
print "Resolution: %f mm per pixel" % MM_PIXEL
print "Steps per pixel (needs to be > 5, otherwise marlin joins lines): %f" % STEPS_PIXEL

from PIL import Image
import sys

def pixel_to_bit(pixel, threshold=128):
    """Convert the pixel value to a bit."""
    # some really weird stuff here ;-P

    # RGB to greyscale
    #print pixel
    #print type(pixel)
    if isinstance(pixel, tuple):
        #rgb
        pixel = pixel[0]*0.2989 + pixel[1]*0.5870 + pixel[2]*0.1140
        threshold = 128
        if pixel > threshold:
            return 1
        else:
            return 0


    # color palette
    if (pixel > 0):
        return 1
    else:
        return 0

#
# Open the image file and get the basic information about it.
#
try:
    im = Image.open(sys.argv[1])
except:
    print "Unable to open %s" % sys.argv[1]
    exit(-1)

print "format: %s   mode: %s   palette: %s" % (im.format,im.mode,im.palette)
width,height = im.size
print "The image is %d x %d" % im.size

pix = im.load()


fo = open(sys.argv[1] + ".g", "w")
#fo.write("G10 P1 X-30.0 Y1.5 Z0.0 R0 S0 ; Laser tool offset\n")
#fo.write("M218 T1 X.30.0 Y1.5 ; Laser tool offset\")
#fo.write("G28 X Y ; Home position\n")
# G90 = absolute positioning, G91 = relative
#fo.write("M83 ; Set extruder (laser) to relative mode\n")
fo.write("""
; Filename: %s
; GCode generated by bitplotter one-night-quick-hack script (marlin code flavour)

G21 ; Metric
; We assume Z is in focus height and laser head is focus at bottom left of image!
G92 X0 Y0 E0; set zero position - new origin
G90 ; absolute positioning
M82 ; Set extruder (laser) to absolute positioning
M201 X1000 Y1000 E500 ; Set acceleration
M203 X1000 Y1000 Z4 E10 ; Set max feedrate
M209 S0 ; disable firmware retraction, we dont want to burn holes...
M302 ; Allow cold extrudes - doesnt matter because we hack the extruder physically off with the M571 E mod
M571 S1 E1 ; Activate Laser output on extrusion, but block real motor movement!
G0 X0 Y0 F%d ; Set moving speed TRAVEL_SPEED
G1 X0 Y0 F%d ; Set linear engraving speed ENGRAVE_SPEED

""" % (sys.argv[1], TRAVEL_SPEED, ENGRAVE_SPEED) )

fo.write(";Start engraving the raster image: %dx%d points @ %d DPI = %.0fx%.0f mm" % (
    im.size[0], im.size[1], DPI, im.size[0]*MM_PIXEL, im.size[1]*MM_PIXEL) )

INVERT_Y = MM_PIXEL * (im.size[1] -1) * (-1)

DIR = 1
for X in range(im.size[0]):
    fo.write("; X=%d printing row: direction %i\n" % (X, DIR))
    fo.write("G92 E0\n")
    E = 0
    last_bit = 1 # we engrave on black pixel = 0
    START_Y = 0
    if DIR > 0:
        range_start = 0
        range_stop = im.size[1]
    else:
        range_start = im.size[1] -1
        range_stop = -1

    for Y in range(range_start, range_stop, DIR):
        YMM = abs((Y * MM_PIXEL) + INVERT_Y)
        XMM = X * MM_PIXEL
        #print "X %d Y %d" % (X, Y)
        bit = pixel_to_bit(pix[X, Y], GREY_THRESHOLD)
        if last_bit == bit:
            if bit == 1:
                # nothing to do,
                continue
            else:
                # are we at the end of Y range?
                #print Y
                if (Y == (im.size[1] - 1)) or (Y == 0):
                    # draw line
                    if DIR > 0:
                        E = E + MM_PIXEL * (Y - START_Y)
                    else:
                        E = E + MM_PIXEL * (START_Y - Y)
                    fo.write("G1 X%.4f Y%.4f E%.4f F%d\n" % (XMM, YMM, E * E_FACTOR, ENGRAVE_SPEED))
        else:
            # bit value has changed!
            if bit == 0:
                # jump to start of line to write
                START_Y = Y
                fo.write("G0 X%.4f Y%.4f F%d\n" % (XMM, YMM, TRAVEL_SPEED))
            else:
                # end of line to write
                if DIR > 0:
                    E = E + MM_PIXEL * (Y - START_Y)
                else:
                    E = E + MM_PIXEL * (START_Y - Y)
                fo.write("G1 X%.4f Y%.4f E%.4f F%d\n" % (XMM, YMM, E * E_FACTOR, ENGRAVE_SPEED))
        last_bit = bit
    if CHANGE_DIRECTION:
        DIR = DIR * (-1) # change y direction on every X


fo.write("M571 S0 E0\n")
fo.write("M501 ; undo all settings made\n")
#fo.write("G28 X0 Y0 ; Home position\n")

fo.close()

mercurial