diff --git a/src/trace/trace.cpp b/src/trace/trace.cpp
index 408f5c5c3b988ef4e640817750a974240367da38..925e4e195de41aa2068d7f20fc56645ab0197563 100644 (file)
--- a/src/trace/trace.cpp
+++ b/src/trace/trace.cpp
-/*
+/**
* A generic interface for plugging different
* autotracers into Inkscape.
*
#include <desktop-handles.h>
#include <document.h>
#include <message-stack.h>
+#include <gtkmm.h>
#include <glibmm/i18n.h>
#include <selection.h>
#include <xml/repr.h>
-
/**
* Get the selected image. Also check for any SPItems over it, in
* case the user wants SIOX pre-processing.
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
if (!desktop)
{
- g_warning("Trace: No active desktop\n");
+ g_warning("Trace: No active desktop");
return NULL;
}
typedef org::siox::SioxImage SioxImage;
+typedef org::siox::SioxObserver SioxObserver;
typedef org::siox::Siox Siox;
-GdkPixbuf *
-Tracer::sioxProcessImage(SPImage *img, GdkPixbuf *origPixbuf)
+
+class TraceSioxObserver : public SioxObserver
+{
+public:
+
+ /**
+ *
+ */
+ TraceSioxObserver (void *contextArg) :
+ SioxObserver(contextArg)
+ {}
+
+ /**
+ *
+ */
+ virtual ~TraceSioxObserver ()
+ { }
+
+ /**
+ * Informs the observer how much has been completed.
+ * Return false if the processing should be aborted.
+ */
+ virtual bool progress(float percentCompleted)
+ {
+ //Tracer *tracer = (Tracer *)context;
+ //## Allow the GUI to update
+ Gtk::Main::iteration(false); //at least once, non-blocking
+ while( Gtk::Main::events_pending() )
+ Gtk::Main::iteration();
+ return true;
+ }
+
+ /**
+ * Send an error string to the Observer. Processing will
+ * be halted.
+ */
+ virtual void error(const std::string &msg)
+ {
+ //Tracer *tracer = (Tracer *)context;
+ }
+
+
+};
+
+
+
+
+
+/**
+ * Process a GdkPixbuf, according to which areas have been
+ * obscured in the GUI.
+ */
+Glib::RefPtr<Gdk::Pixbuf>
+Tracer::sioxProcessImage(SPImage *img,
+ Glib::RefPtr<Gdk::Pixbuf>origPixbuf)
{
if (!sioxEnabled)
return origPixbuf;
+ if (origPixbuf == lastOrigPixbuf)
+ return lastSioxPixbuf;
+
+ //g_message("siox: start");
+
//Convert from gdk, so a format we know. By design, the pixel
//format in PackedPixelMap is identical to what is needed by SIOX
- SioxImage simage(origPixbuf);
+ SioxImage simage(origPixbuf->gobj());
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
if (!desktop)
{
g_warning(_("Trace: No active desktop"));
- return NULL;
+ return Glib::RefPtr<Gdk::Pixbuf>(NULL);
}
Inkscape::MessageStack *msgStack = sp_desktop_message_stack(desktop);
char *msg = _("Select an <b>image</b> to trace");
msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
//g_warning(msg);
- return NULL;
+ return Glib::RefPtr<Gdk::Pixbuf>(NULL);
}
NRArenaItem *aImg = sp_item_get_arenaitem(img, desktop->dkey);
for (iter = sioxShapes.begin() ; iter!=sioxShapes.end() ; iter++)
{
SPItem *item = *iter;
- //### Create ArenaItems and set transform
NRArenaItem *aItem = sp_item_get_arenaitem(item, desktop->dkey);
-
- //nr_arena_item_set_transform(aItem, item->transform);
- //g_message("%d %d %d %d\n", aItem->bbox.x0, aItem->bbox.y0,
- // aItem->bbox.x1, aItem->bbox.y1);
arenaItems.push_back(aItem);
}
+
//g_message("%d arena items\n", arenaItems.size());
- PackedPixelMap *dumpMap = PackedPixelMapCreate(
- simage.getWidth(), simage.getHeight());
+ //PackedPixelMap *dumpMap = PackedPixelMapCreate(
+ // simage.getWidth(), simage.getHeight());
+
+ //g_message("siox: start selection");
- for (int row=0 ; row<simage.getHeight() ; row++)
+ for (int row=0 ; row<iheight ; row++)
{
double ypos = ((double)aImg->bbox.y0) + ihscale * (double) row;
for (int col=0 ; col<simage.getWidth() ; col++)
point *= aImg->transform;
//point *= imgMat;
//point = desktop->doc2dt(point);
- std::vector<SPShape *>::iterator iter;
//g_message("x:%f y:%f\n", point[0], point[1]);
bool weHaveAHit = false;
std::vector<NRArenaItem *>::iterator aIter;
if (weHaveAHit)
{
//g_message("hit!\n");
- dumpMap->setPixelLong(dumpMap, col, row, 0L);
+ //dumpMap->setPixelLong(dumpMap, col, row, 0L);
simage.setConfidence(col, row,
Siox::UNKNOWN_REGION_CONFIDENCE);
}
else
{
- dumpMap->setPixelLong(dumpMap, col, row,
- simage.getPixel(col, row));
+ //g_message("miss!\n");
+ //dumpMap->setPixelLong(dumpMap, col, row,
+ // simage.getPixel(col, row));
simage.setConfidence(col, row,
Siox::CERTAIN_BACKGROUND_CONFIDENCE);
}
}
}
+ //g_message("siox: selection done");
+
//dumpMap->writePPM(dumpMap, "siox1.ppm");
- dumpMap->destroy(dumpMap);
+ //dumpMap->destroy(dumpMap);
//## ok we have our pixel buf
- org::siox::Siox sengine;
- org::siox::SioxImage result =
- sengine.extractForeground(simage, 0xffffff);
+ TraceSioxObserver observer(this);
+ Siox sengine(&observer);
+ SioxImage result = sengine.extractForeground(simage, 0xffffff);
if (!result.isValid())
{
g_warning(_("Invalid SIOX result"));
- return NULL;
+ return Glib::RefPtr<Gdk::Pixbuf>(NULL);
}
//result.writePPM("siox2.ppm");
nr_object_unref((NRObject *) arena);
*/
- GdkPixbuf *newPixbuf = result.getGdkPixbuf();
+ Glib::RefPtr<Gdk::Pixbuf> newPixbuf = Glib::wrap(result.getGdkPixbuf());
+
+ //g_message("siox: done");
+
+ lastSioxPixbuf = newPixbuf;
return newPixbuf;
}
/**
*
*/
-GdkPixbuf *
+Glib::RefPtr<Gdk::Pixbuf>
Tracer::getSelectedImage()
{
+
SPImage *img = getSelectedSPImage();
if (!img)
- return NULL;
+ return Glib::RefPtr<Gdk::Pixbuf>(NULL);
- GdkPixbuf *pixbuf = img->pixbuf;
- if (!pixbuf)
- return NULL;
+ if (!img->pixbuf)
+ return Glib::RefPtr<Gdk::Pixbuf>(NULL);
+
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf =
+ Glib::wrap(img->pixbuf, true);
if (sioxEnabled)
{
- GdkPixbuf *sioxPixbuf = sioxProcessImage(img, pixbuf);
+ Glib::RefPtr<Gdk::Pixbuf> sioxPixbuf =
+ sioxProcessImage(img, pixbuf);
if (!sioxPixbuf)
{
- g_object_ref(pixbuf);
return pixbuf;
}
else
}
else
{
- g_object_ref(pixbuf);
return pixbuf;
}
return;
}
- GdkPixbuf *pixbuf = img->pixbuf;
- g_object_ref(pixbuf);
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(img->pixbuf, true);
pixbuf = sioxProcessImage(img, pixbuf);
return;
}
- int nrPaths;
- TracingEngineResult *results = engine->trace(pixbuf, &nrPaths);
- //printf("nrPaths:%d\n", nrPaths);
+ msgStack->flash(Inkscape::NORMAL_MESSAGE, _("Trace: Starting trace..."));
+ desktop->updateCanvasNow();
+
+ std::vector<TracingEngineResult> results =
+ engine->trace(pixbuf);
+ //printf("nrPaths:%d\n", results.size());
+ int nrPaths = results.size();
//### Check if we should stop
- if (!keepGoing || !results || nrPaths<1)
+ if (!keepGoing || nrPaths<1)
{
engine = NULL;
return;
NR::Matrix trans(NR::translate(x, y));
- double iwidth = (double)gdk_pixbuf_get_width(pixbuf);
- double iheight = (double)gdk_pixbuf_get_height(pixbuf);
+ double iwidth = (double)pixbuf->get_width();
+ double iheight = (double)pixbuf->get_height();
double iwscale = width / iwidth;
double ihscale = height / iheight;
//#OK. Now let's start making new nodes
+ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc());
Inkscape::XML::Node *groupRepr = NULL;
//# if more than 1, make a <g>roup of <path>s
if (nrPaths > 1)
{
- groupRepr = sp_repr_new("svg:g");
+ groupRepr = xml_doc->createElement("svg:g");
par->addChild(groupRepr, imgRepr);
}
long totalNodeCount = 0L;
- for (TracingEngineResult *result=results ;
- result ; result=result->next)
+ for (unsigned int i=0 ; i<results.size() ; i++)
{
- totalNodeCount += result->getNodeCount();
+ TracingEngineResult result = results[i];
+ totalNodeCount += result.getNodeCount();
- Inkscape::XML::Node *pathRepr = sp_repr_new("svg:path");
- pathRepr->setAttribute("style", result->getStyle());
- pathRepr->setAttribute("d", result->getPathData());
+ Inkscape::XML::Node *pathRepr = xml_doc->createElement("svg:path");
+ pathRepr->setAttribute("style", result.getStyle().c_str());
+ pathRepr->setAttribute("d", result.getPathData().c_str());
if (nrPaths > 1)
groupRepr->addChild(pathRepr, NULL);
Inkscape::GC::release(pathRepr);
}
- //release our pixbuf
- g_object_unref(pixbuf);
-
- delete results;
-
// If we have a group, then focus on, then forget it
if (nrPaths > 1)
{
}
//## inform the document, so we can undo
- sp_document_done(doc);
+ sp_document_done(doc, SP_VERB_SELECTION_TRACE, _("Trace bitmap"));
engine = NULL;