This document should be cited using something like the bibtex entry:
Anyone who has ever played with a 3D printer no doubt almostimmediately encountered the little problem of having a 2D imagethat they wanted to convert into a 3D model. However, there's aspecial reason this became a priority for me now: for the firsttime in over three decades of being a professor, in Fall 2015, Iwill have a blind student in one of the classes I teach. Mycourse unfortunately has significant visual components in theform of various diagrams, so one of the obvious possibleapproaches would be to try to use my 3D printer to createtactile versions of the key graphics for the course. I createdtrace2scad to facilitate making these 'bump readable'graphic images using my MakerGear M2 3D printer.
Trace2SCAD is distributed as full sourcecode under Creative Commons - Attribution constraints. Youuse it at your own risk, with no warranty, etc.

3d Printer Images Sample

Background

There are many ways to convert 2D graphics into a 3D-printablemodel. There are even a number of free software toolsexplicitly supporting this type of transformation. To name afew:
  • PNG23D is avery widely available free tool that converts a PNG image intoeither an OpenSCAD or STL file. It's not fast, but directlygenerates a triangle mesh for a manifold polygon representingthe pixel values as heights. Put another way, this converts animage into a Lithophane, and can even deal with color.
  • Img2SCAD is aPython tool that converts a monochrome image into an OpenSCADstructure that is essentially a cube per pixel, such that thecube height represents the 'whiteness' of the correspondingpixel.
  • OpenSCAD itself has long included a surface()primitive that can read a raw data file and represent it an anobject where the height at each point corresponds to the datavalue for that point, with nicely sloped transitions betweenpoints. The data file format is not an image per se, butconsists of ASCII text giving whitespace-separated integer pixelheights -- which is easily generated by stripping the header offan ASCII PGM file (the type that begins with the sequenceP2). As of the 2014.QX versions, there is also provisionfor reading-in a PNG image, with gray scale values computedas Y = 0.2126R + 0.7152G + 0.0722B and scaled to 0.100.
  • Inkscape offers a verydifferent alternative. It is capable of directly manipulatingvector drawings and can even trace pixel-based images to createvector forms. These vetor forms can then be saved as DXF files,which tools like OpenSCAD can import directly. The catch is thatthe vector model in Inkscape is far more general than what DXFfiles can represent, so the drawing must be processed to removeconstructs like smooth curves, replacing them all withstraight-line segments. In the 'Extensions' menu, there is anoption called 'Flatten Beziers' which does this simplificationwith a user-settable 'Flatness,' but it is notoriouslyunreliable. It is worth noting that the output of Inkscape iscompletely flat in the sense that model height is fixed at 1unit.
  • Image to lithophaneis a fantastic WWW-based tool for creating 3D STL meshes fromimages. It's probably what you want if you want to makelithophanes. However, it generates models with complexityproportional to image pixel count.
  • Curanow has the ability to read-in an image file and create a smoothedheight-map, which it can 'save model' as an STL file. It's notparticularly clever, but it's free, fast, and really easy to use.Model complexity is proportional to pixel count.Can be used to make simple lithophanes.
  • Selva3D is yet anotherWWW-based tool for generating 3D models from 2D images. Itcharges for 'high quality' STLs, but delivers lower-quality onesfor free after a 2-minute delay. It seems to be attempting tosimplify the model much as trace2scad does, but perhapsnot as successfully. Still, it does appear to generate 3D outputdirectly.

3d Printer Images To Print

Given all those different approaches (and there are many othersnot mentioned above), why are we creating and posting yetanother tool to convert images into models? Well, we generate anOpenSCAD model, not an STL file. In addition, OpenSCADdoesn't deal well with very complex models, so we try tomoderate model complexity. Unfortunately, to get smooth-lookingstructures from all the above except Inkscape, you need lots ofpixels and model complexity for most of the above is directlyproportional to the total number of pixels in the image.Inkscape solves this problem, but not in an easy to use norreliable way. Trace2SCAD is doing much the same processing as wewould do with Inkscape, but it is much faster, easier to use,directly generates an OpenSCAD model of controllable size, andhopefully will prove to be more reliable.
One more thing: trace2scad also knows how to buildmulti-layer models somewhat like the pixel bump maps built byother tools, but not based on pixels. The 3D modelsare presented as a set of discrete layers, so it would be moretechnically correct to call it 2.5D rather than 3D.

Image Ascii 2 3d Printer Installer

How Trace2SCAD Works

Trace2SCAD is a shell script using sed, awk,ImageMagick convert, mkbitmap, andpotrace. Thanks to convert, nearly any imagefile format can be used for the input, and mkbitmap isused to further enhance the image for procesing, but the bulk ofthe work is really done by the incredibly useful Potrace. That toolis also what does the heavy lifting for Inkscape. However,rather than letting potrace go to all the work ofgenerating smooth curves and then converting them tostraight-line segments, we simply tell potrace tooutput straight-line segments. The specific style of grouped SVGoutput by potrace is then parsed and reprocessed tocreate an OpenSCAD module definition.
There are a few options that we'll discuss in the followingsection, but there is one that is particularly important andunique to this tool: trace2scad allows you to specify amaximum model complexity, and will automatically iteratesimplifying the image and retracing until a model is createdthat does not exceed the target complexity. Thus, you havedirect control over the compexity of the OpenSCAD model -- whichis critical given that OpenSCAD can take many hours to renderoverly complex models, often quietly failing after many hours ofprocessing.

Ascii 3d Text

Using Trace2SCAD

Trace2SCAD is really very easy to use, essentially able toaccept just about any type of 2D image file as input anddirectly generating an output file that contains the OpenSCADmodel as a set of module definitions. The modules are alwaysscaled to be bounded within a 1mm cube that is sitting on theZ=0 plane and is centered at X=0, Y=0. That is almost certainlytoo small to be used directly; for example, iflithophane() is the name of a generated module that youwant to make have a maximum X or Y dimension of 100mm and Z 3mm,this can be done using scale([100, 100, 3])lithophane();. Note that the X/Y aspect ratio of theoriginal image is preserved by trace2scad, so the X andY scaling components should normally be the same value.
At this writing, the command line for trace2scad hasfair number of options, but most are rarely needed. The basicusage is:
The command line options are:
-a
Force alignment of the model based on image bounds (also--align). Normally, the model is centered based on thebounding box computed from the generated models, but that meansposition of the object within the original image is lost. Thus,overlaying multiple trace2scad models from the sameoriginal image will not align them. To ensure alignment,-a is automatically set if you are generating modelsfor more than one layer.
-cnumber
Set the target model complexity (also --complex). Themodel will be iteratively simplified until the total number ofpoints in the polygons is no more than number.
-enumber
Set the maximum line-combining error in pixels (also--pixerr). When the model is converted to linesegments, very often there will be cases where a sequence ofmultiple line segments could be converted into a single linesegment with minimal error. This option sets the maximumdistance, in pixels, that a discarded point can be from the linethat replaces it. The default value is a very conservative 1.0;larger values will tend to greatly simplify the model while'smoothing' minor bumps that often happen due to pixel-levelaliasing of the original image. For high-resolution images,-e 2 to -e 10 can really help smooth thingswith minimal ill effect. This feature was added in version20150415.
-fnumber
Set the highpass filter radius (also --filter). If setto 0, the image will simply be thresholded to find edges andlarge dark areas will be modeled as solids. If set greater than0, the effect is to convert constant-brightness regions intooutlines with an edge thickness proportional to thenumber. Generally, a value between 2 and 4 isappropriate for outlining.
-gnumber
Set the image gamma (also --gamma). This allows simpleadjustment of the tonal spread of the image before filteringand thresholding.
-h
Print the command line help message to stderr and exit.
-llevelspec
Set the level threshold or thresholds (also --level).A level directly determines the cut-off between model and void.The number should be a decimal value between 0 and 1(exclusive); for example, '-l 0.5' would set a singlethreshold of 0.5. However, this command line option can also beused to specify multiple levels to create a contoured 3D modelby union. Such a 3D contour, for example, can be used as themodel for a Lithophane. You can give a single integer value (with no'.') to request creation of that many levels with levelthresholds equally spaced between 0 and 1. For example, '-l4' would create four levels. If you want direct controlover the individual levels used, you can instead list them with',' between the threshold values: '-l0.875,0.625,0.375,0.125' produces the same result as'-l 4' -- creating four levels. If more than one levelis specified, -a is implied to ensure that the levelswill align correctly.
-ofile
Set the file name for the OpenSCAD output to file.Normally, the output file name is derived from the inputfilename by replacing any characters after '.' with'.scad' -- but that can be a problem if the image iscoming from a read-only directory, etc. When you specify adifferent name using -o, the name is used precisely asentered, without adding the suffix '.scad.'
-pprefix
Set the name prefix to use for the generated OpenSCAD model(also --prefix). By default, the name prefix is derivedfrom the image file name by removing the portion of the nameafter ., but that might not result in an appropriatename. For example, files can have - in their names, butOpenSCAD modules can't. The resulting model can be instantiatedby prefix();; an individual layer of the modelcan be instantiated byprefix_number(); wherenumber is the level number starting at 1.
-snumber
Set the sub-pixel resolution (also --subres). This isreally a potrace parameter, determining the fraction ofa pixel to which analysis is performed. Larger values are moreprecise, but values between 2 and 10 generally suffice.
-tnumber
Set the 'turd' size (also --turd). This is really apotrace parameter, and the name isn't my fault. Anytraced region smaller than number pixels is essentiallydiscarded from the model.
-v
Enable verbose output to stderr (also --verbose).There are some other messages that go to stdout, but these canbe isolated because they go to stderr. Enabling verbosity alsohas the side effect of leaving temporary files holding theintermediate stages in processing, so it would be appropriate tothink of it as primarily a debugging option.
-xnumber
Set the maximum X axis pixel resolution of the image (also--xres). This value doesn't have as straightforward aneffect on the model as one might expect, but larger values tendto create somewhat more complex models. The iterative complexityscaling is actually implemented by reducing this value andreprocessing.
-ynumber
Set the maximum Y axis pixel resolution of the image (also--yres). Just like X, but for the Y axis..
inputimagefile
The inputimagefile can be in any format understood byImageMagick convert. The portion of the name after .is stripped to create the default prefix for OpenSCAD model componentnames. The output file name is also generated from inputimagefileby removing the portion of the name after . and replacing it with.scad. For example, test.jpg would produce OpenSCADcode names starting with test and would place the output in afile named test.scad.

Examples

Let's start with an easy one: converting a Klingon plaque designfor my parallel processing lab into an OpenSCAD model. Thecommand line was:
The generated OpenSCAD modelfile is fairly straightforward, and the model is simplyklingon_dondewi(). The -f 0 said to keepsolid areas solid. We could also have let the system do highpassfiltering to extract edges:
The generated OpenSCAD model file isfairly straightforward, and the model is again simplyklingon_dondewi(). The original input image and thetwo OpenSCAD 3D models (scaled to 200x200x1) look like:
Ok. That was easy. The second model seems to have done a goodjob of extracting the outlines, except there's also some fluffthat doesn't belong. You can easily fix them using the-t option to remove those little 'turds' (aspotrace calls them). Actually, had I not been sosloppy when making the image, there wouldn't have been a weakbroken edge there for trace2scad to detect in the firstplace..
As of version 20150415, the -e option can really helpto smooth-out the model. This OpenSCAD model, generated by ./trace2scad -f 0 -e10 klingon_dondewi.png, is much cleaner and simpler thanthe ones above. It uses just 387 points, which is only about1/10 as many as the above models, yet the quality of the modelis not clearly inferior; in some ways, it is actually better.
Here's a harder case: my face. For this one, we'll asktrace2scad to make an 8-layer lithophane:
This OpenSCAD model is the resultof converting the following image into the design shown by OpenSCAD.Yes, by default trace2scad sets the object colors based onthe threshold used for each level, so it really does look like amonochrome image.

The Source Code

It's just one file -- a shell script. Thelatest version is trace2scad.All released versions of trace2scad are linked here:
trace2scad20150106
Initial release. Probably buggy? Let me know if you findanything..
trace2scad20150107
Quick clean-up of the initial version. Potrace often generatesline segments that are segments of a potentially longer linesegment, so this version optimizes those out, and now alsoprunes the too-complex trace attempts faster.
trace2scad20150415
Added the -e option to dramatically reduce modelcomplexity and smooth bumps due to pixel-level aliasing.Minor other tweaks.
The only thing set in stone is our name.