# -*- coding: utf-8 -*-
import tempfile
from dp_tornado.engine.helper import Helper as dpHelper
[docs]class ImageHelper(dpHelper):
[docs] def compare(self, i1, i2, error=0):
i1 = self.load(i1)
i2 = self.load(i2)
if not i1 or not i2:
return None
s1 = i1.size
s2 = i2.size
if s1[0] != s2[0] or s2[1] != s2[1]:
print('size ne,', s1, s2)
return False
i1 = i1.load()
i2 = i2.load()
for i in range(s1[0]):
for j in range(s1[1]):
if i1[i, j] != i2[i, j]:
if error:
for k in range(len(i1[i, j])):
if abs(i1[i, j][k] - i2[i, j][k]) > error:
print('pixel ne,', i1[i, j], i2[i, j], abs(i1[i, j][k] - i2[i, j][k]), error)
return False
else:
return False
return True
def _driver(self, options=None, **kwargs):
if not options and kwargs:
options = kwargs
if options and 'driver' in options and options['driver'] == 'wand':
return self.helper.io.image.driver.wand
return self.helper.io.image.driver.pillow
[docs] def load(self, src, options=None, **kwargs):
if not options and kwargs:
options = kwargs
tmp = None
drivers = []
pillow_image = self.helper.io.image.driver.pillow.Image
wand_image = self.helper.io.image.driver.wand.Image
if pillow_image:
drivers.append(pillow_image)
if wand_image:
drivers.append(wand_image)
try:
if isinstance(src, tuple(drivers)):
return src
elif self.helper.web.url.validate(src):
code, res = self.helper.web.http.get.raw(src)
if code != 200:
raise Exception('The specified image url is invalid.')
tmp = tempfile.NamedTemporaryFile(delete=False)
tmp.write(res)
tmp.close()
tmp = tmp.name
else:
tmp = None
if not tmp and not src:
raise Exception('The specified image is invalid.')
img = self._driver(options=options).load(tmp if tmp else src)
if not img:
raise Exception('The specified image is invalid.')
return img
except Exception as e:
self.logging.exception(e)
return False
finally:
if tmp:
self.helper.io.file.remove(tmp)
[docs] def execute(self, src, fn, options=None, **kwargs):
if not options and kwargs:
options = kwargs
img = self.load(src, options=options)
if not img:
return False
try:
return fn(img, options)
except Exception as e:
self.logging.exception(e)
return False
[docs] def size(self, src, options=None, **o_kwargs):
if not options and o_kwargs:
options = o_kwargs
def fn(img, kwargs):
if not img:
return -1, -1
return img.width, img.height
return self.execute(src, fn, options=options)
[docs] def crop(self, src, options=None, **o_kwargs):
if not options and o_kwargs:
options = o_kwargs
def fn(img, kwargs):
crop = kwargs['crop'] if 'crop' in kwargs else None
if not crop:
return img
e_top = 0
e_left = 0
e_right = 0
e_bottom = 0
if self.helper.misc.type.check.string(crop):
crop = crop.split(',')
crop = [int(e.strip()) for e in crop]
if self.helper.misc.type.check.numeric(crop):
e_top = e_left = e_right = e_bottom = crop
elif isinstance(crop, (tuple, list)):
if len(crop) == 1:
e_top = e_left = e_right = e_bottom = crop[0]
elif len(crop) == 2:
e_top = e_bottom = crop[0]
e_left = e_right = crop[1]
elif len(crop) == 4:
e_top = crop[0]
e_right = crop[1]
e_bottom = crop[2]
e_left = crop[3]
img = self._driver(options=kwargs).crop(img, e_left, e_top, img.size[0] - e_right, img.size[1] - e_bottom)
return img
return self.execute(src, fn, options=options)
[docs] def border(self, src, options=None, **o_kwargs):
if not options and o_kwargs:
options = o_kwargs
def fn(img, kwargs):
border = int(kwargs['border']) if 'border' in kwargs else 0
border_color = kwargs['border_color'] if 'border_color' in kwargs else '#000000'
if not border:
return img
if '_org' in kwargs and 'radius' in kwargs and kwargs['radius']:
return img
img = self._driver(options=kwargs).border(img, border, border_color)
return img
return self.execute(src, fn, options=options)
[docs] def radius(self, src, options=None, **o_kwargs):
if not options and o_kwargs:
options = o_kwargs
def fn(img, kwargs):
radius = int(kwargs['radius'] or 0) if 'radius' in kwargs else None
border = int(kwargs['border']) if 'border' in kwargs else 0
border_color = kwargs['border_color'] if 'border_color' in kwargs else '#000000'
if not radius:
return img
elif '__radius_processed__' in img.__dict__:
return img
img = self._driver(options=kwargs).radius(img, radius, border, border_color)
img.__dict__['__radius_processed__'] = True
return img
return self.execute(src, fn, options=options)
[docs] def colorize(self, src, options=None, **o_kwargs):
if not options and o_kwargs:
options = o_kwargs
def fn(img, kwargs):
colorize = kwargs['colorize'] if 'colorize' in kwargs else None
if not colorize:
return img
img = self._driver(options=kwargs).colorize(img, colorize)
return img
return self.execute(src, fn, options=options)
[docs] def resize(self, src, options=None, **o_kwargs):
if not options and o_kwargs:
options = o_kwargs
def fn(img, kwargs):
size = kwargs['size'] if 'size' in kwargs else None
mode = kwargs['mode'] if 'mode' in kwargs else None
scale = int(kwargs['scale']) if 'scale' in kwargs else 1
limit = True if 'limit' in kwargs and kwargs['limit'] else False
border = int(kwargs['border']) if 'border' in kwargs else 0
if not size:
return img
width_new, height_new = size
width_origin, height_origin = img.size
if scale > 1:
if limit:
scale_max_width = float(width_origin) / float(width_new)
scale_max_height = float(height_origin) / float(height_new)
scale_max = min(scale, scale_max_width, scale_max_height)
else:
scale_max = scale
if scale_max > 1:
width_new = int(width_new * scale_max)
height_new = int(height_new * scale_max)
if not width_new:
width_new = width_origin * height_new / height_origin
mode = self.helper.io.image.mode.resize
if not height_new:
height_new = height_origin * width_new / width_origin
mode = self.helper.io.image.mode.resize
if border:
width_new -= border * 2
height_new -= border * 2
if not mode:
mode = self.helper.io.image.mode.resize
if mode not in self.helper.io.image.mode.modes:
raise Exception('The specified mode is not supported.')
seqs = []
for i, im in self._driver(options=kwargs).iter_seqs(img, kwargs):
# Image Resizing
if mode == self.helper.io.image.mode.center:
im = self._driver(options=kwargs).resize(im, width_new, height_new, kwargs)
elif mode == self.helper.io.image.mode.fill:
ratio_origin = float(width_origin) / float(height_origin)
ratio_new = float(width_new) / float(height_new)
if ratio_origin > ratio_new:
tw = int(round(height_new * ratio_origin))
im = self._driver(options=kwargs).resize(im, tw, height_new)
left = int(round((tw - width_new) / 2.0))
im = self._driver(options=kwargs).crop(im, left, 0, left + width_new, height_new)
elif ratio_origin < ratio_new:
th = int(round(width_new / ratio_origin))
im = self._driver(options=kwargs).resize(im, width_new, th)
top = int(round((th - height_new) / 2.0))
im = self._driver(options=kwargs).crop(im, 0, top, width_new, top + height_new)
else:
im = self._driver(options=kwargs).resize(im, width_new, height_new)
elif mode == self.helper.io.image.mode.resize:
if width_new > width_origin or height_new > height_origin:
width_new = width_origin
height_new = height_origin
im = self._driver(options=kwargs).resize(im, width_new, height_new)
seqs.append(im)
img = seqs[0]
seqs.remove(img)
img.__dict__['__frames__'] = seqs
return img
return self.execute(src, fn, options=options)
[docs] def save(self, src, options=None, **o_kwargs):
if not options and o_kwargs:
options = o_kwargs
def fn(img, kwargs):
ext = kwargs['format'] if 'format' in kwargs else None
dest = kwargs['dest'] if 'dest' in kwargs else None
if not dest:
return None
if not ext and self.helper.misc.type.check.string(dest):
ext = self.helper.io.path.ext(dest, dot='').lower()
if not ext and self.helper.misc.type.check.string(src):
ext = self.helper.io.path.ext(src, dot='').lower()
if not ext and '_org' in kwargs and kwargs['_org'] and self.helper.misc.type.check.string(kwargs['_org']):
ext = self.helper.io.path.ext(kwargs['_org'], dot='').lower()
if dest == 's3':
# TODO
return False
if not self._driver(options=kwargs).save(img, ext, dest, kwargs):
return False
return True
return self.execute(src, fn, options=options)
[docs] def manipulate(self, src, options=None, **kwargs):
if not options and kwargs:
options = kwargs
options['_org'] = src
try:
img = self.load(src, options=options)
# Crop
img = self.crop(img, options=options)
if not img:
return False
# Resize
img = self.resize(img, options=options)
if not img:
return False
# Radius
img = self.radius(img, options=options)
if not img:
return False
# Border
img = self.border(img, options=options)
if not img:
return False
# Colorize
img = self.colorize(img, options=options)
if not img:
return False
# Save
saved = self.save(img, options=options)
if saved is None:
return img
elif saved is False:
return False
return True
except Exception as e:
self.logging.exception(e)
return False