diff options
| author | Nicolas Dufour <nicoduf@yahoo.fr> | 2011-08-18 21:29:26 +0000 |
|---|---|---|
| committer | JazzyNico <nicoduf@yahoo.fr> | 2011-08-18 21:29:26 +0000 |
| commit | 003fc530c79f74f54e93ade3207b9b2c2d8b4c4e (patch) | |
| tree | d85cb7c502c92bba39339fff9ea6e04d9d2e8b7b /src/extension/internal/bitmap | |
| parent | default to slightly friendlier grid color like the one from 0.45 :) (diff) | |
| download | inkscape-003fc530c79f74f54e93ade3207b9b2c2d8b4c4e.tar.gz inkscape-003fc530c79f74f54e93ade3207b9b2c2d8b4c4e.zip | |
Extensions. New Crop bitmap extension (see Bug #517082, Request Crop Image).
(bzr r10554)
Diffstat (limited to 'src/extension/internal/bitmap')
| -rw-r--r-- | src/extension/internal/bitmap/crop.cpp | 84 | ||||
| -rw-r--r-- | src/extension/internal/bitmap/crop.h | 34 | ||||
| -rw-r--r-- | src/extension/internal/bitmap/imagemagick.cpp | 298 | ||||
| -rw-r--r-- | src/extension/internal/bitmap/imagemagick.h | 1 |
4 files changed, 273 insertions, 144 deletions
diff --git a/src/extension/internal/bitmap/crop.cpp b/src/extension/internal/bitmap/crop.cpp new file mode 100644 index 000000000..23e31b510 --- /dev/null +++ b/src/extension/internal/bitmap/crop.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2011 Authors: + * Nicolas Dufour <nicoduf@yahoo.fr> + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "2geom/transforms.h" +#include "extension/effect.h" +#include "extension/system.h" + +#include "crop.h" +#include "selection-chemistry.h" +#include "sp-item-transform.h" + +namespace Inkscape { +namespace Extension { +namespace Internal { +namespace Bitmap { + +void +Crop::applyEffect(Magick::Image *image) { + int width = image->baseColumns() - (_left + _right); + int height = image->baseRows() - (_top + _bottom); + if (width > 0 and height > 0) { + image->crop(Magick::Geometry(width, height, _left, _top, false, false)); + image->page("+0+0"); + } +} + +void +Crop::postEffect(Magick::Image *image, SPItem *item) { + + // Scale bbox + Geom::Scale scale (0,0); + scale = Geom::Scale(image->columns() / (double) image->baseColumns(), + image->rows() / (double) image->baseRows()); + sp_item_scale_rel (item, scale); + + // Translate proportionaly to the image/bbox ratio + Geom::OptRect bbox(item->getBboxDesktop()); + //g_warning("bbox. W:%f, H:%f, X:%f, Y:%f", bbox->dimensions()[Geom::X], bbox->dimensions()[Geom::Y], bbox->min()[Geom::X], bbox->min()[Geom::Y]); + + Geom::Translate translate (0,0); + translate = Geom::Translate(((_left - _right) / 2.0) * (bbox->dimensions()[Geom::X] / (double) image->columns()), + ((_bottom - _top) / 2.0) * (bbox->dimensions()[Geom::Y] / (double) image->rows())); + sp_item_move_rel(item, translate); +} + +void +Crop::refreshParameters(Inkscape::Extension::Effect *module) { + _top = module->get_param_int("top"); + _bottom = module->get_param_int("bottom"); + _left = module->get_param_int("left"); + _right = module->get_param_int("right"); +} + +#include "../clear-n_.h" + +void +Crop::init(void) +{ + Inkscape::Extension::build_from_mem( + "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n" + "<name>" N_("Crop") "</name>\n" + "<id>org.inkscape.effect.bitmap.crop</id>\n" + "<param name=\"top\" gui-text=\"" N_("Top (px):") "\" type=\"int\" min=\"0\" max=\"100000\">0</param>\n" + "<param name=\"bottom\" gui-text=\"" N_("Bottom (px):") "\" type=\"int\" min=\"0\" max=\"100000\">0</param>\n" + "<param name=\"left\" gui-text=\"" N_("Left (px):") "\" type=\"int\" min=\"0\" max=\"100000\">0</param>\n" + "<param name=\"right\" gui-text=\"" N_("Right (px):") "\" type=\"int\" min=\"0\" max=\"100000\">0</param>\n" + "<effect>\n" + "<object-type>all</object-type>\n" + "<effects-menu>\n" + "<submenu name=\"" N_("Raster") "\" />\n" + "</effects-menu>\n" + "<menu-tip>" N_("Crop selected bitmap(s).") "</menu-tip>\n" + "</effect>\n" + "</inkscape-extension>\n", new Crop()); +} + +}; /* namespace Bitmap */ +}; /* namespace Internal */ +}; /* namespace Extension */ +}; /* namespace Inkscape */ diff --git a/src/extension/internal/bitmap/crop.h b/src/extension/internal/bitmap/crop.h new file mode 100644 index 000000000..ce9b92797 --- /dev/null +++ b/src/extension/internal/bitmap/crop.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010 Authors: + * Christopher Brown <audiere@gmail.com> + * Ted Gould <ted@gould.cx> + * Nicolas Dufour <nicoduf@yahoo.fr> + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "imagemagick.h" + +namespace Inkscape { +namespace Extension { +namespace Internal { +namespace Bitmap { + +class Crop : public ImageMagick +{ +private: + int _top; + int _bottom; + int _left; + int _right; +public: + void applyEffect(Magick::Image *image); + void postEffect(Magick::Image *image, SPItem *item); + void refreshParameters(Inkscape::Extension::Effect *module); + static void init (void); +}; + +}; /* namespace Bitmap */ +}; /* namespace Internal */ +}; /* namespace Extension */ +}; /* namespace Inkscape */ diff --git a/src/extension/internal/bitmap/imagemagick.cpp b/src/extension/internal/bitmap/imagemagick.cpp index 65968bdc4..a5d27726f 100644 --- a/src/extension/internal/bitmap/imagemagick.cpp +++ b/src/extension/internal/bitmap/imagemagick.cpp @@ -34,182 +34,192 @@ namespace Internal { namespace Bitmap { class ImageMagickDocCache: public Inkscape::Extension::Implementation::ImplementationDocumentCache { - friend class ImageMagick; + friend class ImageMagick; private: - void readImage(char const *xlink, Magick::Image *image); + void readImage(char const *xlink, Magick::Image *image); protected: - Inkscape::XML::Node** _nodes; - - Magick::Image** _images; - int _imageCount; - char** _caches; - unsigned* _cacheLengths; - - const char** _originals; + Inkscape::XML::Node** _nodes; + + Magick::Image** _images; + int _imageCount; + char** _caches; + unsigned* _cacheLengths; + const char** _originals; + SPItem** _imageItems; public: - ImageMagickDocCache(Inkscape::UI::View::View * view); - ~ImageMagickDocCache ( ); + ImageMagickDocCache(Inkscape::UI::View::View * view); + ~ImageMagickDocCache ( ); }; ImageMagickDocCache::ImageMagickDocCache(Inkscape::UI::View::View * view) : - Inkscape::Extension::Implementation::ImplementationDocumentCache(view), - _nodes(NULL), - _images(NULL), - _imageCount(0), - _caches(NULL), - _cacheLengths(NULL), - _originals(NULL) + Inkscape::Extension::Implementation::ImplementationDocumentCache(view), + _nodes(NULL), + _images(NULL), + _imageCount(0), + _caches(NULL), + _cacheLengths(NULL), + _originals(NULL), + _imageItems(NULL) { - SPDesktop *desktop = (SPDesktop*)view; - const GSList *selectedReprList = desktop->selection->reprList(); - int selectCount = g_slist_length((GSList *)selectedReprList); - - // Init the data-holders - _nodes = new Inkscape::XML::Node*[selectCount]; - _originals = new const char*[selectCount]; - _caches = new char*[selectCount]; - _cacheLengths = new unsigned int[selectCount]; - _images = new Magick::Image*[selectCount]; - _imageCount = 0; - - // Loop through selected nodes - for (; selectedReprList != NULL; selectedReprList = g_slist_next(selectedReprList)) - { - Inkscape::XML::Node *node = reinterpret_cast<Inkscape::XML::Node *>(selectedReprList->data); - if (!strcmp(node->name(), "image") || !strcmp(node->name(), "svg:image")) - { - _nodes[_imageCount] = node; - char const *xlink = node->attribute("xlink:href"); - - _originals[_imageCount] = xlink; - _caches[_imageCount] = ""; - _cacheLengths[_imageCount] = 0; - _images[_imageCount] = new Magick::Image(); - readImage(xlink, _images[_imageCount]); - - _imageCount++; - } - } + SPDesktop *desktop = (SPDesktop*)view; + const GSList *selectedItemList = desktop->selection->itemList(); + int selectCount = g_slist_length((GSList *)selectedItemList); + + // Init the data-holders + _nodes = new Inkscape::XML::Node*[selectCount]; + _originals = new const char*[selectCount]; + _caches = new char*[selectCount]; + _cacheLengths = new unsigned int[selectCount]; + _images = new Magick::Image*[selectCount]; + _imageCount = 0; + _imageItems = new SPItem*[selectCount]; + + // Loop through selected items + for (; selectedItemList != NULL; selectedItemList = g_slist_next(selectedItemList)) + { + SPItem *item = SP_ITEM(selectedItemList->data); + Inkscape::XML::Node *node = reinterpret_cast<Inkscape::XML::Node *>(item->getRepr()); + if (!strcmp(node->name(), "image") || !strcmp(node->name(), "svg:image")) + { + _nodes[_imageCount] = node; + char const *xlink = node->attribute("xlink:href"); + _originals[_imageCount] = xlink; + _caches[_imageCount] = (char*)""; + _cacheLengths[_imageCount] = 0; + _images[_imageCount] = new Magick::Image(); + readImage(xlink, _images[_imageCount]); + _imageItems[_imageCount] = item; + _imageCount++; + } + } } ImageMagickDocCache::~ImageMagickDocCache ( ) { - if (_nodes) - delete _nodes; - if (_originals) - delete _originals; - if (_caches) - delete _caches; - if (_cacheLengths) - delete _cacheLengths; - if (_images) - delete _images; - - return; + if (_nodes) + delete _nodes; + if (_originals) + delete _originals; + if (_caches) + delete _caches; + if (_cacheLengths) + delete _cacheLengths; + if (_images) + delete _images; + if (_imageItems) + delete _imageItems; + return; } void ImageMagickDocCache::readImage(const char *xlink, Magick::Image *image) { - // Find if the xlink:href is base64 data, i.e. if the image is embedded - char *search = (char *) g_strndup(xlink, 30); - if (strstr(search, "base64") != (char*)NULL) { - // 7 = strlen("base64") + strlen(",") - const char* pureBase64 = strstr(xlink, "base64") + 7; - Magick::Blob blob; - blob.base64(pureBase64); - image->read(blob); - } - else { - const gchar *path = xlink; + // Find if the xlink:href is base64 data, i.e. if the image is embedded + char *search = (char *) g_strndup(xlink, 30); + if (strstr(search, "base64") != (char*)NULL) { + // 7 = strlen("base64") + strlen(",") + const char* pureBase64 = strstr(xlink, "base64") + 7; + Magick::Blob blob; + blob.base64(pureBase64); + image->read(blob); + } + else { + const gchar *path = xlink; if (strncmp (xlink,"file:", 5) == 0) { path = g_filename_from_uri(xlink, NULL, NULL); - } + } - try { - image->read(path); - } catch (...) {} - } - g_free(search); + try { + image->read(path); + } catch (...) {} + } + g_free(search); } bool ImageMagick::load(Inkscape::Extension::Extension */*module*/) { - return true; + return true; } Inkscape::Extension::Implementation::ImplementationDocumentCache * ImageMagick::newDocCache (Inkscape::Extension::Extension * /*ext*/, Inkscape::UI::View::View * view) { - return new ImageMagickDocCache(view); + return new ImageMagickDocCache(view); } void ImageMagick::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache) { - refreshParameters(module); - - if (docCache == NULL) { // should never happen - docCache = newDocCache(module, document); - } - ImageMagickDocCache * dc = dynamic_cast<ImageMagickDocCache *>(docCache); - if (dc == NULL) { // should really never happen - printf("AHHHHHHHHH!!!!!"); - exit(1); - } - - for (int i = 0; i < dc->_imageCount; i++) - { - try - { - Magick::Image effectedImage = *dc->_images[i]; // make a copy - applyEffect(&effectedImage); - - Magick::Blob *blob = new Magick::Blob(); - effectedImage.write(blob); - - std::string raw_string = blob->base64(); - const int raw_len = raw_string.length(); - const char *raw_i = raw_string.c_str(); - - unsigned new_len = (int)(raw_len * (77.0 / 76.0) + 100); - if (new_len > dc->_cacheLengths[i]) { - dc->_cacheLengths[i] = (int)(new_len * 1.2); - dc->_caches[i] = new char[dc->_cacheLengths[i]]; - } - char *formatted_i = dc->_caches[i]; - const char *src; - - for (src = "data:image/"; *src; ) - *formatted_i++ = *src++; - for (src = effectedImage.magick().c_str(); *src ; ) - *formatted_i++ = *src++; - for (src = ";base64, \n" ; *src; ) - *formatted_i++ = *src++; - - int col = 0; - while (*raw_i) { - *formatted_i++ = *raw_i++; - if (col++ > 76) { - *formatted_i++ = '\n'; - col = 0; - } - } - if (col) { - *formatted_i++ = '\n'; - } - *formatted_i = '\0'; - - dc->_nodes[i]->setAttribute("xlink:href", dc->_caches[i], true); - dc->_nodes[i]->setAttribute("sodipodi:absref", NULL, true); - } - catch (Magick::Exception &error_) { - printf("Caught exception: %s \n", error_.what()); - } - - //while(Gtk::Main::events_pending()) { - // Gtk::Main::iteration(); - //} - } + refreshParameters(module); + + if (docCache == NULL) { // should never happen + docCache = newDocCache(module, document); + } + ImageMagickDocCache * dc = dynamic_cast<ImageMagickDocCache *>(docCache); + if (dc == NULL) { // should really never happen + printf("AHHHHHHHHH!!!!!"); + exit(1); + } + + for (int i = 0; i < dc->_imageCount; i++) + { + try + { + Magick::Image effectedImage = *dc->_images[i]; // make a copy + + applyEffect(&effectedImage); + + // postEffect can be used to change things on the item itself + // e.g. resize the image element, after the effecti is applied + postEffect(&effectedImage, dc->_imageItems[i]); + +// dc->_nodes[i]->setAttribute("xlink:href", dc->_caches[i], true); + + Magick::Blob *blob = new Magick::Blob(); + effectedImage.write(blob); + + std::string raw_string = blob->base64(); + const int raw_len = raw_string.length(); + const char *raw_i = raw_string.c_str(); + + unsigned new_len = (int)(raw_len * (77.0 / 76.0) + 100); + if (new_len > dc->_cacheLengths[i]) { + dc->_cacheLengths[i] = (int)(new_len * 1.2); + dc->_caches[i] = new char[dc->_cacheLengths[i]]; + } + char *formatted_i = dc->_caches[i]; + const char *src; + + for (src = "data:image/"; *src; ) + *formatted_i++ = *src++; + for (src = effectedImage.magick().c_str(); *src ; ) + *formatted_i++ = *src++; + for (src = ";base64, \n" ; *src; ) + *formatted_i++ = *src++; + + int col = 0; + while (*raw_i) { + *formatted_i++ = *raw_i++; + if (col++ > 76) { + *formatted_i++ = '\n'; + col = 0; + } + } + if (col) { + *formatted_i++ = '\n'; + } + *formatted_i = '\0'; + + dc->_nodes[i]->setAttribute("xlink:href", dc->_caches[i], true); + dc->_nodes[i]->setAttribute("sodipodi:absref", NULL, true); + } + catch (Magick::Exception &error_) { + printf("Caught exception: %s \n", error_.what()); + } + + //while(Gtk::Main::events_pending()) { + // Gtk::Main::iteration(); + //} + } } /** \brief A function to get the prefences for the grid diff --git a/src/extension/internal/bitmap/imagemagick.h b/src/extension/internal/bitmap/imagemagick.h index 5b4a1eb21..1b150fc3d 100644 --- a/src/extension/internal/bitmap/imagemagick.h +++ b/src/extension/internal/bitmap/imagemagick.h @@ -23,6 +23,7 @@ public: /* Functions to be implemented by subclasses */ virtual void applyEffect(Magick::Image */*image*/) { }; virtual void refreshParameters(Inkscape::Extension::Effect */*module*/) { }; + virtual void postEffect(Magick::Image */*image*/, SPItem */*item*/) { }; /* Functions implemented from ::Implementation */ bool load(Inkscape::Extension::Extension *module); |
