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 <gtkmm/box.h>
12 #include <gtkmm/adjustment.h>
13 #include <gtkmm/spinbutton.h>
15 #include <glib/gstdio.h>
17 #include "desktop.h"
18 #include "desktop-handles.h"
19 #include "selection.h"
20 #include "sp-object.h"
21 #include "util/glib-list-iterators.h"
23 #include "extension/effect.h"
24 #include "extension/system.h"
26 #include "imagemagick.h"
28 namespace Inkscape {
29 namespace Extension {
30 namespace Internal {
31 namespace Bitmap {
33 bool
34 ImageMagick::load(Inkscape::Extension::Extension *module)
35 {
36 _loaded = FALSE;
37 return TRUE;
38 }
40 void
41 ImageMagick::commitDocument(void) {
42 _loaded = FALSE;
43 }
45 void
46 ImageMagick::cancelDocument(void) {
47 for (int i = 0; i < _imageCount; i++) {
48 _nodes[i]->setAttribute("xlink:href", _originals[i], true);
49 }
51 _loaded = FALSE;
52 }
54 void
55 ImageMagick::readImage(const char *xlink, Magick::Image *image)
56 {
57 // Find if the xlink:href is base64 data, i.e. if the image is embedded
58 char *search = (char *) g_strndup(xlink, 30);
59 if (strstr(search, "base64") != (char*)NULL) {
60 // 7 = strlen("base64") + strlen(",")
61 char* pureBase64 = strstr(xlink, "base64") + 7;
62 Magick::Blob blob;
63 blob.base64(pureBase64);
64 image->read(blob);
65 }
66 else {
67 image->read(xlink);
68 }
69 }
71 void
72 ImageMagick::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document)
73 {
74 refreshParameters(module);
76 if (!_loaded)
77 {
78 SPDesktop *desktop = (SPDesktop*)document;
79 const GSList *selectedReprList = desktop->selection->reprList();
80 int selectCount = g_slist_length((GSList *)selectedReprList);
82 // Init the data-holders
83 _nodes = new Inkscape::XML::Node*[selectCount];
84 _originals = new const char*[selectCount];
85 _images = new Magick::Image[selectCount];
86 _imageCount = 0;
88 // Loop through selected nodes
89 for (; selectedReprList != NULL; selectedReprList = g_slist_next(selectedReprList))
90 {
91 Inkscape::XML::Node *node = reinterpret_cast<Inkscape::XML::Node *>(selectedReprList->data);
92 if (!strcmp(node->name(), "image") || !strcmp(node->name(), "svg:image"))
93 {
94 _nodes[_imageCount] = node;
95 char const *xlink = node->attribute("xlink:href");
97 _originals[_imageCount] = xlink;
99 readImage(xlink, &_images[_imageCount]);
101 _imageCount++;
102 }
103 }
105 _loaded = 1;
106 }
108 for (int i = 0; i < _imageCount; i++)
109 {
110 try
111 {
112 Magick::Image effectedImage = _images[i];
113 applyEffect(&effectedImage);
115 Magick::Blob blob;
116 effectedImage.write(&blob);
118 std::string raw_string = blob.base64();
119 const char *raw = raw_string.c_str();
121 /*
122 const int raw_len = raw_string.length();
123 const char *raw_i = raw;
124 int formatted_len = (int)(raw_len / 76.0 * 78.0) + 100;
125 char *formatted = new char[formatted_len];
126 char *formatted_i = formatted;
127 // data:image/png;base64,
128 formatted_i = stpcpy(formatted_i, "data:image/");
129 formatted_i = stpcpy(formatted_i, effectedImage.magick().c_str());
130 formatted_i = stpcpy(formatted_i, ";base64, \n");
131 while (strnlen(raw_i, 80) > 76)
132 {
133 formatted_i = stpncpy(formatted_i, raw_i, 76);
134 formatted_i = stpcpy(formatted_i, "\n");
135 raw_i += 76;
136 }
137 if (strlen(raw_i) > 0)
138 {
139 formatted_i = stpcpy(formatted_i, raw_i);
140 formatted_i = stpcpy(formatted_i, "\n");
141 }
143 formatted_i = stpcpy(formatted_i, "\0");
145 _nodes[i]->setAttribute("xlink:href", formatted, true);
146 */
148 Glib::ustring buf = "data:image/";
149 buf.append(effectedImage.magick());
150 buf.append(";base64, \n");
151 int col = 0;
152 while (*raw)
153 {
154 buf.push_back(*raw++);
155 if (col>=76)
156 {
157 buf.push_back('\n');
158 col = 0;
159 }
160 }
161 if (col)
162 buf.push_back('\n');
164 _nodes[i]->setAttribute("xlink:href", buf.c_str(), true);
165 }
166 catch (Magick::Exception &error_) {
167 printf("Caught exception: %s \n", error_.what());
168 }
169 }
170 }
172 /** \brief A function to get the prefences for the grid
173 \param moudule Module which holds the params
174 \param view Unused today - may get style information in the future.
176 Uses AutoGUI for creating the GUI.
177 */
178 Gtk::Widget *
179 ImageMagick::prefs_effect(Inkscape::Extension::Effect *module, Inkscape::UI::View::View * view, sigc::signal<void> * changeSignal)
180 {
181 SPDocument * current_document = view->doc();
183 using Inkscape::Util::GSListConstIterator;
184 GSListConstIterator<SPItem *> selected = sp_desktop_selection((SPDesktop *)view)->itemList();
185 Inkscape::XML::Node * first_select = NULL;
186 if (selected != NULL)
187 first_select = SP_OBJECT_REPR(*selected);
189 return module->autogui(current_document, first_select, changeSignal);
190 }
192 }; /* namespace Bitmap */
193 }; /* namespace Internal */
194 }; /* namespace Extension */
195 }; /* namespace Inkscape */