A simple interface to the Brushograph software: it turns uploaded thresholded images into G-code for Brushograph-style brush plotters.
How a run works
- A machine config (
.conf) describes the machine. Every option below it is generated from that file. - You upload one thresholded image per tray, in the order given by
color_order. - Each image is traced to vectors with potrace, extruded to a solid with OpenSCAD, and filled with PrusaSlicer to get brush strokes.
- copicograf turns those strokes into brush choreography: dipping in the paint tray, knocking off drips on the rim, washing in water, and re-inking every few hundred millimetres.
Tool status on this machine
| potrace | /usr/bin/potrace |
| openscad | /usr/local/bin/openscad |
| slicer | /usr/bin/prusa-slicer |
Notes
- A tray's image can be already thresholded or a photo. A photo becomes a woodcut first: shadows go solid black, midtones are carried by hatching that thickens as the tone darkens, highlights stay as paper. The hatching follows the picture's own directions, curving around a form the way a carved line does, rather than lying over it as straight stripes or a lattice. Hatch spacing follows the brush width, so every mark is one the machine can actually paint. Preview it before running.
- If a person, animal or prominent object is detected in the photo, an Isolate option appears. It cuts the subject out with a small segmentation network (U²-Net, 4.4 MB, downloaded once on first start and run through OpenCV), leaving the background as bare paper. Without the model it falls back to GrabCut, which is worse but keeps the feature working.
- The opening sequence — mix, wash, load the brush — is not part of a job. A job starts painting with whatever is already on the brush.
- Dip Depth sets how far the brush goes into a cup. It was fixed at Z −4, which is deeper than a shallow dish needs. It is always offered, even by a config that does not mention it, as are the backlash settings, which are ticked unless the config says otherwise.
- The preview shows the path without backlash compensation. Those corrective moves are for the machine's slack, and drawing them would bury the artwork in strokes that are not in it.
- A shape too thin for the slicer to outline gets its centreline painted instead, so every ribbon, hairline and rib is drawn rather than dropped.
- An infill line distance of 0 paints outlines only. A nominal 1 mm stroke width stands in for the brush, since the config then states none.
- Files are named after the picture and the colours used —
vali_letten_c1_infill.gcode— with the tray numbers the form shows. - The ink/paper split is found per image rather than fixed, so a print on cream paper is not read as one solid block of ink. It is taken on the darkest colour channel, so a light ink such as yellow still counts as ink.
- Set
infill_line_distanceto roughly the width your brush lays down. It is the gap between fill lines; a pen-plotter value such as 0.5 mm paints the same area ten times over. On one test image, going from 0.5 mm to 5 mm cut brush lifts from 598 to 103, tray dips from 318 to 74, and painted distance from 23.8 m to 4.5 m. - Strokes the slicer split are chained back together, and ends within 1.5 line widths are
bridged into one serpentine, so the brush stays down for as long as possible. Reaching
further gains nothing: the brush must re-ink every
paint_per_runanyway. - copicograf detects brush-up and brush-down from two exact Z lines that only
cura-sliceremits. Slicer output is rewritten into that form before it is handed over, so any installed slicer works. - Configs naming a generator other than
copicografrender their options here, but cannot be built — that generator is not part of this repository. M204,M203andM400come from the config'smovesblocks and are Marlin-only. They are kept for Controller Type: Marlin and stripped for GRBL and FluidNC, which halt on an unknown M-code. A config with no controller section is treated as GRBL.- Every file opens with
G90/G21, the normal feedrate and a lift to the config's safe Z, before anything moves. copicografemitsG28 X Yonce near the top. Marlin homes on it; GRBL and FluidNC reject the bare axis words outright, so it is replaced with a comment. It is not rewritten to$H, which needs limit switches — home or zero the machine yourself before streaming.