blob: b622c804d80670a3b00a39d30406818bf8a64699 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Image processing functions
from StringIO import StringIO
try:
from PIL import Image
from PIL import ImageOps
from PIL import ExifTags
except:
Image = None
from base64 import b64encode, b64decode
from urllib import urlopen
from util import *
from sys import debug
# Rotate image if needed
def rotateimg(img):
debug('imgutil.py::rotateimg')
if not hasattr(img, '_getexif'):
return img
exif = img._getexif()
if exif is None:
return img
for tag, value in exif.items():
decoded = ExifTags.TAGS.get(tag, tag)
if decoded == 'Orientation':
if value == 3: return img.rotate(180)
if value == 6: return img.rotate(270)
if value == 8: return img.rotate(90)
return img
# Convert image to a cropped thumbnail
def thumbnail(img, size):
def intsz(*nums):
return tuple(int(round(n)) for n in nums)
class imgsz(object):
def __init__(self, pair):
self.width = float(pair[0])
self.height = float(pair[1])
self.aspect_ratio = self.width / self.height
self.size = intsz(self.width, self.height)
osz = imgsz(img.size)
tsz = imgsz(size)
if tsz.aspect_ratio > osz.aspect_ratio:
scale = tsz.width / osz.width
crop = imgsz((osz.width, tsz.height / scale))
cut = (osz.height - crop.height) / 2
img = img.crop(intsz(0, cut, crop.width, cut + crop.height))
elif tsz.aspect_ratio < osz.aspect_ratio:
scale = tsz.height / osz.height
crop = imgsz((tsz.width / scale, osz.height))
cut = (osz.width - crop.width) / 2
img = img.crop(intsz(cut, 0, cut + crop.width, crop.height))
return img.resize(tsz.size, Image.ANTIALIAS)
# Convert image URL to a 50x50 JPEG
def urlto50x50jpeg(url):
debug('imgutil.py::urlto50x50jpeg::url', url)
if Image is None:
return url
img = Image.open(StringIO(b64decode(url.split(',')[1])) if url.startswith('data:') else StringIO(urlopen(url).read()))
if img.size == (50, 50):
debug('imgutil.py::urlto50x50jpeg::res', url)
return url
thumb = thumbnail(rotateimg(img), (50, 50))
obuf = StringIO()
thumb.save(obuf, 'JPEG')
res = 'data:image/jpeg;base64,' + b64encode(obuf.getvalue()).replace('\n', '')
debug('imgutil.py::urlto50x50jpeg::res', res)
return res;
# Convert image to a 50x50 JPEG
def bufto50x50jpeg(buf):
debug('imgutil.py::bufto50x50jpeg')
if Image is None:
return ''
img = Image.open(StringIO(buf))
if img.size == (50, 50):
debug('imgutil.py::urlto50x50jpeg::res', url)
return url
thumb = thumbnail(rotateimg(img), (50, 50))
obuf = StringIO()
thumb.save(obuf, 'JPEG')
res = 'data:image/jpeg;base64,' + b64encode(obuf.getvalue()).replace('\n', '')
debug('imgutil.py::bufto50x50jpeg::res', res)
return res