summaryrefslogtreecommitdiffstats
path: root/share/extensions/image_embed.py
diff options
context:
space:
mode:
Diffstat (limited to 'share/extensions/image_embed.py')
-rwxr-xr-xshare/extensions/image_embed.py147
1 files changed, 147 insertions, 0 deletions
diff --git a/share/extensions/image_embed.py b/share/extensions/image_embed.py
new file mode 100755
index 0000000..e04bc85
--- /dev/null
+++ b/share/extensions/image_embed.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+# coding=utf-8
+#
+# Copyright (C) 2005,2007 Aaron Spike, aaron@ekips.org
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# pylint: disable=ungrouped-imports
+"""
+Embed images so they are base64 encoded data inside the svg.
+"""
+
+from __future__ import unicode_literals
+
+import os
+
+import inkex
+from inkex import Image
+from inkex.localization import inkex_gettext as _
+
+try:
+ import urllib.request as urllib
+ import urllib.parse as urlparse
+ from base64 import encodebytes
+except ImportError:
+ # python2 compatibility, remove when python3 only.
+ import urllib
+ import urlparse
+ from base64 import encodestring as encodebytes
+
+
+class EmbedImage(inkex.EffectExtension):
+ """Allow selected image tags to become embeded image tags"""
+
+ def add_arguments(self, pars):
+ pars.add_argument(
+ "--selectedonly", type=inkex.Boolean, help="embed only selected images"
+ )
+
+ def effect(self):
+ # if slectedonly is enabled and there is a selection
+ # only embed selected images. otherwise embed all images
+ if self.options.selectedonly:
+ images = self.svg.selection.get(Image)
+ else:
+ images = self.svg.xpath("//svg:image")
+
+ for node in images:
+ self.embed_image(node)
+
+ def embed_image(self, node):
+ """Embed the data of the selected Image Tag element"""
+ xlink = node.get("xlink:href")
+ if xlink is not None and xlink[:5] == "data:":
+ # No need, data already embedded
+ return
+ if xlink is None:
+ inkex.errormsg(
+ _('Attribute "xlink:href" not set on node {}.'.format(node.get_id()))
+ )
+ return
+
+ url = urlparse.urlparse(xlink)
+ href = urllib.url2pathname(url.path)
+
+ # Look relative to the *temporary* filename instead of the original filename.
+ try:
+ cwd = os.path.dirname(self.options.input_file)
+ except TypeError:
+ # input_file was actually stdin, fall back.
+ cwd = None
+
+ path = self.absolute_href(href or "", cwd=cwd)
+
+ # Backup directory where we can find the image
+ if not os.path.isfile(path):
+ path = node.get("sodipodi:absref", path)
+
+ if not os.path.isfile(path):
+ inkex.errormsg(
+ _('File not found "{}". Unable to embed image.').format(path)
+ )
+ return
+
+ with open(path, "rb") as handle:
+ # Don't read the whole file to check the header
+ file_type = get_type(path, handle.read(10))
+ handle.seek(0)
+
+ if file_type:
+ # Future: Change encodestring to encodebytes when python3 only
+ node.set(
+ "xlink:href",
+ "data:{};base64,{}".format(
+ file_type, encodebytes(handle.read()).decode("ascii")
+ ),
+ )
+ node.pop("sodipodi:absref")
+ else:
+ inkex.errormsg(
+ _(
+ "%s is not of type image/png, image/jpeg, "
+ "image/bmp, image/gif, image/tiff, or image/x-icon"
+ )
+ % path
+ )
+
+
+def get_type(path, header):
+ """Basic magic header checker, returns mime type"""
+ for head, mime in (
+ (b"\x89PNG", "image/png"),
+ (b"\xff\xd8", "image/jpeg"),
+ (b"BM", "image/bmp"),
+ (b"GIF87a", "image/gif"),
+ (b"GIF89a", "image/gif"),
+ (b"MM\x00\x2a", "image/tiff"),
+ (b"II\x2a\x00", "image/tiff"),
+ ):
+ if header.startswith(head):
+ return mime
+
+ # ico files lack any magic... therefore we check the filename instead
+ for ext, mime in (
+ # official IANA registered MIME is 'image/vnd.microsoft.icon' tho
+ (".ico", "image/x-icon"),
+ (".svg", "image/svg+xml"),
+ ):
+ if path.endswith(ext):
+ return mime
+ return None
+
+
+if __name__ == "__main__":
+ EmbedImage().run()