Populate title & description from IPTC image data
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.
This commit is contained in:
1
AUTHORS
1
AUTHORS
@@ -13,6 +13,7 @@ alphabetical order):
|
||||
- Christophe-Marie Duquesne
|
||||
- @datro
|
||||
- David Siroky
|
||||
- Edwin Steele
|
||||
- François D. (@franek)
|
||||
- Giel van Schijndel
|
||||
- Jamie Starke
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
# Copyright (c) 2014 - Jonas Kaufmann
|
||||
# Copyright (c) 2015 - François D.
|
||||
# Copyright (c) 2017 - Mate Lakat
|
||||
# Copyright (c) 2018 - Edwin Steele
|
||||
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
@@ -42,7 +43,8 @@ from os.path import isfile, join, splitext
|
||||
|
||||
from . import image, video, signals
|
||||
from .compat import PY2, UnicodeMixin, strxfrm, url_quote, text_type, pickle
|
||||
from .image import process_image, get_exif_tags, get_exif_data, get_size
|
||||
from .image import (process_image, get_exif_tags, get_exif_data, get_size,
|
||||
get_iptc_data)
|
||||
from .settings import get_thumb
|
||||
from .utils import (Devnull, copy, check_or_create_dir, url_from_path,
|
||||
read_markdown, cached_property, is_valid_html5_video,
|
||||
@@ -165,6 +167,23 @@ class Image(Media):
|
||||
return (get_exif_tags(self.raw_exif, datetime_format=datetime_format)
|
||||
if self.raw_exif and self.ext in ('.jpg', '.jpeg') else None)
|
||||
|
||||
def _get_metadata(self):
|
||||
super(Image, self)._get_metadata()
|
||||
# If a title or description hasn't been obtained by other means, look
|
||||
# for the information in IPTC fields as catalogued in:
|
||||
# https://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata
|
||||
if not self.title or not self.description:
|
||||
iptc_data = get_iptc_data(self.src_path)
|
||||
if iptc_data and not self.title:
|
||||
# 2:05 is the IPTC title property
|
||||
if (2, 5) in iptc_data:
|
||||
self.title = iptc_data[(2, 5)].decode('utf-8')
|
||||
|
||||
if iptc_data and not self.description:
|
||||
# 2:120 is the IPTC description property
|
||||
if (2, 120) in iptc_data:
|
||||
self.description = iptc_data[(2, 120)].decode('utf-8')
|
||||
|
||||
@cached_property
|
||||
def raw_exif(self):
|
||||
try:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
# Copyright (c) 2009-2016 - Simon Conseil
|
||||
# Copyright (c) 2015 - François D.
|
||||
# Copyright (c) 2018 - Edwin Steele
|
||||
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
@@ -43,6 +44,7 @@ from datetime import datetime
|
||||
from PIL.ExifTags import TAGS, GPSTAGS
|
||||
from PIL import Image as PILImage
|
||||
from PIL import ImageOps
|
||||
from PIL import IptcImagePlugin
|
||||
from pilkit.processors import Transpose
|
||||
from pilkit.utils import save_image
|
||||
|
||||
@@ -235,6 +237,13 @@ def get_exif_data(filename):
|
||||
return data
|
||||
|
||||
|
||||
def get_iptc_data(filename):
|
||||
"""Return a dict with the raw IPTC data."""
|
||||
|
||||
img = _read_image(filename)
|
||||
return IptcImagePlugin.getiptcinfo(img)
|
||||
|
||||
|
||||
def dms_to_degrees(v):
|
||||
"""Convert degree/minute/second to decimal degrees."""
|
||||
|
||||
|
||||
BIN
tests/sample/pictures/iptcTest/1.jpg
Normal file
BIN
tests/sample/pictures/iptcTest/1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
BIN
tests/sample/pictures/iptcTest/2.jpg
Normal file
BIN
tests/sample/pictures/iptcTest/2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 43 KiB |
3
tests/sample/pictures/iptcTest/2.md
Normal file
3
tests/sample/pictures/iptcTest/2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Title: Markdown title beats iptc
|
||||
|
||||
Markdown description beats iptc
|
||||
3
tests/sample/pictures/iptcTest/index.md
Normal file
3
tests/sample/pictures/iptcTest/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Title: iptc test gallery
|
||||
|
||||
## This is used by test_image.py and test_gallery.py to validate iptc handling
|
||||
@@ -111,6 +111,22 @@ def test_media_orig(settings, tmpdir):
|
||||
assert m.big == '21.jpg'
|
||||
|
||||
|
||||
def test_media_iptc_override(settings):
|
||||
img_with_md = Image('2.jpg', 'iptcTest', settings)
|
||||
assert img_with_md.title == "Markdown title beats iptc"
|
||||
# Markdown parsing adds formatting. Let's just focus on content
|
||||
assert "Markdown description beats iptc" in img_with_md.description
|
||||
img_no_md = Image('1.jpg', 'iptcTest', settings)
|
||||
assert img_no_md.title == 'Haemostratulus clouds over Canberra - ' + \
|
||||
'2005-12-28 at 03-25-07'
|
||||
assert img_no_md.description == \
|
||||
'"Haemo" because they look like haemoglobin ' + \
|
||||
'cells and "stratulus" because I can\'t work out whether ' + \
|
||||
'they\'re Stratus or Cumulus clouds.\nWe\'re driving down ' + \
|
||||
'the main drag in Canberra so it\'s Parliament House that ' + \
|
||||
'you can see at the end of the road.'
|
||||
|
||||
|
||||
def test_image(settings, tmpdir):
|
||||
settings['destination'] = str(tmpdir)
|
||||
settings['datetime_format'] = '%d/%m/%Y'
|
||||
|
||||
@@ -7,7 +7,7 @@ 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_exif_data, get_size, process_image, get_iptc_data)
|
||||
from sigal.settings import create_settings, Status
|
||||
|
||||
CURRENT_DIR = os.path.dirname(__file__)
|
||||
@@ -162,6 +162,27 @@ def test_get_exif_tags():
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user