first comit
This commit is contained in:
83
venv/lib/python3.10/site-packages/jsignature/utils.py
Normal file
83
venv/lib/python3.10/site-packages/jsignature/utils.py
Normal file
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
Very inspired by zivezab's django-autograph
|
||||
https://github.com/zivezab/django-autograph/blob/master/autograph/utils.py
|
||||
"""
|
||||
import json
|
||||
from itertools import chain
|
||||
from PIL import Image, ImageDraw, ImageOps, __version__ as PIL_VERSION
|
||||
|
||||
AA = 5 # super sampling for antialiasing
|
||||
|
||||
|
||||
def draw_signature(data, as_file=False):
|
||||
"""Draw signature based on lines stored in json_string.
|
||||
`data` can be a json object (list in fact) or a json string
|
||||
if `as_file` is True, a temp file is returned instead of Image instance
|
||||
"""
|
||||
|
||||
def _remove_empty_pts(pt):
|
||||
return {
|
||||
"x": list(filter(lambda n: n is not None, pt["x"])),
|
||||
"y": list(filter(lambda n: n is not None, pt["y"])),
|
||||
}
|
||||
|
||||
if isinstance(data, str):
|
||||
drawing = json.loads(data, object_hook=_remove_empty_pts)
|
||||
elif isinstance(data, list):
|
||||
drawing = data
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
# Compute box
|
||||
padding = 10
|
||||
min_width = int(round(min(chain(*[d["x"] for d in drawing])))) - padding
|
||||
max_width = int(round(max(chain(*[d["x"] for d in drawing])))) + padding
|
||||
width = max_width - min_width
|
||||
min_height = int(round(min(chain(*[d["y"] for d in drawing])))) - padding
|
||||
max_height = int(round(max(chain(*[d["y"] for d in drawing])))) + padding
|
||||
height = max_height - min_height
|
||||
|
||||
# Draw image
|
||||
im = Image.new("RGBA", (width * AA, height * AA))
|
||||
draw = ImageDraw.Draw(im)
|
||||
for coords in drawing:
|
||||
line_length = len(coords["x"])
|
||||
if line_length == 1:
|
||||
# This is a single point, convert to a circle of 2x2 AA pixels
|
||||
draw.ellipse(
|
||||
[
|
||||
(
|
||||
(coords["x"][0] - min_width) * AA,
|
||||
(coords["y"][0] - min_height) * AA,
|
||||
),
|
||||
(
|
||||
(coords["x"][0] - min_width + 2) * AA,
|
||||
(coords["y"][0] - min_height + 2) * AA,
|
||||
),
|
||||
],
|
||||
fill="#000",
|
||||
)
|
||||
else:
|
||||
points = [
|
||||
((coords["x"][i] - min_width) * AA, (coords["y"][i] - min_height) * AA)
|
||||
for i in range(0, line_length)
|
||||
]
|
||||
draw.line(points, fill="#000", width=2 * AA)
|
||||
im = ImageOps.expand(im)
|
||||
# Smart crop
|
||||
bbox = im.getbbox()
|
||||
if bbox:
|
||||
im.crop(bbox)
|
||||
|
||||
im.thumbnail(
|
||||
(width, height),
|
||||
# Image.ANTIALIAS is replaced in PIL 10.0.0
|
||||
Image.ANTIALIAS if int(PIL_VERSION.split(".")[0]) < 10 else Image.LANCZOS,
|
||||
)
|
||||
|
||||
if as_file:
|
||||
ret = im._dump(format="PNG")
|
||||
else:
|
||||
ret = im
|
||||
|
||||
return ret
|
||||
Reference in New Issue
Block a user