Skip to content

Commit

Permalink
.image() support bitmap images
Browse files Browse the repository at this point in the history
  • Loading branch information
spirali committed Jun 12, 2019
1 parent 0850855 commit 4a55057
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 17 deletions.
73 changes: 59 additions & 14 deletions elsie/box.py
@@ -1,8 +1,11 @@
import logging

import lxml.etree as et
import base64
from PIL import Image
import io

from .draw import draw_text
from .draw import draw_text, draw_bitmap
from .geom import Rect
from .highlight import highlight_code
from .image import get_image_steps, create_image_data
Expand Down Expand Up @@ -45,6 +48,19 @@ def set_paint_style(xml, color, bg_color, stroke_width, stroke_dasharray):
xml.set("style", ";".join(styles))


def scaler(rect, image_width, image_height):
scale_x = rect.width / image_width
scale_y = rect.height / image_height

if rect.width and rect.height:
return min(scale_x, scale_y)
elif rect.width:
return scale_x
elif rect.height:
return scale_y
return None


class Box:

def __init__(self,
Expand Down Expand Up @@ -268,6 +284,46 @@ def _render_svg(self, ctx, x, y, scale, data):
ctx.xml.close()

def image(self, filename, scale=None, fragments=True, show_begin=1):
""" Draw an svg/png/jpeg image, detect by extension """
if filename.endswith("svg"):
self.image_svg(filename, scale, fragments, show_begin)
elif any(filename.endswith(ext) for ext in [".png", ".jpeg", ".jpg"]):
self._image_bitmap(filename, scale)
else:
raise Exception("Unkown image extension")
return self

def _image_bitmap(self, filename, scale):

with open(filename, "rb") as f:
data = f.read()

img = Image.open(io.BytesIO(data))
mime = Image.MIME[img.format]
image_width, image_height = img.size
del img

data = base64.b64encode(data).decode("ascii")

def draw(ctx, rect):
if scale is None:
s = scaler(rect, image_width, image_height)
if s is None:
logging.warning(
"Scale of image {} is 0, set scale explicitly or set at least one "
"dimension for the parent box".format(filename))
else:
s = scale

w = image_width * s
h = image_height * s
x = rect.x + (rect.width - w) / 2
y = rect.y + (rect.height - h) / 2
draw_bitmap(ctx.xml, x, y, w, h, mime, data)

self.add_child(draw)

def _image_svg(self, filename, scale=None, fragments=True, show_begin=1):
""" Draw an svg image """

root = et.parse(filename).getroot()
Expand Down Expand Up @@ -298,17 +354,8 @@ def draw(ctx, rect):
data = image_data

if scale is None:
scale_x = rect.width / image_width
scale_y = rect.height / image_height

s = 0
if rect.width and rect.height:
s = min(scale_x, scale_y)
elif rect.width:
s = scale_x
elif rect.height:
s = scale_y
else:
s = scaler(rect, image_width, image_height)
if s is None:
logging.warning(
"Scale of image {} is 0, set scale explicitly or set at least one "
"dimension for the parent box".format(filename))
Expand All @@ -323,8 +370,6 @@ def draw(ctx, rect):

self.add_child(draw)

return self

def code(self, language, text, tabsize=4, line_numbers=False, style="code"):
""" Draw a code with syntax highlighting """

Expand Down
10 changes: 10 additions & 0 deletions elsie/draw.py
Expand Up @@ -67,3 +67,13 @@ def draw_text(xml, x, y, parsed_text, style, styles, id=None):
for s in active_styles:
xml.close("tspan")
xml.close("text")


def draw_bitmap(xml, x, y, width, height, mime, data):
xml.element("image")
xml.set("x", x)
xml.set("y", y)
xml.set("width", width)
xml.set("height", height)
xml.set("xlink:href", "data:{};base64,{}".format(mime, data), escape=False)
xml.close("image")
2 changes: 1 addition & 1 deletion elsie/image.py
Expand Up @@ -36,4 +36,4 @@ def find_hidden_elements(element):
find_hidden_elements(root)
for element, child in hidden:
element.remove(child)
return et.tostring(root).decode()
return et.tostring(root).decode()
5 changes: 3 additions & 2 deletions elsie/sxml.py
Expand Up @@ -23,9 +23,10 @@ def element(self, name):
self.stack.append(name)
self.is_open = True

def set(self, name, value):
def set(self, name, value, escape=True):
assert self.is_open
value = str(value).replace("'", "\\'")
if escape:
value = str(value).replace("'", "\\'")
self.chunks.append(" {}='{}'".format(name, escape_text(value)))

def text(self, text):
Expand Down
Binary file added tests/data/imgs/test.jpeg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tests/data/imgs/test.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions tests/test_image.py
Expand Up @@ -65,3 +65,22 @@ def test_image_scale_width_height(test_env):
def test_image_scale_no_dimensions(test_env):
test_env.slide.box().image(test_env.data_path("scale.svg"))
test_env.check("scale-no-dimensions")

def test_image_bitmap(test_env):
slide = test_env.slide
img_png = test_env.data_path("imgs/test.png")
img_jpg = test_env.data_path("imgs/test.jpeg")

b = slide.fbox(height=140)
b.rect(bg_color="green")
b.image(img_png)

b = slide.fbox(height=300)
b.rect(bg_color="blue")
b.image(img_png)

b = slide.fbox(height=300)
b.rect(bg_color="green")
b.image(img_jpg)

test_env.check("image-bitmap", 1)

0 comments on commit 4a55057

Please sign in to comment.