summaryrefslogtreecommitdiffstats
path: root/src/extension/internal/bitmap
diff options
context:
space:
mode:
authorNicolas Dufour <nicoduf@yahoo.fr>2011-08-18 21:29:26 +0000
committerJazzyNico <nicoduf@yahoo.fr>2011-08-18 21:29:26 +0000
commit003fc530c79f74f54e93ade3207b9b2c2d8b4c4e (patch)
treed85cb7c502c92bba39339fff9ea6e04d9d2e8b7b /src/extension/internal/bitmap
parentdefault to slightly friendlier grid color like the one from 0.45 :) (diff)
downloadinkscape-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.cpp84
-rw-r--r--src/extension/internal/bitmap/crop.h34
-rw-r--r--src/extension/internal/bitmap/imagemagick.cpp298
-rw-r--r--src/extension/internal/bitmap/imagemagick.h1
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);