GlyphAutoTrace.h header

#include <ew/app/GlyphAutoTrace.h>

Namespace ew::app

TraceBitmap struct

struct ew::app::TraceBitmap

A greyscale bitmap for the tracer to read: width by height samples, row-major, 0 black and 255 white.

Deliberately not an image type. The tracer is geometry, not presentation, and taking a plain buffer keeps it testable without a window system and leaves the desktop free to hand it a photograph, a scan, or a region a user dragged out of one.

Members

int ew::app::script::TraceBitmap::width = 0

Samples across.

int ew::app::script::TraceBitmap::height = 0

Samples down.

std::vector<std::uint8_t> ew::app::script::TraceBitmap::luminance

The samples, row-major, width * height of them.

bool ew::app::script::TraceBitmap::isValid() const

Whether the buffer's size matches its dimensions, so a caller cannot trace a truncated image and get silently wrong geometry from the rows that are missing.

std::uint8_t ew::app::script::TraceBitmap::at(int x, int y) const

The sample at (x, y), or 255 (blank) outside the image – so the edge of the picture behaves like paper rather than like ink.

TraceOptions struct

struct ew::app::TraceOptions

How a bitmap is turned into strokes.

Members

int ew::app::script::TraceOptions::threshold = 128

Samples at or beyond this distance from the paper colour count as ink (0-255).

bool ew::app::script::TraceOptions::inkIsDark = true

Whether the drawing is dark on light. False traces light marks on a dark ground, which is what a photograph of chalk or a negative scan gives.

double ew::app::script::TraceOptions::simplifyTolerance = 0.01

How far, in glyph-box units, a point may sit from the line before it is kept. Larger leaves fewer points.

int ew::app::script::TraceOptions::minimumPoints = 3

Strokes with fewer points than this are dropped, which removes the specks a photograph of paper always has without touching a real mark.

bool ew::app::script::TraceOptions::fitToInk = true

Whether the traced result is scaled so the INK fills the glyph box.

On by default because a photograph is mostly margin: tracing a letter that occupies a tenth of the frame and placing it at a tenth of the box would make every traced glyph tiny and the feature useless. The aspect ratio is kept, so the letter is not stretched.

Functions

std::vector< bool > ew::app::script::inkMask(const TraceBitmap &bitmap, const TraceOptions &options)

bitmap reduced to the samples that are ink, as a mask the size of the image.

Exposed so a preview can show what the threshold selected. A user who cannot see what counts as ink can only adjust the slider by trial.

std::vector< bool > ew::app::script::thinned(const std::vector< bool > &mask, int width, int height)

mask thinned to single-sample centrelines (Zhang-Suen), the same size as the input.

std::vector< ew::core::conlang::Stroke > ew::app::script::traceBitmap(const TraceBitmap &bitmap, const TraceOptions &options)

The strokes bitmap's drawn lines reduce to.

Threshold, thin to single-sample centrelines, trace those into polylines splitting at every junction so a crossing becomes separate strokes rather than one path that doubles back, then simplify. The result is an ordinary editable glyph – a very good first draft, not a final answer, which is the whole point: manual tracing of complex curves is the difference between an afternoon and a week for a user with a page of drawings.