18#include <potracelib.h>
25#include "trace/quantize.h"
31struct potrace_state_deleter {
void operator()(potrace_state_t *p) { potrace_state_free(p); }; };
32using potrace_state_uniqptr = std::unique_ptr<potrace_state_t, potrace_state_deleter>;
34struct potrace_bitmap_deleter {
void operator()(potrace_bitmap_t *p) {
bm_free(p); }; };
35using potrace_bitmap_uniqptr = std::unique_ptr<potrace_bitmap_t, potrace_bitmap_deleter>;
37Glib::ustring twohex(
int value)
51 : traceType(traceType)
53 , quantizationNrColors(quantizationNrColors)
54 , brightnessThreshold(brightnessThreshold)
55 , brightnessFloor(brightnessFloor)
56 , cannyHighThreshold(cannyHighThreshold)
57 , multiScanNrColors(multiScanNrColors)
58 , multiScanStack(multiScanStack)
59 , multiScanSmooth(multiScanSmooth)
60 , multiScanRemoveBackground(multiScanRemoveBackground) {
common_init(); }
98 auto to_geom = [] (potrace_dpoint_t
const &
c) {
102 for (
auto path =
paths; path; path = path->sibling) {
105 auto const &
curve = path->curve;
112 auto const pt = to_geom(seg[2]);
114 auto inserted = points.emplace(pt).second;
121 for (
int i = 0; i <
curve.n; i++) {
122 auto seg =
curve.c[i];
123 switch (
curve.tag[i]) {
125 builder.lineTo(to_geom(seg[1]));
126 builder.lineTo(to_geom(seg[2]));
128 case POTRACE_CURVETO:
129 builder.curveTo(to_geom(seg[0]), to_geom(seg[1]), to_geom(seg[2]));
145 std::optional<GrayMap>
map;
162 for (
int y = 0; y < gm.height; y++) {
163 for (
int x = 0; x < gm.width; x++) {
164 double brightness = gm.getPixel(x, y);
165 bool black = brightness >=
floor && brightness < cutoff;
183 for (
int y = 0; y <
map->height; y++) {
184 for (
int x = 0; x <
map->width; x++) {
185 auto brightness =
map->getPixel(x, y);
187 map->setPixel(x, y, brightness);
205 auto tomono = [] (
RGB c) ->
RGB {
206 unsigned char s = ((int)
c.r + (
int)
c.g + (int)
c.b) / 3;
212 for (
auto &
c : imap.clut) {
246 auto potraceBitmap = potrace_bitmap_uniqptr(
bm_new(grayMap.
width, grayMap.
height));
247 if (!potraceBitmap) {
254 for (
int y = 0; y < grayMap.
height; y++) {
255 for (
int x = 0; x < grayMap.
width; x++) {
256 BM_UPUT(potraceBitmap, x, y, grayMap.
getPixel(x, y) ? 0 : 1);
274 potraceParams->progress.callback = [] (
double progress,
void *
data) {
reinterpret_cast<decltype(throttled)*
>(
data)->report(progress); };
275 auto potraceState = potrace_state_uniqptr(potrace_trace(
potraceParams, potraceBitmap.get()));
277 potraceBitmap.reset();
283 std::unordered_set<Geom::Point> points;
295 auto grayMap =
filter(pixbuf);
306 results.emplace_back(
"fill:#000000", std::move(pv));
318 results.emplace_back(
"fill:#000000", std::move(pv));
327 double constexpr low = 0.2;
328 double constexpr high = 0.9;
340 auto grayMap =
filter(pixbuf);
345 subprogress.report_or_throw(0.2);
355 auto style = Glib::ustring::compose(
"fill-opacity:1.0;fill:#%1%2%3", twohex(grayVal), twohex(grayVal), twohex(grayVal));
358 results.emplace_back(style.raw(), std::move(pv));
364 subprogress.report_or_throw(1.0);
383 auto gm =
GrayMap(imap.width, imap.height);
384 for (
int row = 0; row < gm.height; row++) {
385 for (
int col = 0; col < gm.width; col++) {
392 for (
int colorIndex = 0; colorIndex < imap.nrColors; colorIndex++) {
393 auto subprogress =
Async::SubProgress(progress, (
double)colorIndex / imap.nrColors, 1.0 / imap.nrColors);
396 for (
int row = 0; row < imap.height; row++) {
397 for (
int col = 0; col < imap.width; col++) {
398 int index = imap.getPixel(col, row);
399 if (
index == colorIndex) {
407 subprogress.report_or_throw(0.2);
415 auto rgb = imap.clut[colorIndex];
416 auto style = Glib::ustring::compose(
"fill:#%1%2%3", twohex(
rgb.r), twohex(
rgb.g), twohex(
rgb.b));
417 results.emplace_back(style.raw(), std::move(pv));
420 subprogress.report_or_throw(1.0);
Store paths to a PathVector.
Two-dimensional point that doubles as a vector.
A Progress object that throttles reports to a given step size.
An interface for tasks to report progress and check for cancellation.
void report_or_throw(T const &... progress)
Report a progress value, throwing CancelledException if cancelled.
void throw_if_cancelled() const
Throw CancelledException if cancelled.
A Progress object representing a sub-task of another Progress.
double cannyHighThreshold
TraceResult traceBrightnessMulti(Glib::RefPtr< Gdk::Pixbuf > const &pixbuf, Async::Progress< double > &progress)
Called for multiple-scanning algorithms.
potrace_param_t * potraceParams
TraceResult trace(Glib::RefPtr< Gdk::Pixbuf > const &pixbuf, Async::Progress< double > &progress) override
This is the working method of this interface, and all implementing classes.
TraceResult traceSingle(Glib::RefPtr< Gdk::Pixbuf > const &pixbuf, Async::Progress< double > &progress)
This is called for a single scan.
double brightnessThreshold
bool multiScanRemoveBackground
TraceResult traceGrayMap(GrayMap const &grayMap, Async::Progress< double > &progress)
This allows routines that already generate GrayMaps to skip image filtering, increasing performance.
Glib::RefPtr< Gdk::Pixbuf > preview(Glib::RefPtr< Gdk::Pixbuf > const &pixbuf) override
Generate a quick preview without any actual tracing.
Geom::PathVector grayMapToPath(GrayMap const &gm, Async::Progress< double > &progress)
This is the actual wrapper of the call to Potrace.
TraceResult traceQuant(Glib::RefPtr< Gdk::Pixbuf > const &pixbuf, Async::Progress< double > &progress)
Quantization.
IndexedMap filterIndexed(Glib::RefPtr< Gdk::Pixbuf > const &pixbuf) const
std::optional< GrayMap > filter(Glib::RefPtr< Gdk::Pixbuf > const &pixbuf) const
void setOptTolerance(double)
void writePaths(potrace_path_t *paths, Geom::PathBuilder &builder, std::unordered_set< Geom::Point > &points, Async::Progress< double > &progress) const
Recursively descend the potrace_path_t node tree paths, writing paths to builder.
~PotraceTracingEngine() override
std::unordered_map< std::string, std::unique_ptr< SPDocument > > map
auto floor(Geom::Rect const &rect)
TODO: insert short description here.
potrace_path_s potrace_path_t
vector< vector< Point > > paths
RgbMap gdkPixbufToRgbMap(Glib::RefPtr< Gdk::Pixbuf > const &buf)
Glib::RefPtr< Gdk::Pixbuf > grayMapToGdkPixbuf(GrayMap const &map)
GrayMap grayMapCanny(GrayMap const &gm, double dLowThreshold, double dHighThreshold)
Perform Sobel convolution on a GrayMap.
RgbMap rgbMapGaussian(RgbMap const &me)
Apply gaussian blur to an RgbMap.
GrayMap gdkPixbufToGrayMap(Glib::RefPtr< Gdk::Pixbuf > const &buf)
GrayMap quantizeBand(RgbMap const &rgbMap, int nrColors)
std::vector< TraceResultItem > TraceResult
Glib::RefPtr< Gdk::Pixbuf > indexedMapToGdkPixbuf(IndexedMap const &map)
IndexedMap rgbMapQuantize(RgbMap const &rgbmap, int ncolor)
quantize an RGB image to a reduced number of colors.
Glib::ustring format_classic(T const &... args)
Helper class to stream background task notifications as a series of messages.
void invert(const double v[16], double alpha[16])
static unsigned long constexpr WHITE
static unsigned long constexpr BLACK
T getPixel(int x, int y) const
static potrace_bitmap_t * bm_new(int w, int h)
static void bm_free(potrace_bitmap_t *bm)
static void bm_clear(potrace_bitmap_t *bm, int c)
Glib::RefPtr< Gtk::Builder > builder