Added support for both linked and embedded images
This commit is contained in:
parent
807fa69a16
commit
ab5c2e54fc
@ -31,17 +31,13 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import base64
|
import base64
|
||||||
from io import StringIO, BytesIO
|
from io import StringIO, BytesIO
|
||||||
import urllib.parse
|
import urllib.request as urllib
|
||||||
import urllib.request
|
|
||||||
import inkex
|
import inkex
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
|
||||||
inkex.localization.localize
|
|
||||||
|
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
|
|
||||||
|
|
||||||
# int r = ( hexcolor >> 16 ) & 0xFF;
|
# int r = ( hexcolor >> 16 ) & 0xFF;
|
||||||
# int g = ( hexcolor >> 8 ) & 0xFF;
|
# int g = ( hexcolor >> 8 ) & 0xFF;
|
||||||
# int b = hexcolor & 0xFF;
|
# int b = hexcolor & 0xFF;
|
||||||
@ -53,7 +49,6 @@ def hex_to_int_color(v):
|
|||||||
assert(len(v) == 6)
|
assert(len(v) == 6)
|
||||||
return int(v[:2], 16), int(v[2:4], 16), int(v[4:6], 16)
|
return int(v[:2], 16), int(v[2:4], 16), int(v[4:6], 16)
|
||||||
|
|
||||||
|
|
||||||
class Pixel2SVG(inkex.Effect):
|
class Pixel2SVG(inkex.Effect):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
inkex.Effect.__init__(self)
|
inkex.Effect.__init__(self)
|
||||||
@ -69,55 +64,30 @@ class Pixel2SVG(inkex.Effect):
|
|||||||
self.arg_parser.add_argument("--color", default="FFFFFF", help="Special color")
|
self.arg_parser.add_argument("--color", default="FFFFFF", help="Special color")
|
||||||
self.arg_parser.add_argument("--tab")
|
self.arg_parser.add_argument("--tab")
|
||||||
|
|
||||||
def getImagePath(self, node, xlink):
|
def checkImagePath(self, node):
|
||||||
"""
|
"""Embed the data of the selected Image Tag element"""
|
||||||
Find image file, return path
|
xlink = node.get('xlink:href')
|
||||||
"""
|
if xlink and xlink[:5] == 'data:':
|
||||||
absref = node.get(inkex.addNS('absref', 'sodipodi'))
|
# No need, data alread embedded
|
||||||
url = urlparse(xlink)
|
return
|
||||||
href = urllib.request.url2pathname
|
|
||||||
|
|
||||||
path = ''
|
url = urllib.urlparse(xlink)
|
||||||
#path selection strategy:
|
href = urllib.url2pathname(url.path)
|
||||||
# 1. href if absolute
|
|
||||||
# 2. realpath-ified href
|
|
||||||
# 3. absref, only if the above does not point to a file
|
|
||||||
if href is not None:
|
|
||||||
path = os.path.realpath(href)
|
|
||||||
if (not os.path.isfile(path)):
|
|
||||||
if absref is not None:
|
|
||||||
path = absref
|
|
||||||
|
|
||||||
try:
|
# Primary location always the filename itself.
|
||||||
path = unicode(path, "utf-8")
|
path = self.absolute_href(href or '')
|
||||||
except TypeError:
|
|
||||||
path = path
|
|
||||||
|
|
||||||
if (not os.path.isfile(path)):
|
# Backup directory where we can find the image
|
||||||
inkex.errormsg(_(
|
if not os.path.isfile(path):
|
||||||
"No xlink:href or sodipodi:absref attributes found, " +
|
path = node.get('sodipodi:absref', path)
|
||||||
"or they do not point to an existing file! Unable to find image file."))
|
|
||||||
if path:
|
if not os.path.isfile(path):
|
||||||
inkex.errormsg(_("Sorry we could not locate %s") % str(path))
|
inkex.errormsg('File not found "{}". Unable to embed image.').format(path)
|
||||||
return False
|
return
|
||||||
|
|
||||||
if (os.path.isfile(path)):
|
if (os.path.isfile(path)):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def getImageData(self, xlink):
|
|
||||||
"""
|
|
||||||
Read, decode and return data of embedded image
|
|
||||||
"""
|
|
||||||
comma = xlink.find(',')
|
|
||||||
data = ''
|
|
||||||
|
|
||||||
if comma > 0:
|
|
||||||
data = base64.decodebytes(xlink[comma:].encode('UTF-8'))
|
|
||||||
else:
|
|
||||||
inkex.errormsg(_("Failed to read embedded image data."))
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
def getImage(self, node):
|
def getImage(self, node):
|
||||||
image_element=self.svg.find('.//{http://www.w3.org/2000/svg}image')
|
image_element=self.svg.find('.//{http://www.w3.org/2000/svg}image')
|
||||||
image_string=image_element.get('{http://www.w3.org/1999/xlink}href')
|
image_string=image_element.get('{http://www.w3.org/1999/xlink}href')
|
||||||
@ -170,7 +140,18 @@ class Pixel2SVG(inkex.Effect):
|
|||||||
Parse RGBA values of linked bitmap image, create a group and
|
Parse RGBA values of linked bitmap image, create a group and
|
||||||
draw the rectangles (SVG pixels) inside the new group
|
draw the rectangles (SVG pixels) inside the new group
|
||||||
"""
|
"""
|
||||||
image = self.getImage(node)
|
self.path = self.checkImagePath(node) # This also ensures the file exists
|
||||||
|
if self.path is None: # check if image is embedded or linked
|
||||||
|
image_string = node.get('{http://www.w3.org/1999/xlink}href')
|
||||||
|
# find comma position
|
||||||
|
i = 0
|
||||||
|
while i < 40:
|
||||||
|
if image_string[i] == ',':
|
||||||
|
break
|
||||||
|
i = i + 1
|
||||||
|
image = Image.open(BytesIO(base64.b64decode(image_string[i + 1:len(image_string)])))
|
||||||
|
else:
|
||||||
|
image = Image.open(self.path)
|
||||||
|
|
||||||
if image:
|
if image:
|
||||||
# init, set limit (default: 256)
|
# init, set limit (default: 256)
|
||||||
@ -281,10 +262,10 @@ class Pixel2SVG(inkex.Effect):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
# bail out with larger images
|
# bail out with larger images
|
||||||
inkex.errormsg(_(
|
inkex.errormsg(
|
||||||
"Bailing out: this extension is not intended for large images.\n" +
|
"Bailing out: this extension is not intended for large images.\n" +
|
||||||
"The current limit is %spx for either dimension of the bitmap image."
|
"The current limit is %spx for either dimension of the bitmap image."
|
||||||
% pixel2svg_max))
|
% pixel2svg_max)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# clean-up?
|
# clean-up?
|
||||||
@ -292,7 +273,7 @@ class Pixel2SVG(inkex.Effect):
|
|||||||
inkex.utils.debug("Done.")
|
inkex.utils.debug("Done.")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
inkex.errormsg(_("Bailing out: No supported image file or data found"))
|
inkex.errormsg("Bailing out: No supported image file or data found")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def effect(self):
|
def effect(self):
|
||||||
@ -307,8 +288,7 @@ class Pixel2SVG(inkex.Effect):
|
|||||||
self.vectorizeImage(node)
|
self.vectorizeImage(node)
|
||||||
|
|
||||||
if not found_image:
|
if not found_image:
|
||||||
inkex.errormsg(_("Please select one or more bitmap image(s) for Pixel2SVG"))
|
inkex.errormsg("Please select one or more bitmap image(s) for Pixel2SVG")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
Pixel2SVG().run()
|
||||||
Pixel2SVG().run()
|
|
Reference in New Issue
Block a user