147 lines
4.6 KiB
Python
Executable file
147 lines
4.6 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
# 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()
|