inkscape-potrace.cpp revision 5cacbbec22b42a0480f396eb94bcfb5f746ac68a
/*
* This is the C++ glue between Inkscape and Potrace
*
* Authors:
* Bob Jamison <rjamison@titan.com>
* Stéphane Gimenez <dev@gim.name>
*
* Copyright (C) 2004-2006 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*
* Potrace, the wonderful tracer located at http://potrace.sourceforge.net,
* is provided by the generosity of Peter Selinger, to whom we are grateful.
*
*/
#include "inkscape-potrace.h"
#include <iomanip>
#include "trace/filterset.h"
#include "trace/quantize.h"
#include "trace/imagemap-gdk.h"
#include <inkscape.h>
#include <desktop-handles.h>
#include "message-stack.h"
#include <sp-path.h>
#include <svg/path-string.h>
#include "curve.h"
#include "bitmap.h"
static void updateGui()
{
//## Allow the GUI to update
}
{
updateGui();
if (!userData)
return;
//g_message("progress: %f\n", progress);
//Inkscape::Trace::Potrace::PotraceTracingEngine *engine =
// (Inkscape::Trace::Potrace::PotraceTracingEngine *)userData;
}
namespace {
{
}
} // namespace
//required by potrace
namespace Inkscape {
namespace Trace {
namespace Potrace {
/**
*
*/
keepGoing(1),
invert(false),
brightnessThreshold(0.45),
brightnessFloor(0),
cannyHighThreshold(0.65),
multiScanStack(true),
multiScanSmooth(false),
multiScanRemoveBackground(false)
{
/* get default parameters */
}
{
}
typedef struct
{
double x;
double y;
} Point;
/**
* Check a point against a list of points to see if it
* has already occurred.
*/
{
{
if (p.x == x && p.y == y)
return true;
}
return false;
}
/**
* Recursively descend the path_t node tree, writing paths in SVG
* format into the output stream. The Point vector is used to prevent
* redundant paths. Returns number of paths processed.
*/
{
long nodeCount = 0L;
{
//g_message("node->fm:%d\n", node->fm);
if (!curve->n)
continue;
double x0 = 0.0;
double y0 = 0.0;
double x1 = 0.0;
double y1 = 0.0;
//Have we been here already?
{
//g_message("duplicate point: (%f,%f)\n", x2, y2);
continue;
}
else
{
Point p;
}
nodeCount++;
for (int i=0 ; i<curve->n ; i++)
{
return 0L;
{
case POTRACE_CORNER:
break;
case POTRACE_CURVETO:
break;
default:
break;
}
nodeCount++;
}
{
}
}
return nodeCount;
}
{
if (!pixbuf)
return NULL;
/*### Color quantization -- banding ###*/
{
//rgbMap->writePPM(rgbMap, "rgb.ppm");
//return newGm;
}
/*### Brightness threshold ###*/
{
double floor = 3.0 *
double cutoff = 3.0 *
{
{
else
}
}
//newGm->writePPM(newGm, "brightness.ppm");
//return newGm;
}
/*### Canny edge detection ###*/
{
//newGm->writePPM(newGm, "canny.ppm");
//return newGm;
}
/*### Do I invert the image? ###*/
{
{
{
}
}
}
return newGm;//none of the above
}
{
if (!pixbuf)
return NULL;
if (engine.getMultiScanSmooth())
{
}
else
{
}
{
//Turn to grays
{
}
}
return newGm;
}
{
if ( traceType == TRACE_QUANT_COLOR ||
{
if (!gm)
return newBuf;
}
else
{
if (!gm)
return newBuf;
}
}
//*This is the core inkscape-to-potrace binding
{
if (!keepGoing)
{
g_warning("aborted");
return "";
}
bm_clear(potraceBitmap, 0);
//##Read the data out of the GrayMap
{
{
BM_UPUT(potraceBitmap, x, y,
}
}
//##Debug
/*
FILE *f = fopen("poimage.pbm", "wb");
bm_writepbm(f, bm);
fclose(f);
*/
/* trace a bitmap*/
//## Free the Potrace bitmap
if (!keepGoing)
{
g_warning("aborted");
return "";
}
//## copy the path information into our d="" attribute string
/* free a potrace items */
if (!keepGoing)
return "";
if ( nodeCount)
}
/**
* This is called for a single scan
*/
{
if (!thePixbuf)
return results;
if (!grayMap)
return results;
long nodeCount;
char const *style = "fill:#000000";
//g_message("### GOT '%s' \n", d);
return results;
}
/**
* This allows routines that already generate GrayMaps to skip image filtering,
* increasing performance.
*/
{
long nodeCount;
char const *style = "fill:#000000";
//g_message("### GOT '%s' \n", d);
return results;
}
/**
* Called for multiple-scanning algorithms
*/
{
if ( thePixbuf ) {
int traceCount = 0;
for ( brightnessThreshold = low ;
brightnessThreshold <= high ;
brightnessThreshold += delta) {
if ( grayMap ) {
long nodeCount;
if ( !d.empty() ) {
//### get style info
ustring style = ustring::compose("fill-opacity:1.0;fill:%1%2%3", twohex(grayVal), twohex(grayVal), twohex(grayVal) );
//g_message("### GOT '%s' \n", style.c_str());
if (!multiScanStack) {
}
if (desktop) {
}
}
}
}
//# Remove the bottom-most scan, if requested
}
}
return results;
}
/**
* Quantization
*/
{
if (thePixbuf) {
if ( iMap ) {
//Create and clear a gray map
}
}
// Make a gray map for each color index
if (indx == colorIndex) {
} else if (!multiScanStack) {
}
}
}
//## Now we have a traceable graymap
long nodeCount;
if ( !d.empty() ) {
//### get style info
//g_message("### GOT '%s' \n", style.c_str());
if (desktop) {
}
}
}// for colorIndex
}
//# Remove the bottom-most scan, if requested
}
}
return results;
}
/**
* This is the working method of this interface, and all
* implementing classes. Take a GdkPixbuf, trace it, and
* return the path data that is compatible with the d="" attribute
* of an SVG <path> element.
*/
{
//Set up for messages
keepGoing = 1;
if ( traceType == TRACE_QUANT_COLOR ||
{
return traceQuant(thePixbuf);
}
else if ( traceType == TRACE_BRIGHTNESS_MULTI )
{
return traceBrightnessMulti(thePixbuf);
}
else
{
return traceSingle(thePixbuf);
}
}
/**
* Abort the thread that is executing getPathDataFromPixbuf()
*/
void PotraceTracingEngine::abort()
{
//g_message("PotraceTracingEngine::abort()\n");
keepGoing = 0;
}
} // namespace Potrace
} // namespace Trace
} // namespace Inkscape
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :