X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Ftrace%2Ftrace.cpp;h=925e4e195de41aa2068d7f20fc56645ab0197563;hb=724821145d62dee9f97465c706952582da6e432d;hp=04f1cbed0c9e1696e6ca527a1d8c6615a5a692f5;hpb=b9dca513b411d7d67bca555c52add0e3295c1990;p=inkscape.git diff --git a/src/trace/trace.cpp b/src/trace/trace.cpp index 04f1cbed0..925e4e195 100644 --- a/src/trace/trace.cpp +++ b/src/trace/trace.cpp @@ -1,4 +1,4 @@ -/* +/** * A generic interface for plugging different * autotracers into Inkscape. * @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -33,33 +34,40 @@ #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() { + SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) { - g_warning("Trace: No active desktop\n"); + g_warning("Trace: No active desktop"); 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 image to trace"); - SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg); + msgStack->flash(Inkscape::ERROR_MESSAGE, msg); //g_warning(msg); return NULL; } @@ -94,7 +102,7 @@ Tracer::getSelectedSPImage() if (img) //we want only one { char *msg = _("Select only one image to trace"); - SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg); + msgStack->flash(Inkscape::ERROR_MESSAGE, msg); return NULL; } img = SP_IMAGE(item); @@ -112,7 +120,7 @@ Tracer::getSelectedSPImage() 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; @@ -124,7 +132,7 @@ Tracer::getSelectedSPImage() if (!item) { char *msg = _("Select an image 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; } @@ -132,7 +140,7 @@ Tracer::getSelectedSPImage() if (!SP_IS_IMAGE(item)) { char *msg = _("Select an image to trace"); - SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg); + msgStack->flash(Inkscape::ERROR_MESSAGE, msg); //g_warning(msg); return NULL; } @@ -146,55 +154,96 @@ Tracer::getSelectedSPImage() -/** - * - */ -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 +Tracer::sioxProcessImage(SPImage *img, + Glib::RefPtrorigPixbuf) { + 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 - 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]; + SioxImage simage(origPixbuf->gobj()); SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) { - g_warning("Trace: No active desktop\n"); - return NULL; + g_warning(_("Trace: No active desktop")); + return Glib::RefPtr(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 image to trace"); - SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg); + msgStack->flash(Inkscape::ERROR_MESSAGE, msg); //g_warning(msg); - return NULL; + return Glib::RefPtr(NULL); } - Inkscape::XML::Node *imgRepr = SP_OBJECT(img)->repr; - 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); @@ -202,36 +251,32 @@ Tracer::sioxProcessImage(SPImage *img, GdkPixbuf *origPixbuf) double width = (double)(aImg->bbox.x1 - aImg->bbox.x0); double height = (double)(aImg->bbox.y1 - aImg->bbox.y0); - 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; - unsigned long cmIndex = 0; - - std::vector arenaItems; std::vector::iterator iter; 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(ppMap->width, ppMap->height); + //PackedPixelMap *dumpMap = PackedPixelMapCreate( + // simage.getWidth(), simage.getHeight()); - for (int row=0 ; rowheight ; row++) + //g_message("siox: start selection"); + + for (int row=0 ; rowbbox.y0) + ihscale * (double) row; - for (int col=0 ; colwidth ; col++) + for (int col=0 ; colbbox.x0) + iwscale * (double)col; @@ -239,7 +284,6 @@ Tracer::sioxProcessImage(SPImage *img, GdkPixbuf *origPixbuf) point *= aImg->transform; //point *= imgMat; //point = desktop->doc2dt(point); - std::vector::iterator iter; //g_message("x:%f y:%f\n", point[0], point[1]); bool weHaveAHit = false; std::vector::iterator aIter; @@ -258,27 +302,37 @@ Tracer::sioxProcessImage(SPImage *img, GdkPixbuf *origPixbuf) if (weHaveAHit) { //g_message("hit!\n"); - dumpMap->setPixelLong(dumpMap, col, row, 0L); - confidenceMatrix[cmIndex] = - org::siox::SioxSegmentator::CERTAIN_FOREGROUND_CONFIDENCE; + //dumpMap->setPixelLong(dumpMap, col, row, 0L); + simage.setConfidence(col, row, + Siox::UNKNOWN_REGION_CONFIDENCE); } else { - dumpMap->setPixelLong(dumpMap, col, row, - ppMap->getPixel(ppMap, col, row)); - 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 - org::siox::SioxSegmentator ss(ppMap->width, ppMap->height, NULL, 0); - ss.segmentate(imgBuf, confidenceMatrix, 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(NULL); + } - dumpMap->writePPM(dumpMap, "siox.ppm"); - dumpMap->destroy(dumpMap); + //result.writePPM("siox2.ppm"); /* Free Arena and ArenaItem */ /* @@ -291,14 +345,54 @@ Tracer::sioxProcessImage(SPImage *img, GdkPixbuf *origPixbuf) nr_object_unref((NRObject *) arena); */ - GdkPixbuf *newPixbuf = packedPixelMapToGdkPixbuf(ppMap); - ppMap->destroy(ppMap); - delete confidenceMatrix; + Glib::RefPtr newPixbuf = Glib::wrap(result.getGdkPixbuf()); + + //g_message("siox: done"); + + lastSioxPixbuf = newPixbuf; return newPixbuf; } +/** + * + */ +Glib::RefPtr +Tracer::getSelectedImage() +{ + + + SPImage *img = getSelectedSPImage(); + if (!img) + return Glib::RefPtr(NULL); + + if (!img->pixbuf) + return Glib::RefPtr(NULL); + + Glib::RefPtr pixbuf = + Glib::wrap(img->pixbuf, true); + + if (sioxEnabled) + { + Glib::RefPtr sioxPixbuf = + sioxProcessImage(img, pixbuf); + if (!sioxPixbuf) + { + return pixbuf; + } + else + { + return sioxPixbuf; + } + } + else + { + return pixbuf; + } + +} + //######################################################################### @@ -333,12 +427,14 @@ void Tracer::traceThread() 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"); - SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg); + msgStack->flash(Inkscape::ERROR_MESSAGE, msg); //g_warning(msg); engine = NULL; return; @@ -354,37 +450,29 @@ void Tracer::traceThread() return; } - GdkPixbuf *pixbuf = img->pixbuf; + Glib::RefPtr pixbuf = Glib::wrap(img->pixbuf, true); + + pixbuf = sioxProcessImage(img, pixbuf); 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; } - //## 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 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; @@ -413,8 +501,8 @@ void Tracer::traceThread() 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; @@ -429,25 +517,26 @@ void Tracer::traceThread() //#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 roup of 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 ; igetNodeCount(); + 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); @@ -469,14 +558,6 @@ void Tracer::traceThread() 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) { @@ -486,12 +567,12 @@ void Tracer::traceThread() } //## 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); - SP_DT_MSGSTACK(desktop)->flash(Inkscape::NORMAL_MESSAGE, msg); + msgStack->flash(Inkscape::NORMAL_MESSAGE, msg); g_free(msg); }