Source code for colour_hdri.utilities.exif
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
EXIF Manipulation
=================
Exif data manipulation routines based on *exiftool*:
- :func:`parse_exif_data`
- :func:`read_exif_tags`
- :func:`copy_exif_tags`
- :func:`update_exif_tags`
- :func:`delete_exif_tags`
- :func:`read_exif_tag`
- :func:`write_exif_tag`
"""
from __future__ import division, unicode_literals
import logging
import re
import subprocess
from colour_hdri.utilities import vivification
__author__ = 'Colour Developers'
__copyright__ = 'Copyright (C) 2015 - Colour Developers'
__license__ = 'New BSD License - http://opensource.org/licenses/BSD-3-Clause'
__maintainer__ = 'Colour Developers'
__email__ = 'colour-science@googlegroups.com'
__status__ = 'Production'
__all__ = ['EXIF_EXECUTABLE',
'parse_exif_data',
'read_exif_tags',
'copy_exif_tags',
'update_exif_tags',
'delete_exif_tags',
'read_exif_tag',
'write_exif_tag']
LOGGER = logging.getLogger(__name__)
EXIF_EXECUTABLE = 'exiftool'
[docs]def parse_exif_data(data):
"""
Parses given exif data output from *exiftool*.
Parameters
----------
data : unicode
Exif data.
Returns
-------
list
Parsed exif data.
"""
search = re.search(
r'\[(?P<group>\w+)\]\s*(?P<id>(\d+|-))?(?P<tag>.*?):(?P<value>.*$)',
data)
return map(lambda x: x.strip() if x is not None else x,
(search.group('group'),
search.group('id'),
search.group('tag'),
search.group('value')))
[docs]def read_exif_tags(image):
"""
Returns given image exif image tags.
Parameters
----------
image : unicode
Image file.
Returns
-------
defaultdict
Exif tags.
"""
LOGGER.info("Reading '{0}' image exif data.".format(image))
exif_tags = vivification()
lines = unicode(subprocess.check_output(
[EXIF_EXECUTABLE, '-D', '-G', '-a', '-u', '-n', image]),
'utf-8', 'ignore').split('\n')
for line in lines:
if not line.strip():
continue
group, identifier, tag, value = parse_exif_data(line)
exif_tags[group][tag] = (value, identifier)
return exif_tags
[docs]def copy_exif_tags(source, target):
"""
Copies given source image file exif tag to given image target.
Parameters
----------
source : unicode
Source image file.
target : unicode
Target image file.
Returns
-------
bool
Definition success.
"""
LOGGER.info("Copying '{0}' file exif data to '{1}' file.".format(
target, source))
subprocess.check_output(
[EXIF_EXECUTABLE,
'-overwrite_original',
'-TagsFromFile',
'{0}'.format(source),
'{0}'.format(target)])
return True
[docs]def update_exif_tags(images):
"""
Updates given images siblings images pairs exif tags.
Parameters
----------
images : list
Image files to update.
Returns
-------
bool
Definition success.
"""
success = True
for (source, target) in images:
success *= copy_exif_tags(source, target)
return success
[docs]def delete_exif_tags(image):
"""
Deletes all given image exif tags.
Parameters
----------
image : unicode
Image file.
Returns
-------
bool
Definition success.
"""
LOGGER.info("Deleting '{0}' image exif tags.".format(image))
subprocess.check_output(
[EXIF_EXECUTABLE, '-overwrite_original', '-all=', image])
return True
[docs]def read_exif_tag(image, tag):
"""
Returns given image exif tag value.
Parameters
----------
image : unicode
Image file.
tag : unicode
Tag.
Returns
-------
unicode
Tag value.
"""
value = unicode(subprocess.check_output(
[EXIF_EXECUTABLE, '-{0}'.format(tag), image]),
'utf-8', 'ignore').split(':').pop().strip()
LOGGER.info("Reading '{0}' image '{1}' exif tag value: '{2}'".format(
image, tag, value))
return value
[docs]def write_exif_tag(image, tag, value):
"""
Sets given image exif tag value.
Parameters
----------
image : unicode
Image file.
tag : unicode
Tag.
value : unicode
Value.
Returns
-------
bool
Definition success.
"""
LOGGER.info("Writing '{0}' image '{1}' exif tag with '{2}' value.".format(
image, tag, value))
subprocess.check_output(
[EXIF_EXECUTABLE, '-overwrite_original', '-{0}={1}'.format(tag, value),
image])
return True