Image to G-code in Javascript (part 2)
Part 1: https://speakr.blog/thuijzer/posts/2
When raw pixels of an image are loaded in Javascript we can use them to generate G-code commands. This post will explain a very simple example: we are going to mill holes as pixels, deep holes for dark pixels and shallow holes for light pixels.
Relating image size to mill size
The image we loaded has a certain size. For example 800x600 pixels. Actually, size is not the best term here. An image doesn't have a real size, but in our case it has 800 horizontal and 600 vertical pixels. A pixel also doesn't have a size. A pixel is just a location (horizontal x vertical) with a color and maybe some transparency.
Let's say we have a piece of wood that is 100x200 mm in size. And we are going to drill holes with a drill bit that is 2mm in diameter. Then we can drill 50x100 holes in our work piece. When we reduce our image from 800x600 pixels to 50x100 pixels we can just use each pixel for each hole. In part 1 we used this code to draw the image on the canvas: ``` context.drawImage( image, // source image 0, // source x position 0, // source y position image.width, // source width image.height, // source height 0, // destination x position 0, // destination y position canvas.width, // destination width canvas.height // destination height ); ``` Let's change this so the image is reduced to 50x100 pixels.
First let's set some variables at the top of our code we can later use: ``` let workPieceWidth = 100; // mm let workPieceHeight = 200; // mm let drillBitSize = 2; // mm let horizontalPixels = Math.floor(workPieceWidth / drillBitSize); let verticalPixels = Math.floor(workPieceHeight / drillBitSize); ``` We now know how big our canvas should be, only horizontalPixels by verticalPixels. So first change the code that sets the canvas size: ``` let canvas = document.createElement('canvas'); canvas.width = horizontalPixels; canvas.height = verticalPixels; ``` Now the canvas has the right size. But how do we determine which pixels of the image will be drawn on it?
Using the right pixels
To determine which pixels should be used we first need to know the proportions of the image and of the canvas: ``` let imageP = image.width / image.height; let canvasP = canvas.width / canvas.height; ``` Now we know the proportions (landscape vs portrait) of both the image and canvas. If the value is smaller than 1 it means it is portrait. If it is greater than 1 it is landscape. 1 means it is square. For our example this will give us `imageP == 1.33` (800 / 600) and `canvasP == 0.5` (50 / 100). Because the canvas is portrait the image height should be scaled to the height of the canvas. Then the pixels of the image will cover the complete canvas. Let's calculate the scale value we should use for the image so it matches the canvas: ``` let scale = 1; if(imageP < canvasP) { scale = image.width / canvas.width; } else { scale = image.height / canvas.height; } ``` Now we can draw the image on the canvas using the right size: ``` context.drawImage( image, // source image 0, // source x position 0, // source y position canvas.width \* scale, // source width canvas.height \* scale, // source height 0, // destination x position 0, // destination y position canvas.width, // destination width canvas.height // destination height ); ``` But there is a small 'problem' with this. The image will always be drawn from the top left corner. If we want to center the image on the canvas we first must calculate how much pixels are not drawn, divide that amount by 2 and use that as offset: ``` let srcX = (image.width - canvas.width \* scale) \* 0.5; let srcY = (image.height - canvas.height \* scale) \* 0.5; context.drawImage( image, // source image srcX, // source x position srcY, // source y position canvas.width * scale, // source width canvas.height * scale, // source height 0, // destination x position 0, // destination y position canvas.width, // destination width canvas.height // destination height ); ``` Now we scaled the pixels of the image to the amount of pixels we need to create our G-code. Once again the raw pixel data can be accessed by using: ``` let imageData = context.getImageData( 0, // x position 0, // y position canvas.width, // width canvas.height // height ); ``` In my next post we will finally generate G-code from this image data: https://speakr.blog/thuijzer/posts/5