Code

a6c30a587b6c1666d34d91fd64d340c348bbc76c
[inkscape.git] / src / extension / internal / bitmap / imagemagick.cpp
1 /*
2  * Authors:
3  *   Christopher Brown <audiere@gmail.com>
4  *   Ted Gould <ted@gould.cx>
5  *
6  * Copyright (C) 2007 Authors
7  *
8  * Released under GNU GPL, read the file 'COPYING' for more information
9  */
11 #include <libintl.h>
13 #include <gtkmm/box.h>
14 #include <gtkmm/adjustment.h>
15 #include <gtkmm/spinbutton.h>
16 #include <gtkmm.h>
18 #include <glib/gstdio.h>
20 #include "desktop.h"
21 #include "desktop-handles.h"
22 #include "selection.h"
23 #include "sp-object.h"
24 #include "util/glib-list-iterators.h"
26 #include "extension/effect.h"
27 #include "extension/system.h"
29 #include "imagemagick.h"
31 namespace Inkscape {
32 namespace Extension {
33 namespace Internal {
34 namespace Bitmap {
36 bool
37 ImageMagick::load(Inkscape::Extension::Extension *module)
38 {
39         _loaded = FALSE;
40         
41         return TRUE;
42 }
44 void
45 ImageMagick::commitDocument(void) {
46         _loaded = FALSE;
47 }
49 /*void
50 ImageMagick::cancelDocument(void) {     
51         for (int i = 0; i < _imageCount; i++) {
52                 _nodes[i]->setAttribute("xlink:href", _originals[i], true);
53                 
54                 if (strlen(_originals[i]) < 256)
55                         _nodes[i]->setAttribute("sodipodi:absref", _originals[i], true);
56         }
57         
58         _loaded = FALSE;
59 }*/
61 void
62 ImageMagick::readImage(const char *xlink, Magick::Image *image)
63 {
64         // Find if the xlink:href is base64 data, i.e. if the image is embedded 
65         char *search = (char *) g_strndup(xlink, 30);
66         if (strstr(search, "base64") != (char*)NULL) {
67                 // 7 = strlen("base64") + strlen(",")
68                 char* pureBase64 = strstr(xlink, "base64") + 7;         
69                 Magick::Blob blob;
70                 blob.base64(pureBase64);
71                 image->read(blob);
72         }
73         else {
74                 image->read(xlink);
75         }
76 }
78 void
79 ImageMagick::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document)
80 {
81         refreshParameters(module);
82         
83         if (!_loaded)
84         {
85                 SPDesktop *desktop = (SPDesktop*)document;
86                 const GSList *selectedReprList = desktop->selection->reprList();
87                 int selectCount = g_slist_length((GSList *)selectedReprList);
89                 // Init the data-holders
90                 _nodes = new Inkscape::XML::Node*[selectCount];
91                 _originals = new const char*[selectCount];
92                 _caches = new char*[selectCount];
93                 _cacheLengths = new unsigned[selectCount];
94                 _images = new Magick::Image*[selectCount];
95                 _imageCount = 0;
97                 // Loop through selected nodes
98                 for (; selectedReprList != NULL; selectedReprList = g_slist_next(selectedReprList))
99                 {
100                         Inkscape::XML::Node *node = reinterpret_cast<Inkscape::XML::Node *>(selectedReprList->data);
101                         if (!strcmp(node->name(), "image") || !strcmp(node->name(), "svg:image"))
102                         {
103                                 _nodes[_imageCount] = node;     
104                                 char const *xlink = node->attribute("xlink:href");
106                                 _originals[_imageCount] = xlink;
107                                 _caches[_imageCount] = "";
108                                 _cacheLengths[_imageCount] = 0;
109                                 _images[_imageCount] = new Magick::Image();
110                                 readImage(xlink, _images[_imageCount]);                 
112                                 _imageCount++;
113                         }                       
114                 }
116                 _loaded = 1;
117         }
119         for (int i = 0; i < _imageCount; i++)
120         {
121                 try
122                 {
123                         Magick::Image effectedImage = *_images[i]; // make a copy
124                         applyEffect(&effectedImage);
126                         Magick::Blob *blob = new Magick::Blob();
127                         effectedImage.write(blob);
129                         std::string raw_string = blob->base64();
130                         const int raw_len = raw_string.length();
131                         const char *raw_i = raw_string.c_str();
133                         unsigned new_len = (int)(raw_len * (77.0 / 76.0) + 100);
134                         if (new_len > _cacheLengths[i]) {
135                                 _cacheLengths[i] = (int)(new_len * 1.2);
136                                 _caches[i] = new char[_cacheLengths[i]];
137                         }
138                         char *formatted_i = _caches[i];
139                         const char *src;
141                         for (src = "data:image/"; *src; )
142                                 *formatted_i++ = *src++;
143                         for (src = effectedImage.magick().c_str(); *src ; )
144                                 *formatted_i++ = *src++;
145                         for (src = ";base64, \n" ; *src; )
146                                 *formatted_i++ = *src++;
148                         int col = 0;
149                         while (*raw_i) {
150                            *formatted_i++ = *raw_i++;
151                            if (col++ > 76) {
152                                    *formatted_i++ = '\n';
153                                    col = 0;
154                            }
155                         }                       
156                         if (col) {
157                            *formatted_i++ = '\n';
158                         }
159                         *formatted_i = '\0';
161                         _nodes[i]->setAttribute("xlink:href", _caches[i], true);                        
162                         _nodes[i]->setAttribute("sodipodi:absref", NULL, true);
163                 }
164                 catch (Magick::Exception &error_) {
165                         printf("Caught exception: %s \n", error_.what());
166                 }
168                 while(Gtk::Main::events_pending())
169                         Gtk::Main::iteration();
170         }
173 /** \brief  A function to get the prefences for the grid
174     \param  moudule  Module which holds the params
175     \param  view     Unused today - may get style information in the future.
177     Uses AutoGUI for creating the GUI.
178 */
179 Gtk::Widget *
180 ImageMagick::prefs_effect(Inkscape::Extension::Effect *module, Inkscape::UI::View::View * view, sigc::signal<void> * changeSignal)
182     SPDocument * current_document = view->doc();
184     using Inkscape::Util::GSListConstIterator;
185     GSListConstIterator<SPItem *> selected = sp_desktop_selection((SPDesktop *)view)->itemList();
186     Inkscape::XML::Node * first_select = NULL;
187     if (selected != NULL) 
188         first_select = SP_OBJECT_REPR(*selected);
190     return module->autogui(current_document, first_select, changeSignal);
193 }; /* namespace Bitmap */
194 }; /* namespace Internal */
195 }; /* namespace Extension */
196 }; /* namespace Inkscape */