--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bitmap_plot.py Sat Nov 07 13:30:53 2015 +0100 @@ -0,0 +1,147 @@ +#!/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() \ No newline at end of file