### Summary

PixelPrinter is a web app to make parameterized, pixelated, 3D-printable objects from images by selecting a few representative colors.

### Workflow

1. Select or upload an image. Smaller images work best, since larger images take longer to generate the model.
2. Click on two or more colors in your image that you want PixelPrinter to keep. PixelPrinter will convert any non-selected colors in the image to the colors you select. The first selected color will be the tallest in the final model. The last selected color will be the shortest.
3. Simplify the colors and review the simplified image.
4. Generate the model.
5. Play with the parameters on the left to customize your model. Click Update to regenerate the model with the new parameters. Click and drag to rotate the model. Shift+click and drag to pan.
8. Profit.

### How it works

The user uploads an image, and it gets scaled up or down to fit the available space and drawn onto an HTML5 canvas element.

When the user mouses over the image, the color under the cursor is shown. When the user clicks, the color under the cursor is saved to a list and shown at the bottom of the page.

When the user is happy with the selection of colors, she may Simplify Colors. This command first converts all the saved colors to grayscale by averaging the rgb values. Then, it goes pixel-by-pixel through the image and converts each pixel's color to grayscale, and it finds the the closest saved (grayscale) color via the good ol' Pythagorean Theorem $x^2+y^2+z^2=(distance)^2$. The resulting image is written out to another HTML5 canvas element and displayed alongside the original image.

When the user choses to generate the 3D model from an image, she may either choose Generate Model from Original Image or Generate Model from Simplified Image. In either case, the command goes pixel-by-pixel through the image, creating and placing a block in the appropriate place. The height of the block is determined by the color of the pixel. Fully transparent pixels (shown with a checkerboard pattern in the images) are ignored.

For models generated from the Simplified image, the number next to the color correspond to the block's height for all pixels of that color.

For models generated from the Original image, the system finds all of the unique colors in the original image, and makes the darkest ones tallest, and the lightest ones shortest. (Again, with the Pythagorean Theorem finding the grayscale color's distance from pure white, rgb(255,255,255).)

Since all of the rendering happens on the user's computer, rendering time can vary widely. Most 50px square images render in less than 15 seconds. Some text and a loading icon are shown in the bottom left of the screen to indicate to the user that the rendering is still processing.

Once the 3D model is generated, the user can then rotate/zoom/pan the view to get a better look.

The parameters on the left side of the screen allow the user to modify the 3D model without regenerating a new model from the images.

The Model parameter is a holdover from development since this is still a work in progress. It substitutes an entirely different model into the view.

The Additional Thickness parameter increases all of the block heights by the value specified. It's useful for making objects that stand upright.

The Multiplier parameter acts very similarly to Additional Thickness, except instead of the specified value being added to the block height, it is multiplied by the block height.

The 10 numbered parameters resize each block-height category individually. For example, if Twos is set to 3, then all blocks that were originally 2 unit tall become 3 units tall. There is a lot of room for improvement in how these parameters are named and generated. Ideally, there would only be as many block-height category parameters as there are actual block-height categories, but currently number is hardcoded to 10.

The secret sauce is betrayed by the New Bitmap Array parameter. This is where the resultant array that represents the block heights ends up after it is calculated from the image. It's merely an array of arrays, so you can type in your own just to see. For instance, perhaps you can recognize this guy?

[
[0,0,0,3,3,3,3,3,0,0,0,0],
[0,0,3,3,3,3,3,3,3,3,3,0],
[0,0,2,2,2,1,1,2,1,0,0,0],
[0,2,1,2,1,1,1,2,1,1,1,0],
[0,2,1,2,2,1,1,1,2,1,1,1],
[0,2,2,1,1,1,1,2,2,2,2,0],
[0,0,0,1,1,1,1,1,1,1,0,0],
[0,0,2,2,3,2,2,2,0,0,0,0],
[0,2,2,2,3,2,2,3,2,2,2,0],
[2,2,2,2,3,3,3,3,2,2,2,2],
[1,1,2,3,1,3,3,1,3,2,1,1],
[1,1,1,3,3,3,3,3,3,1,1,1],
[1,1,3,3,3,3,3,3,3,3,1,1],
[0,0,3,3,3,0,0,3,3,3,0,0],
[0,2,2,2,0,0,0,0,2,2,2,0],
[2,2,2,2,0,0,0,0,2,2,2,2]
]


"It's me, Mario"

Just for fun, the user can change the color of the 3D model. I submitted a pull request for this color-picker feature to the main OpenJSCad branch, but they were already working on it.

Update re-renders the model with the updated parameters. Instant Update re-renders the model as soon as any of the parameter input fields loses focus.

When the user is ready, she may select a downloadable file format and download her model. They print quite quickly and easily. The models are usually relatively short in the Z-axis, and there is often a lot of surface area to adhere to the print bed.

So yeah, I'm quite happy with it. 8/10 would code/print again.