diff --git a/src/trace/trace.cpp b/src/trace/trace.cpp
index 2e46dd854fba8789f826d11a197e4b1635796b5d..925e4e195de41aa2068d7f20fc56645ab0197563 100644 (file)
--- a/src/trace/trace.cpp
+++ b/src/trace/trace.cpp
-/*
+/**
* A generic interface for plugging different
* autotracers into Inkscape.
*
* A generic interface for plugging different
* autotracers into Inkscape.
*
#include <desktop-handles.h>
#include <document.h>
#include <message-stack.h>
#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>
#include <glibmm/i18n.h>
#include <selection.h>
#include <xml/repr.h>
#include <sp-item.h>
#include <sp-shape.h>
#include <sp-image.h>
#include <sp-item.h>
#include <sp-shape.h>
#include <sp-image.h>
-#include <splivarot.h> //for intersection boolop
+
+#include <display/nr-arena.h>
+#include <display/nr-arena-shape.h>
#include "siox.h"
#include "imagemap-gdk.h"
#include "siox.h"
#include "imagemap-gdk.h"
-namespace Inkscape {
-namespace Trace {
+
+namespace Inkscape
+{
+
+namespace Trace
+{
+
+
+
+
/**
/**
- *
+ * Get the selected image. Also check for any SPItems over it, in
+ * case the user wants SIOX pre-processing.
*/
SPImage *
Tracer::getSelectedSPImage()
{
*/
SPImage *
Tracer::getSelectedSPImage()
{
+
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
if (!desktop)
{
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
if (!desktop)
{
- g_warning("Trace: No active desktop\n");
+ g_warning("Trace: No active desktop");
return NULL;
}
return NULL;
}
- Inkscape::Selection *sel = SP_DT_SELECTION(desktop);
+ Inkscape::MessageStack *msgStack = sp_desktop_message_stack(desktop);
+
+ Inkscape::Selection *sel = sp_desktop_selection(desktop);
if (!sel)
{
char *msg = _("Select an <b>image</b> to trace");
if (!sel)
{
char *msg = _("Select an <b>image</b> to trace");
- SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
//g_warning(msg);
return NULL;
}
//g_warning(msg);
return NULL;
}
if (img) //we want only one
{
char *msg = _("Select only one <b>image</b> to trace");
if (img) //we want only one
{
char *msg = _("Select only one <b>image</b> to trace");
- SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
return NULL;
}
img = SP_IMAGE(item);
}
return NULL;
}
img = SP_IMAGE(item);
}
- else if (img) //# items -after- the image in tree (above it in Z)
+ else // if (img) //# items -after- the image in tree (above it in Z)
{
if (SP_IS_SHAPE(item))
{
{
if (SP_IS_SHAPE(item))
{
}
}
}
}
}
}
+
if (!img || sioxShapes.size() < 1)
{
char *msg = _("Select one image and one or more shapes above it");
if (!img || sioxShapes.size() < 1)
{
char *msg = _("Select one image and one or more shapes above it");
- SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
return NULL;
}
return img;
return NULL;
}
return img;
if (!item)
{
char *msg = _("Select an <b>image</b> to trace"); //same as above
if (!item)
{
char *msg = _("Select an <b>image</b> to trace"); //same as above
- SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
//g_warning(msg);
return NULL;
}
//g_warning(msg);
return NULL;
}
if (!SP_IS_IMAGE(item))
{
char *msg = _("Select an <b>image</b> to trace");
if (!SP_IS_IMAGE(item))
{
char *msg = _("Select an <b>image</b> to trace");
- SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
//g_warning(msg);
return NULL;
}
//g_warning(msg);
return NULL;
}
-/**
- *
- */
-GdkPixbuf *
-Tracer::getSelectedImage()
+typedef org::siox::SioxImage SioxImage;
+typedef org::siox::SioxObserver SioxObserver;
+typedef org::siox::Siox Siox;
+
+
+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;
+ }
- SPImage *img = getSelectedSPImage();
- if (!img)
- return NULL;
+ /**
+ * Send an error string to the Observer. Processing will
+ * be halted.
+ */
+ virtual void error(const std::string &msg)
+ {
+ //Tracer *tracer = (Tracer *)context;
+ }
- GdkPixbuf *pixbuf = img->pixbuf;
- return pixbuf;
+};
+
-}
-GdkPixbuf *
-Tracer::sioxProcessImage(SPImage *img, GdkPixbuf *origPixbuf)
+
+/**
+ * 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;
- PackedPixelMap *ppMap = gdkPixbufToPackedPixelMap(origPixbuf);
- //We need to create two things:
- // 1. An array of long pixel values of ARGB
- // 2. A matching array of per-pixel float 'confidence' values
- unsigned long *imgBuf = ppMap->pixels;
- float *confidenceMatrix = new float[ppMap->width * ppMap->height];
+ if (origPixbuf == lastOrigPixbuf)
+ return lastSioxPixbuf;
- Inkscape::XML::Node *imgRepr = SP_OBJECT(img)->repr;
- /*
- //## Make a Rect overlaying the image
- Inkscape::XML::Node *parent = imgRepr->parent();
+ //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->gobj());
- Inkscape::XML::Node *rect = sp_repr_new("svg:rect");
- Inkscape::Util::List<Inkscape::XML::AttributeRecord const> attr =
- imgRepr->attributeList();
- for ( ; attr ; attr++)
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (!desktop)
{
{
- rect->setAttribute(g_quark_to_string(attr->key), attr->value, false);
+ g_warning(_("Trace: No active desktop"));
+ return Glib::RefPtr<Gdk::Pixbuf>(NULL);
}
}
+ Inkscape::MessageStack *msgStack = sp_desktop_message_stack(desktop);
- //Inkscape::XML::Node *rect = imgRepr->duplicate();
- parent->appendChild(rect);
- Inkscape::GC::release(rect);
- */
+ Inkscape::Selection *sel = sp_desktop_selection(desktop);
+ if (!sel)
+ {
+ char *msg = _("Select an <b>image</b> to trace");
+ msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
+ //g_warning(msg);
+ return Glib::RefPtr<Gdk::Pixbuf>(NULL);
+ }
- //### <image> element
- double x = 0.0;
- double y = 0.0;
- double width = 0.0;
- double height = 0.0;
- double dval = 0.0;
+ NRArenaItem *aImg = sp_item_get_arenaitem(img, desktop->dkey);
+ //g_message("img: %d %d %d %d\n", aImg->bbox.x0, aImg->bbox.y0,
+ // aImg->bbox.x1, aImg->bbox.y1);
- if (sp_repr_get_double(imgRepr, "x", &dval))
- x = dval;
- if (sp_repr_get_double(imgRepr, "y", &dval))
- y = dval;
+ double width = (double)(aImg->bbox.x1 - aImg->bbox.x0);
+ double height = (double)(aImg->bbox.y1 - aImg->bbox.y0);
- if (sp_repr_get_double(imgRepr, "width", &dval))
- width = dval;
- if (sp_repr_get_double(imgRepr, "height", &dval))
- height = dval;
-
- double iwidth = (double)ppMap->width;
- double iheight = (double)ppMap->height;
+ double iwidth = (double)simage.getWidth();
+ double iheight = (double)simage.getHeight();
double iwscale = width / iwidth;
double ihscale = height / iheight;
double iwscale = width / iwidth;
double ihscale = height / iheight;
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ std::vector<NRArenaItem *> arenaItems;
+ std::vector<SPShape *>::iterator iter;
+ for (iter = sioxShapes.begin() ; iter!=sioxShapes.end() ; iter++)
+ {
+ SPItem *item = *iter;
+ NRArenaItem *aItem = sp_item_get_arenaitem(item, desktop->dkey);
+ arenaItems.push_back(aItem);
+ }
+
+ //g_message("%d arena items\n", arenaItems.size());
+
+ //PackedPixelMap *dumpMap = PackedPixelMapCreate(
+ // simage.getWidth(), simage.getHeight());
+
+ //g_message("siox: start selection");
- unsigned long cmIndex = 0;
- for (int row=0 ; row<ppMap->height ; row++)
+ for (int row=0 ; row<iheight ; row++)
{
{
- double ypos = y + ihscale * (double) row;
- for (int col=0 ; col<ppMap->width ; col++)
+ double ypos = ((double)aImg->bbox.y0) + ihscale * (double) row;
+ for (int col=0 ; col<simage.getWidth() ; col++)
{
//Get absolute X,Y position
{
//Get absolute X,Y position
- double xpos = x + iwscale * (double)col;
+ double xpos = ((double)aImg->bbox.x0) + iwscale * (double)col;
NR::Point point(xpos, ypos);
NR::Point point(xpos, ypos);
- point *= img->transform;
- point = desktop->doc2dt(point);
- std::vector<SPShape *>::iterator iter;
- g_message("x:%f y:%f\n", point[0], point[1]);
- SPItem *itemOverPoint = desktop->item_at_point(point, false, NULL);
- int weHaveAHit = false;
- if (itemOverPoint)
+ point *= aImg->transform;
+ //point *= imgMat;
+ //point = desktop->doc2dt(point);
+ //g_message("x:%f y:%f\n", point[0], point[1]);
+ bool weHaveAHit = false;
+ std::vector<NRArenaItem *>::iterator aIter;
+ for (aIter = arenaItems.begin() ; aIter!=arenaItems.end() ; aIter++)
{
{
- printf("searching\n");
- for (iter = sioxShapes.begin() ; iter!=sioxShapes.end() ; iter++)
+ NRArenaItem *arenaItem = *aIter;
+ NRArenaItemClass *arenaClass =
+ (NRArenaItemClass *) NR_OBJECT_GET_CLASS (arenaItem);
+ if (arenaClass->pick(arenaItem, point, 1.0f, 1))
{
{
- SPShape *shape = *iter;
- if (shape == itemOverPoint)
- {
- weHaveAHit = true;
- break;
- }
+ weHaveAHit = true;
+ break;
}
}
}
}
+
if (weHaveAHit)
{
if (weHaveAHit)
{
- g_message("hit!\n");
- confidenceMatrix[cmIndex] =
- org::siox::SioxSegmentator::CERTAIN_FOREGROUND_CONFIDENCE;
+ //g_message("hit!\n");
+ //dumpMap->setPixelLong(dumpMap, col, row, 0L);
+ simage.setConfidence(col, row,
+ Siox::UNKNOWN_REGION_CONFIDENCE);
}
else
{
}
else
{
- confidenceMatrix[cmIndex] =
- org::siox::SioxSegmentator::CERTAIN_BACKGROUND_CONFIDENCE;
+ //g_message("miss!\n");
+ //dumpMap->setPixelLong(dumpMap, col, row,
+ // simage.getPixel(col, row));
+ simage.setConfidence(col, row,
+ Siox::CERTAIN_BACKGROUND_CONFIDENCE);
}
}
- cmIndex++;
}
}
}
}
+ //g_message("siox: selection done");
+
+ //dumpMap->writePPM(dumpMap, "siox1.ppm");
+ //dumpMap->destroy(dumpMap);
+
//## ok we have our pixel buf
//## ok we have our pixel buf
- org::siox::SioxSegmentator ss(ppMap->width, ppMap->height, NULL, 0);
- ss.segmentate(imgBuf, ppMap->width * ppMap->height,
- confidenceMatrix, ppMap->width * ppMap->height,
- 0, 0.0);
+ TraceSioxObserver observer(this);
+ Siox sengine(&observer);
+ SioxImage result = sengine.extractForeground(simage, 0xffffff);
+ if (!result.isValid())
+ {
+ g_warning(_("Invalid SIOX result"));
+ return Glib::RefPtr<Gdk::Pixbuf>(NULL);
+ }
+
+ //result.writePPM("siox2.ppm");
+
+ /* Free Arena and ArenaItem */
+ /*
+ std::vector<NRArenaItem *>::iterator aIter;
+ for (aIter = arenaItems.begin() ; aIter!=arenaItems.end() ; aIter++)
+ {
+ NRArenaItem *arenaItem = *aIter;
+ nr_arena_item_unref(arenaItem);
+ }
+ nr_object_unref((NRObject *) arena);
+ */
+ Glib::RefPtr<Gdk::Pixbuf> newPixbuf = Glib::wrap(result.getGdkPixbuf());
+ //g_message("siox: done");
- GdkPixbuf *newPixbuf = packedPixelMapToGdkPixbuf(ppMap);
- ppMap->destroy(ppMap);
- delete confidenceMatrix;
+ lastSioxPixbuf = newPixbuf;
return newPixbuf;
}
return newPixbuf;
}
+/**
+ *
+ */
+Glib::RefPtr<Gdk::Pixbuf>
+Tracer::getSelectedImage()
+{
+
+
+ SPImage *img = getSelectedSPImage();
+ if (!img)
+ return Glib::RefPtr<Gdk::Pixbuf>(NULL);
+
+ if (!img->pixbuf)
+ return Glib::RefPtr<Gdk::Pixbuf>(NULL);
+
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf =
+ Glib::wrap(img->pixbuf, true);
+
+ if (sioxEnabled)
+ {
+ Glib::RefPtr<Gdk::Pixbuf> sioxPixbuf =
+ sioxProcessImage(img, pixbuf);
+ if (!sioxPixbuf)
+ {
+ return pixbuf;
+ }
+ else
+ {
+ return sioxPixbuf;
+ }
+ }
+ else
+ {
+ return pixbuf;
+ }
+
+}
+
//#########################################################################
//#########################################################################
return;
}
return;
}
- Inkscape::Selection *selection = SP_DT_SELECTION (desktop);
+ Inkscape::MessageStack *msgStack = sp_desktop_message_stack(desktop);
+
+ Inkscape::Selection *selection = sp_desktop_selection (desktop);
if (!SP_ACTIVE_DOCUMENT)
{
char *msg = _("Trace: No active document");
if (!SP_ACTIVE_DOCUMENT)
{
char *msg = _("Trace: No active document");
- SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
//g_warning(msg);
engine = NULL;
return;
//g_warning(msg);
engine = NULL;
return;
return;
}
return;
}
- GdkPixbuf *pixbuf = img->pixbuf;
+ Glib::RefPtr<Gdk::Pixbuf> pixbuf = Glib::wrap(img->pixbuf, true);
+
+ pixbuf = sioxProcessImage(img, pixbuf);
if (!pixbuf)
{
char *msg = _("Trace: Image has no bitmap data");
if (!pixbuf)
{
char *msg = _("Trace: Image has no bitmap data");
- SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ msgStack->flash(Inkscape::ERROR_MESSAGE, msg);
//g_warning(msg);
engine = NULL;
return;
}
//g_warning(msg);
engine = NULL;
return;
}
- //## SIOX pre-processing to get a smart subimage of the pixbuf.
- //## This is done before any other filters
- if (sioxEnabled)
- {
- /*
- Ok, we have requested siox, and getSelectedSPImage() has found a single
- bitmap and one or more SPItems above it. Now what we need to do is create
- a siox-segmented subimage pixbuf. We not need alter 'img' at all, since this
- pixbuf will be the same dimensions and at the same location.
- Remember to free this new pixbuf later.
- */
- pixbuf = sioxProcessImage(img, pixbuf);
- }
-
- 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
//### Check if we should stop
- if (!keepGoing || !results || nrPaths<1)
+ if (!keepGoing || nrPaths<1)
{
engine = NULL;
return;
{
engine = NULL;
return;
NR::Matrix trans(NR::translate(x, y));
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;
double iwscale = width / iwidth;
double ihscale = height / iheight;
//#OK. Now let's start making new nodes
//#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)
{
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;
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);
if (nrPaths > 1)
groupRepr->addChild(pathRepr, NULL);
Inkscape::GC::release(pathRepr);
}
Inkscape::GC::release(pathRepr);
}
- //did we allocate a pixbuf copy?
- if (sioxEnabled)
- {
- g_free(pixbuf);
- }
-
- delete results;
-
// If we have a group, then focus on, then forget it
if (nrPaths > 1)
{
// If we have a group, then focus on, then forget it
if (nrPaths > 1)
{
}
//## inform the document, so we can undo
}
//## inform the document, so we can undo
- sp_document_done(doc);
+ sp_document_done(doc, SP_VERB_SELECTION_TRACE, _("Trace bitmap"));
engine = NULL;
char *msg = g_strdup_printf(_("Trace: Done. %ld nodes created"), totalNodeCount);
engine = NULL;
char *msg = g_strdup_printf(_("Trace: Done. %ld nodes created"), totalNodeCount);
- SP_DT_MSGSTACK(desktop)->flash(Inkscape::NORMAL_MESSAGE, msg);
+ msgStack->flash(Inkscape::NORMAL_MESSAGE, msg);
g_free(msg);
}
g_free(msg);
}