The IPTC spec defines title and description fields so use those to populate these fields on the Image unless they've been set by some other means.
266 lines
9.2 KiB
Python
266 lines
9.2 KiB
Python
# -*- coding:utf-8 -*-
|
|
|
|
import os
|
|
import PIL
|
|
import pytest
|
|
from PIL import Image
|
|
|
|
from sigal import init_logging
|
|
from sigal.image import (generate_image, generate_thumbnail, get_exif_tags,
|
|
get_exif_data, get_size, process_image, get_iptc_data)
|
|
from sigal.settings import create_settings, Status
|
|
|
|
CURRENT_DIR = os.path.dirname(__file__)
|
|
TEST_IMAGE = 'exo20101028-b-full.jpg'
|
|
SRCFILE = os.path.join(CURRENT_DIR, 'sample', 'pictures', 'dir2', TEST_IMAGE)
|
|
|
|
TEST_GIF_IMAGE = '50a1d0bc-763d-457e-b634-c87f16a64270.gif'
|
|
SRC_GIF_FILE = os.path.join(CURRENT_DIR, 'sample', 'pictures',
|
|
'dir1', 'test1', TEST_GIF_IMAGE)
|
|
|
|
|
|
def test_process_image(tmpdir):
|
|
"Test the process_image function."
|
|
|
|
status = process_image('foo.txt', 'none.txt', {})
|
|
assert status == Status.FAILURE
|
|
|
|
settings = create_settings(img_processor='ResizeToFill', make_thumbs=False)
|
|
status = process_image(SRCFILE, str(tmpdir), settings)
|
|
assert status == Status.SUCCESS
|
|
im = Image.open(os.path.join(str(tmpdir), TEST_IMAGE))
|
|
assert im.size == settings['img_size']
|
|
|
|
|
|
def test_generate_image(tmpdir):
|
|
"Test the generate_image function."
|
|
|
|
dstfile = str(tmpdir.join(TEST_IMAGE))
|
|
for i, size in enumerate([(600, 600), (300, 200)]):
|
|
settings = create_settings(img_size=size, img_processor='ResizeToFill',
|
|
copy_exif_data=True)
|
|
options = None if i == 0 else {'quality': 85}
|
|
generate_image(SRCFILE, dstfile, settings, options=options)
|
|
im = Image.open(dstfile)
|
|
assert im.size == size
|
|
|
|
|
|
def test_resize_image_portrait(tmpdir):
|
|
"""Test that the area is the same regardless of aspect ratio."""
|
|
size = (300, 200)
|
|
settings = create_settings(img_size=size)
|
|
|
|
portrait_image = 'm57_the_ring_nebula-587px.jpg'
|
|
portrait_src = os.path.join(CURRENT_DIR, 'sample', 'pictures', 'dir2', portrait_image)
|
|
portrait_dst = str(tmpdir.join(portrait_image))
|
|
|
|
generate_image(portrait_src, portrait_dst, settings)
|
|
im = Image.open(portrait_dst)
|
|
|
|
# In the default mode, PILKit resizes in a way to never make an image
|
|
# smaller than either of the lengths, the other is scaled accordingly.
|
|
# Hence we test that the shorter side has the smallest length.
|
|
assert im.size[0] == 200
|
|
|
|
landscape_image = 'exo20101028-b-full.jpg'
|
|
landscape_src = os.path.join(CURRENT_DIR, 'sample', 'pictures', 'dir2', landscape_image)
|
|
landscape_dst = str(tmpdir.join(landscape_image))
|
|
|
|
generate_image(landscape_src, landscape_dst, settings)
|
|
im = Image.open(landscape_dst)
|
|
assert im.size[1] == 200
|
|
|
|
|
|
@pytest.mark.parametrize(("image", "path"), [(TEST_IMAGE, SRCFILE),
|
|
(TEST_GIF_IMAGE, SRC_GIF_FILE)])
|
|
def test_generate_image_passthrough(tmpdir, image, path):
|
|
"Test the generate_image function with use_orig=True."
|
|
|
|
dstfile = str(tmpdir.join(image))
|
|
settings = create_settings(use_orig=True)
|
|
generate_image(path, dstfile, settings)
|
|
# Check the file was copied, not (sym)linked
|
|
st_src = os.stat(path)
|
|
st_dst = os.stat(dstfile)
|
|
assert st_src.st_size == st_dst.st_size
|
|
assert not os.path.samestat(st_src, st_dst)
|
|
|
|
|
|
def test_generate_image_passthrough_symlink(tmpdir):
|
|
"Test the generate_image function with use_orig=True and orig_link=True."
|
|
|
|
dstfile = str(tmpdir.join(TEST_IMAGE))
|
|
settings = create_settings(use_orig=True, orig_link=True)
|
|
generate_image(SRCFILE, dstfile, settings)
|
|
# Check the file was symlinked
|
|
assert os.path.islink(dstfile)
|
|
assert os.path.samefile(SRCFILE, dstfile)
|
|
|
|
|
|
def test_generate_image_processor(tmpdir):
|
|
"Test generate_image with a wrong processor name."
|
|
|
|
init_logging('sigal')
|
|
dstfile = str(tmpdir.join(TEST_IMAGE))
|
|
settings = create_settings(img_size=(200, 200),
|
|
img_processor='WrongMethod')
|
|
|
|
with pytest.raises(SystemExit):
|
|
generate_image(SRCFILE, dstfile, settings)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("image", "path", "wide_size", "high_size"),
|
|
[(TEST_IMAGE, SRCFILE, (185, 150), (150, 122)),
|
|
(TEST_GIF_IMAGE, SRC_GIF_FILE, (127, 150), (150, 177))])
|
|
def test_generate_thumbnail(tmpdir, image, path, wide_size, high_size):
|
|
"Test the generate_thumbnail function."
|
|
|
|
dstfile = str(tmpdir.join(image))
|
|
for size in [(200, 150), (150, 200)]:
|
|
generate_thumbnail(path, dstfile, size)
|
|
im = Image.open(dstfile)
|
|
assert im.size == size
|
|
|
|
for size, thumb_size in [((200, 150), wide_size),
|
|
((150, 200), high_size)]:
|
|
generate_thumbnail(path, dstfile, size, fit=False)
|
|
im = Image.open(dstfile)
|
|
assert im.size == thumb_size
|
|
|
|
|
|
def test_get_exif_tags():
|
|
test_image = '11.jpg'
|
|
src_file = os.path.join(CURRENT_DIR, 'sample', 'pictures', 'dir1', 'test1',
|
|
test_image)
|
|
data = get_exif_data(src_file)
|
|
simple = get_exif_tags(data, datetime_format='%d/%m/%Y')
|
|
assert simple['fstop'] == 3.9
|
|
assert simple['focal'] == 12.0
|
|
assert simple['iso'] == 50
|
|
assert simple['Make'] == 'NIKON'
|
|
assert simple['datetime'] == '22/01/2006'
|
|
if PIL.PILLOW_VERSION == '3.0.0':
|
|
assert simple['exposure'] == 0.00100603
|
|
else:
|
|
assert simple['exposure'] == '100603/100000000'
|
|
|
|
data = {'FNumber': [1, 0], 'FocalLength': [1, 0], 'ExposureTime': 10}
|
|
simple = get_exif_tags(data)
|
|
assert 'fstop' not in simple
|
|
assert 'focal' not in simple
|
|
assert simple['exposure'] == '10'
|
|
|
|
data = {'ExposureTime': '--', 'DateTimeOriginal': '---',
|
|
'GPSInfo': {'GPSLatitude': ((34, 0), (1, 0), (4500, 100)),
|
|
'GPSLatitudeRef': 'N',
|
|
'GPSLongitude': ((116, 0), (8, 0), (3900, 100)),
|
|
'GPSLongitudeRef': 'W'}}
|
|
simple = get_exif_tags(data)
|
|
assert 'exposure' not in simple
|
|
assert 'datetime' not in simple
|
|
assert 'gps' not in simple
|
|
|
|
|
|
def test_get_iptc_data():
|
|
test_image = '1.jpg'
|
|
src_file = os.path.join(CURRENT_DIR, 'sample', 'pictures', 'iptcTest',
|
|
test_image)
|
|
data = get_iptc_data(src_file)
|
|
# Title
|
|
assert data[(2, 5)] == b'Haemostratulus clouds over Canberra - ' + \
|
|
b'2005-12-28 at 03-25-07'
|
|
# Description
|
|
assert data[(2, 120)] == b'"Haemo" because they look like haemoglobin ' + \
|
|
b'cells and "stratulus" because I can\'t work out whether ' + \
|
|
b'they\'re Stratus or Cumulus clouds.\nWe\'re driving down ' + \
|
|
b'the main drag in Canberra so it\'s Parliament House that ' + \
|
|
b'you can see at the end of the road.'
|
|
# This file has no IPTC data
|
|
test_image = '21.jpg'
|
|
src_file = os.path.join(CURRENT_DIR, 'sample', 'pictures', 'exifTest',
|
|
test_image)
|
|
assert get_iptc_data(src_file) is None
|
|
|
|
|
|
def test_iso_speed_ratings():
|
|
data = {'ISOSpeedRatings': ()}
|
|
simple = get_exif_tags(data)
|
|
assert 'iso' not in simple
|
|
|
|
data = {'ISOSpeedRatings': None}
|
|
simple = get_exif_tags(data)
|
|
assert 'iso' not in simple
|
|
|
|
data = {'ISOSpeedRatings': 125}
|
|
simple = get_exif_tags(data)
|
|
assert 'iso' in simple
|
|
|
|
|
|
def test_null_exposure_time():
|
|
data = {'ExposureTime': (0, 0)}
|
|
simple = get_exif_tags(data)
|
|
assert 'exposure' not in simple
|
|
|
|
|
|
def test_exif_copy(tmpdir):
|
|
"Test if EXIF data can transferred copied to the resized image."
|
|
|
|
test_image = '11.jpg'
|
|
src_file = os.path.join(CURRENT_DIR, 'sample', 'pictures', 'dir1', 'test1',
|
|
test_image)
|
|
dst_file = str(tmpdir.join(test_image))
|
|
|
|
settings = create_settings(img_size=(300, 400), copy_exif_data=True)
|
|
generate_image(src_file, dst_file, settings)
|
|
simple = get_exif_tags(get_exif_data(dst_file))
|
|
assert simple['iso'] == 50
|
|
|
|
settings['copy_exif_data'] = False
|
|
generate_image(src_file, dst_file, settings)
|
|
simple = get_exif_tags(get_exif_data(dst_file))
|
|
assert not simple
|
|
|
|
|
|
@pytest.mark.xfail(PIL.PILLOW_VERSION == '3.0.0',
|
|
reason="Pillow 3.0.0 was broken")
|
|
def test_exif_gps(tmpdir):
|
|
"""Test reading out correct geo tags"""
|
|
|
|
test_image = 'flickr_jerquiaga_2394751088_cc-by-nc.jpg'
|
|
src_file = os.path.join(CURRENT_DIR, 'sample', 'pictures', 'dir1', 'test1',
|
|
test_image)
|
|
dst_file = str(tmpdir.join(test_image))
|
|
|
|
settings = create_settings(img_size=(400, 300), copy_exif_data=True)
|
|
generate_image(src_file, dst_file, settings)
|
|
simple = get_exif_tags(get_exif_data(dst_file))
|
|
assert 'gps' in simple
|
|
|
|
lat = 34.029167
|
|
lon = -116.144167
|
|
|
|
assert abs(simple['gps']['lat'] - lat) < 0.0001
|
|
assert abs(simple['gps']['lon'] - lon) < 0.0001
|
|
|
|
|
|
def test_get_size(tmpdir):
|
|
"""Test reading out image size"""
|
|
|
|
test_image = 'flickr_jerquiaga_2394751088_cc-by-nc.jpg'
|
|
src_file = os.path.join(CURRENT_DIR, 'sample', 'pictures', 'dir1', 'test1',
|
|
test_image)
|
|
|
|
result = get_size(src_file)
|
|
assert result == {'height': 800, 'width': 600}
|
|
|
|
|
|
def test_get_size_with_invalid_path(tmpdir):
|
|
"""Test reading out image size with a missing file"""
|
|
|
|
test_image = 'missing-file.jpg'
|
|
src_file = os.path.join(CURRENT_DIR, test_image)
|
|
|
|
result = get_size(src_file)
|
|
assert result is None
|