diff options
Diffstat (limited to '')
-rwxr-xr-x | share/extensions/image_embed.py | 147 |
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() |