How Makelangelo turns images to gcode
Lots of people are suggesting great ideas for new image filters on the Makelangelo. I wish I had time to do them all myself. As a compromise I’d like to make it so easy to write new filters that anyone can do it. I’m going to walk you through the simplest image filter and show you how it works.
Here is the image I converted to gcode:
Here is the result as it looks in the Makelangelo program after I converted it with the “scanline” style:
In general the process is:
- load a picture. This has been done for you before the filter starts.
- move around the picture and interpret what you see as you go. This is where you do your magic.
- write down what you interpret as instructions for the robot. This has been made simple.
Let’s take a look at a practical example, based on the converted image above. In the github project you’ll find several Filter_* classes. The simplest Filter has only one method called Convert.
[code]public void Convert(BufferedImage img) throws IOException {
// The picture might be in color. Smash it to 255 shades of grey.
Filter_BlackAndWhite bw = new Filter_BlackAndWhite(255);
img = bw.Process(img); //"process" is for filters that change the original image. "convert" should create a few file without modifying the original.
// Open the destination file
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(dest),"UTF-8");
// Set up the conversion from image space to paper space, select the current tool, etc.
ImageStart(img,out);
// "please change to tool X and press any key to continue"
tool.WriteChangeTo(out);
// Make sure the pen is up for the first move
liftPen(out);
// figure out how many lines we’re going to have on this image.
int steps = (int)Math.ceil(tool.GetDiameter()/(1.75*scale));
if(steps<1) steps=1;
// these next three might not be strictly necessary. Call me paranoid.
lastup=true;
previous_x=0;
previous_y=0;
// Color values are from 0…255 inclusive. 255 is white, 0 is black.
// Lift the pen any time the color value is > level (128 or more).
double level=255.0/2.0;
// from top to bottom of the image…
int x,y,z,i=0;
for(y=0;y<image_height;y+=steps) {
++i;
if((i%2)==0) {
// every even line move left to right
//MoveTo(file,x,y,pen up?)
MoveTo(out,(float)0,(float)y,true);
for(x=0;x<image_width;++x) {
// read the image at x,y
z=TakeImageSample(img,x,y);
MoveTo(out,(float)x,(float)y,( z > level ));
}
MoveTo(out,(float)image_width,(float)y,true);
} else {
// every odd line move right to left
MoveTo(out,(float)image_width,(float)y,true);
for(x=image_width-1;x>=0;–x) {
z=TakeImageSample(img,x,y);
MoveTo(out,(float)x,(float)y,( z > level ));
}
MoveTo(out,(float)0,(float)y,true);
}
}
// TODO Sign name here?
// pen is already lifted. Return to home.
tool.WriteMoveTo(out, 0, 0);
// close the file
out.close();
}[/code]