inkscape-potrace.cpp revision 6129af7cc5b723223e9617614c931936e5190421
359a38ce40498397028473d956691915ed3e849atavmjong-free * This is the C++ glue between Inkscape and Potrace
359a38ce40498397028473d956691915ed3e849atavmjong-free * Bob Jamison <rjamison@titan.com>
359a38ce40498397028473d956691915ed3e849atavmjong-free * Copyright (C) 2004 Bob Jamison
359a38ce40498397028473d956691915ed3e849atavmjong-free * Released under GNU GPL, read the file 'COPYING' for more information
359a38ce40498397028473d956691915ed3e849atavmjong-free * Potrace, the wonderful tracer located at http://potrace.sourceforge.net,
359a38ce40498397028473d956691915ed3e849atavmjong-free * is provided by the generosity of Peter Selinger, to whom we are grateful.
359a38ce40498397028473d956691915ed3e849atavmjong-free //## Allow the GUI to update
359a38ce40498397028473d956691915ed3e849atavmjong-free Gtk::Main::iteration(false); //at least once, non-blocking
359a38ce40498397028473d956691915ed3e849atavmjong-freestatic void potraceStatusCallback(double progress, void *userData) /* callback fn */
359a38ce40498397028473d956691915ed3e849atavmjong-free //g_message("progress: %f\n", progress);
359a38ce40498397028473d956691915ed3e849atavmjong-free //Inkscape::Trace::Potrace::PotraceTracingEngine *engine =
652485ad88d2a42f827c7e355220efeb3b2e37afLiam P. White // (Inkscape::Trace::Potrace::PotraceTracingEngine *)userData;
359a38ce40498397028473d956691915ed3e849atavmjong-free//required by potrace
359a38ce40498397028473d956691915ed3e849atavmjong-free //##### Our defaults
359a38ce40498397028473d956691915ed3e849atavmjong-freetypedef struct
5f19756f48574526dda8abedebf811c9d1456e80Markus Engel * Check a point against a list of points to see if it
359a38ce40498397028473d956691915ed3e849atavmjong-free * has already occurred.
359a38ce40498397028473d956691915ed3e849atavmjong-freehasPoint(std::vector<Point> &points, double x, double y)
359a38ce40498397028473d956691915ed3e849atavmjong-free if (p.x == x && p.y == y)
359a38ce40498397028473d956691915ed3e849atavmjong-free return false;
359a38ce40498397028473d956691915ed3e849atavmjong-free * Recursively descend the path_t node tree, writing paths in SVG
359a38ce40498397028473d956691915ed3e849atavmjong-free * format into the output stream. The Point vector is used to prevent
359a38ce40498397028473d956691915ed3e849atavmjong-free * redundant paths. Returns number of paths processed.
652485ad88d2a42f827c7e355220efeb3b2e37afLiam P. WhitewritePaths(PotraceTracingEngine *engine, potrace_path_t *plist,
359a38ce40498397028473d956691915ed3e849atavmjong-free Inkscape::SVGOStringStream& data, std::vector<Point> &points)
359a38ce40498397028473d956691915ed3e849atavmjong-free //g_message("node->fm:%d\n", node->fm);
359a38ce40498397028473d956691915ed3e849atavmjong-free //Have we been here already?
359a38ce40498397028473d956691915ed3e849atavmjong-free //g_message("duplicate point: (%f,%f)\n", x2, y2);
359a38ce40498397028473d956691915ed3e849atavmjong-free for (int i=0 ; i<curve->n ; i++)
359a38ce40498397028473d956691915ed3e849atavmjong-free for (path_t *child=node->childlist; child ; child=child->sibling)
359a38ce40498397028473d956691915ed3e849atavmjong-free nodeCount += writePaths(engine, child, data, points);
359a38ce40498397028473d956691915ed3e849atavmjong-freefilter(PotraceTracingEngine &engine, GdkPixbuf * pixbuf)
359a38ce40498397028473d956691915ed3e849atavmjong-free /*### Color quantization -- banding ###*/
359a38ce40498397028473d956691915ed3e849atavmjong-free //rgbMap->writePPM(rgbMap, "rgb.ppm");
359a38ce40498397028473d956691915ed3e849atavmjong-free //return newGm;
359a38ce40498397028473d956691915ed3e849atavmjong-free /*### Brightness threshold ###*/
359a38ce40498397028473d956691915ed3e849atavmjong-free else if ( engine.getTraceType() == TRACE_BRIGHTNESS ||
359a38ce40498397028473d956691915ed3e849atavmjong-free engine.getTraceType() == TRACE_BRIGHTNESS_MULTI )
359a38ce40498397028473d956691915ed3e849atavmjong-free double brightness = (double)gm->getPixel(gm, x, y);
359a38ce40498397028473d956691915ed3e849atavmjong-free if (brightness >= floor && brightness < cutoff)
359a38ce40498397028473d956691915ed3e849atavmjong-free newGm->setPixel(newGm, x, y, GRAYMAP_BLACK); //black pixel
359a38ce40498397028473d956691915ed3e849atavmjong-free newGm->setPixel(newGm, x, y, GRAYMAP_WHITE); //white pixel
359a38ce40498397028473d956691915ed3e849atavmjong-free //newGm->writePPM(newGm, "brightness.ppm");
359a38ce40498397028473d956691915ed3e849atavmjong-free //return newGm;
359a38ce40498397028473d956691915ed3e849atavmjong-free /*### Canny edge detection ###*/
359a38ce40498397028473d956691915ed3e849atavmjong-free else if (engine.getTraceType() == TRACE_CANNY)
359a38ce40498397028473d956691915ed3e849atavmjong-free newGm = grayMapCanny(gm, 0.1, engine.getCannyHighThreshold());
359a38ce40498397028473d956691915ed3e849atavmjong-free //newGm->writePPM(newGm, "canny.ppm");
359a38ce40498397028473d956691915ed3e849atavmjong-free //return newGm;
359a38ce40498397028473d956691915ed3e849atavmjong-free /*### Do I invert the image? ###*/
bf9ec3e969ba6b11cbbc613545aedc63cc886973Matthew Petroff unsigned long brightness = newGm->getPixel(newGm, x, y);
359a38ce40498397028473d956691915ed3e849atavmjong-freefilterIndexed(PotraceTracingEngine &engine, GdkPixbuf * pixbuf)
add38d633bbf8ef881bdb908735ea27385c554b8Matthew Petroff /*### Color quant multiscan ###*/
359a38ce40498397028473d956691915ed3e849atavmjong-free if (engine.getTraceType() == TRACE_QUANT_COLOR)
359a38ce40498397028473d956691915ed3e849atavmjong-free newGm = rgbMapQuantize(gaussMap, 8, engine.getMultiScanNrColors());
359a38ce40498397028473d956691915ed3e849atavmjong-free newGm = rgbMapQuantize(gm, 8, engine.getMultiScanNrColors());
359a38ce40498397028473d956691915ed3e849atavmjong-free /*### Quant multiscan ###*/
359a38ce40498397028473d956691915ed3e849atavmjong-free else if (engine.getTraceType() == TRACE_QUANT_MONO)
359a38ce40498397028473d956691915ed3e849atavmjong-free newGm = rgbMapQuantize(gaussMap, 8, engine.getMultiScanNrColors());
359a38ce40498397028473d956691915ed3e849atavmjong-free newGm = rgbMapQuantize(gm, 8, engine.getMultiScanNrColors());
359a38ce40498397028473d956691915ed3e849atavmjong-free //Turn to grays
652485ad88d2a42f827c7e355220efeb3b2e37afLiam P. WhitePotraceTracingEngine::preview(GdkPixbuf * pixbuf)
652485ad88d2a42f827c7e355220efeb3b2e37afLiam P. White IndexedMap *gm = filterIndexed(*this, pixbuf);
652485ad88d2a42f827c7e355220efeb3b2e37afLiam P. White GdkPixbuf *newBuf = indexedMapToGdkPixbuf(gm);
359a38ce40498397028473d956691915ed3e849atavmjong-free//*This is the core inkscape-to-potrace binding
359a38ce40498397028473d956691915ed3e849atavmjong-freechar *PotraceTracingEngine::grayMapToPath(GrayMap *grayMap, long *nodeCount)
359a38ce40498397028473d956691915ed3e849atavmjong-free /* get default parameters */
359a38ce40498397028473d956691915ed3e849atavmjong-free potrace_param_t *potraceParams = potrace_param_default();
359a38ce40498397028473d956691915ed3e849atavmjong-free potraceParams->progress.callback = potraceStatusCallback;
359a38ce40498397028473d956691915ed3e849atavmjong-free potrace_bitmap_t *potraceBitmap = bm_new(grayMap->width, grayMap->height);
if (!keepGoing)
return NULL;
if (!keepGoing)
return NULL;
if (!keepGoing)
return NULL;
if ( nodeCount)
if (!thePixbuf)
return NULL;
if (!grayMap)
return NULL;
long nodeCount;
*nrPaths = 0;
return NULL;
free(d);
return result;
if (!thePixbuf)
return NULL;
int traceCount = 0;
if (!grayMap)
return NULL;
long nodeCount;
*nrPaths = 0;
return NULL;
free(d);
if (!results)
if (!multiScanStack)
if (desktop)
return results;
if (!thePixbuf)
return NULL;
if (!iMap)
return NULL;
if (!multiScanStack)
long nodeCount;
*nrPaths = 0;
return NULL;
free(d);
if (!results)
if (desktop)
return results;
keepGoing = 0;