Browse Source

Move to pilkit.

Replace the custom code in the image module by pilkit generators.
pull/17/merge
Simon 13 years ago committed by Simon Conseil
parent
commit
692a036237
  1. 36
      sigal/gallery.py
  2. 108
      sigal/image.py
  3. 11
      sigal/writer.py
  4. 29
      tests/test_image.py

36
sigal/gallery.py

@ -33,7 +33,7 @@ from multiprocessing import Pool
from os.path import join
from PIL import Image as PILImage
from .image import Image
from .image import generate_image, generate_thumbnail
from .settings import get_thumb
from .writer import Writer
@ -211,7 +211,6 @@ class Gallery(object):
for f in img_iterator:
filename = os.path.split(f)[1]
outname = join(outpath, filename)
self.logger.info(filename)
if os.path.isfile(outname) and not self.force:
self.logger.info("%s exists - skipping", filename)
@ -239,25 +238,27 @@ def process_image(filepath, outpath, settings):
filename = os.path.split(filepath)[1]
outname = join(outpath, filename)
ext = os.path.splitext(filename)
img = Image(filepath)
if settings['keep_orig']:
img.save(join(outpath, settings['orig_dir'], filename),
options=settings['jpg_options'])
img.resize(settings['img_size'])
if ext in ['.jpg', '.jpeg', '.JPG', '.JPEG']:
options = settings['jpg_options']
elif ext == '.png':
options = {'optimize': True}
else:
options = {}
if settings['copyright']:
img.add_copyright(settings['copyright'])
# TODO
# if settings['keep_orig']:
# img.save(join(outpath, settings['orig_dir'], filename),
# options=settings['jpg_options'])
img.save(outname, options=settings['jpg_options'])
generate_image(filepath, outname, settings['img_size'], None,
options=options, copyright_text=settings['copyright'])
if settings['make_thumbs']:
thumb_name = join(outpath, get_thumb(settings, filename))
img.thumbnail(thumb_name, settings['thumb_size'],
fit=settings['thumb_fit'],
quality=settings['jpg_options']['quality'])
generate_thumbnail(outname, thumb_name, settings['thumb_size'], None,
fit=settings['thumb_fit'], options=options)
def get_metadata(path):
@ -266,8 +267,8 @@ def get_metadata(path):
- title
- thumbnail image
- description
"""
"""
descfile = join(path, DESCRIPTION_FILE)
if not os.path.isfile(descfile):
@ -279,11 +280,10 @@ def get_metadata(path):
'thumbnail': ''
}
else:
md = markdown.Markdown(extensions=['meta'])
with codecs.open(descfile, "r", "utf-8") as f:
text = f.read()
md = markdown.Markdown(extensions=['meta'])
html = md.convert(text)
meta = {

108
sigal/image.py

@ -20,96 +20,60 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
from __future__ import division
import logging
import os
from PIL import Image as PILImage
from PIL import ImageDraw, ImageOps
from pilkit.processors import ProcessorPipeline, Transpose, ResizeToFill
from pilkit.utils import save_image
# EXIF specs Orientation constant
EXIF_ORIENTATION_TAG = 274
class Image(object):
"""Image container
Prepare images: resize images, and create thumbnails with some options
(squared thumbs, ...).
def generate_image(source, outname, size, format, options=None,
autoconvert=True, copyright_text=''):
"""Image processor, rotate and resize the image.
:param filename: path to an image
:param source: path to an image
:param options: dict with PIL options (quality, optimize, progressive)
"""
def __init__(self, filename):
self.filename = filename
self.imgname = os.path.split(filename)[1]
self.logger = logging.getLogger(__name__)
self.img = PILImage.open(filename)
# Try to read exif metadata. This can fail if:
# - the image does not have exif (png files) -> AttributeError
# - PIL fail to read exif -> IOError
try:
exif = self.img._getexif()
except (IOError, AttributeError):
exif = False
if exif:
# http://www.impulseadventure.com/photo/exif-orientation.html
orientation = exif.get(EXIF_ORIENTATION_TAG)
rotate_map = {3: 180, 6: -90, 8: 90}
rotation = rotate_map.get(orientation)
if rotation:
self.img = self.img.rotate(rotation)
def save(self, filename, format='JPEG', options=None, autoconvert=True):
"""Save the image.
Pass a dict with PIL options (quality, optimize, progressive).
"""
save_image(self.img, filename, format, options=options,
autoconvert=autoconvert)
def resize(self, size):
"""Resize the image.
logger = logging.getLogger(__name__)
img = PILImage.open(source)
original_format = img.format
- check if the image format is portrait or landscape and adjust `size`.
- compute the width and height ratio, and keep the min to resize the
image inside the `size` box without distorting it.
# Run the processors
processors = [
Transpose(), # use exif to rotate the img
ResizeToFill(*size)
]
img = ProcessorPipeline(processors).process(img)
:param size: tuple with the (with, height) to resize
if copyright_text:
add_copyright(img, copyright_text)
"""
format = format or img.format or original_format or 'JPEG'
logger.debug('Save resized image to {0} ({1})'.format(outname, format))
save_image(img, outname, format, options=options, autoconvert=autoconvert)
if self.img.size[0] > self.img.size[1]:
newsize = size
else:
newsize = (size[1], size[0])
wratio = newsize[0] / self.img.size[0]
hratio = newsize[1] / self.img.size[1]
ratio = min(wratio, hratio)
newsize = (int(ratio * self.img.size[0]),
int(ratio * self.img.size[1]))
def generate_thumbnail(source, outname, box, format, fit=True, options=None):
"Create a thumbnail image"
if ratio < 1:
self.img = self.img.resize(newsize, PILImage.ANTIALIAS)
logger = logging.getLogger(__name__)
img = PILImage.open(source)
original_format = img.format
def add_copyright(self, text):
"Add a copyright to the image"
if fit:
img = ImageOps.fit(img, box, PILImage.ANTIALIAS)
else:
img.thumbnail(box, PILImage.ANTIALIAS)
draw = ImageDraw.Draw(self.img)
draw.text((5, self.img.size[1] - 15), '\xa9 ' + text)
format = format or img.format or original_format or 'JPEG'
logger.debug('Save thumnail image to {0} ({1})'.format(outname, format))
save_image(img, outname, format, options=options, autoconvert=True)
def thumbnail(self, filename, box, fit=True, quality=90):
"Create a thumbnail image"
if fit:
self.img = ImageOps.fit(self.img, box, PILImage.ANTIALIAS)
else:
self.img.thumbnail(box, PILImage.ANTIALIAS)
def add_copyright(img, text):
"Add a copyright to the image"
self.img.save(filename, quality=quality)
draw = ImageDraw.Draw(img)
draw.text((5, img.size[1] - 15), '\xa9 ' + text)

11
sigal/writer.py

@ -33,7 +33,7 @@ from distutils.dir_util import copy_tree
from jinja2 import Environment, FileSystemLoader, ChoiceLoader, PrefixLoader
from jinja2.exceptions import TemplateNotFound
from .image import Image
from .image import generate_thumbnail
from .settings import get_thumb
from .pkgmeta import __url__ as sigal_link
@ -147,10 +147,11 @@ class Writer(object):
# generate the thumbnail if it is missing (if
# settings['make_thumbs'] is False)
if not os.path.exists(thumb_path):
img = Image(os.path.join(self.output_dir, dpath, alb_thumb))
img.thumbnail(thumb_path, self.settings['thumb_size'],
fit=self.settings['thumb_fit'],
quality=self.settings['jpg_quality'])
source = os.path.join(self.output_dir, dpath, alb_thumb)
generate_thumbnail(
source, thumb_path, self.settings['thumb_size'],
fit=self.settings['thumb_fit'],
quality=self.settings['jpg_options']['quality'])
ctx['albums'].append({
'url': d + '/' + self.url_ext,

29
tests/test_image.py

@ -1,35 +1,18 @@
# -*- coding:utf-8 -*-
import os
from tempfile import mkdtemp
from shutil import rmtree
try:
import unittest2 as unittest
except ImportError:
import unittest # NOQA
from sigal.image import Image
from sigal.image import generate_image, generate_thumbnail
CURRENT_DIR = os.path.dirname(__file__)
TEST_IMAGE = 'exo20101028-b-full.jpg'
class TestImage(unittest.TestCase):
def test_image(tmpdir):
"Test the Image class."
def setUp(self):
self.temp_path = mkdtemp()
self.srcfile = os.path.join(CURRENT_DIR, 'sample', 'dir2', TEST_IMAGE)
self.dstfile = os.path.join(self.temp_path, TEST_IMAGE)
self.img = Image(self.srcfile)
def tearDown(self):
rmtree(self.temp_path)
def test_imgname(self):
self.assertEqual(self.img.imgname, TEST_IMAGE)
srcfile = os.path.join(CURRENT_DIR, 'sample', 'dir2', TEST_IMAGE)
dstfile = str(tmpdir.join(TEST_IMAGE))
def test_save(self):
self.img.save(self.dstfile)
self.assertTrue(os.path.isfile(self.dstfile))
generate_thumbnail(srcfile, dstfile, (200, 150))
assert os.path.isfile(dstfile)

Loading…
Cancel
Save