diff options
Diffstat (limited to 'share/extensions/extractimage.py')
-rwxr-xr-x | share/extensions/extractimage.py | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/share/extensions/extractimage.py b/share/extensions/extractimage.py new file mode 100755 index 0000000..810c6f4 --- /dev/null +++ b/share/extensions/extractimage.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# coding=utf-8 +# +# Copyright (C) 2005 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. +# +""" +Extract embedded images. +""" + +import os +import inkex +from inkex import Image + +try: + from base64 import decodebytes +except ImportError: + from base64 import decodestring as decodebytes + +class ExtractImage(inkex.EffectExtension): + """Extract images and save to filenames""" + def add_arguments(self, pars): + pars.add_argument("-s", "--selectedonly", type=inkex.Boolean,\ + help="Extract only selected images", default=True) + pars.add_argument("--filepath", default='.',\ + help="Location to save the images.") + + def effect(self): + elems = self.svg.selection.filter(Image).values() \ + if self.options.selectedonly else self.svg.xpath('//svg:image') + + for elem in elems: + self.extract_image(elem) + + @staticmethod + def mime_to_ext(mime): + """Return an extension based on the mime type""" + # Most extensions are automatic (i.e. extension is same as minor part of mime type) + part = mime.split('/', 1)[1].split('+')[0] + return '.' + { + # These are the non-matching ones. + 'svg+xml' : '.svg', + 'jpeg' : '.jpg', + 'icon' : '.ico', + }.get(part, part) + + def extract_image(self, node): + """Extract the node as if it were an image.""" + xlink = node.get('xlink:href') + if not xlink.startswith('data:'): + return # Not embedded image data + + save_to = self.absolute_href(self.options.filepath) + # Make the target directory if it doesn't exist yet. + if not os.path.isdir(save_to): + os.makedirs(save_to) + + try: + data = xlink[5:] + (mimetype, data) = data.split(';', 1) + (base, data) = data.split(',', 1) + except ValueError: + inkex.errormsg("Invalid image format found") + return + + if base != 'base64': + inkex.errormsg("Can't decode encoding: {}".format(base)) + return + + file_ext = self.mime_to_ext(mimetype) + + pathwext = os.path.join(save_to, node.get("id") + file_ext) + if os.path.isfile(pathwext): + inkex.errormsg("Can't extract image, filename already used: {}".format(pathwext)) + return + + self.msg('Image extracted to: {}'.format(pathwext)) + + with open(pathwext, 'wb') as fhl: + fhl.write(decodebytes(data.encode('utf-8'))) + + # absolute for making in-mem cycles work + node.set('xlink:href', os.path.realpath(pathwext)) + +if __name__ == '__main__': + ExtractImage().run() |