Christopher Allan Webber cf29e8a824 It's 2012 all up in here
2012-02-02 09:44:13 -06:00

166 lines
4.4 KiB
Python

# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mediagoblin.tools.extlib.EXIF import process_file, Ratio
from mediagoblin.processing import BadMediaFail
from mediagoblin.tools.translate import pass_to_ugettext as _
# A list of tags that should be stored for faster access
USEFUL_TAGS = [
'Image Make',
'Image Model',
'EXIF FNumber',
'EXIF Flash',
'EXIF FocalLength',
'EXIF ExposureTime',
'EXIF ApertureValue',
'EXIF ExposureMode',
'EXIF ISOSpeedRatings',
'EXIF UserComment',
]
def exif_fix_image_orientation(im, exif_tags):
"""
Translate any EXIF orientation to raw orientation
Cons:
- REDUCES IMAGE QUALITY by recompressig it
Pros:
- Cures my neck pain
"""
# Rotate image
if 'Image Orientation' in exif_tags:
rotation_map = {
3: 180,
6: 270,
8: 90}
orientation = exif_tags['Image Orientation'].values[0]
if orientation in rotation_map.keys():
im = im.rotate(
rotation_map[orientation])
return im
def extract_exif(filename):
"""
Returns EXIF tags found in file at ``filename``
"""
exif_tags = {}
try:
image = open(filename)
exif_tags = process_file(image)
except IOError:
raise BadMediaFail(_('Could not read the image file.'))
return exif_tags
def clean_exif(exif):
'''
Clean the result from anything the database cannot handle
'''
# Discard any JPEG thumbnail, for database compatibility
# and that I cannot see a case when we would use it.
# It takes up some space too.
disabled_tags = [
'Thumbnail JPEGInterchangeFormatLength',
'JPEGThumbnail',
'Thumbnail JPEGInterchangeFormat']
clean_exif = {}
for key, value in exif.items():
if not key in disabled_tags:
clean_exif[key] = _ifd_tag_to_dict(value)
return clean_exif
def _ifd_tag_to_dict(tag):
data = {
'printable': tag.printable,
'tag': tag.tag,
'field_type': tag.field_type,
'field_offset': tag.field_offset,
'field_length': tag.field_length,
'values': None}
if type(tag.values) == list:
data['values'] = []
for val in tag.values:
if isinstance(val, Ratio):
data['values'].append(
_ratio_to_list(val))
else:
data['values'].append(val)
else:
data['values'] = tag.values
return data
def _ratio_to_list(ratio):
return [ratio.num, ratio.den]
def get_useful(tags):
useful = {}
for key, tag in tags.items():
if key in USEFUL_TAGS:
useful[key] = tag
return useful
def get_gps_data(tags):
"""
Processes EXIF data returned by EXIF.py
"""
gps_data = {}
if not 'Image GPSInfo' in tags:
return gps_data
try:
dms_data = {
'latitude': tags['GPS GPSLatitude'],
'longitude': tags['GPS GPSLongitude']}
for key, dat in dms_data.items():
gps_data[key] = (
lambda v:
float(v[0].num) / float(v[0].den) \
+ (float(v[1].num) / float(v[1].den) / 60 )\
+ (float(v[2].num) / float(v[2].den) / (60 * 60))
)(dat.values)
except KeyError:
pass
try:
gps_data['direction'] = (
lambda d:
float(d.num) / float(d.den)
)(tags['GPS GPSImgDirection'].values[0])
except KeyError:
pass
try:
gps_data['altitude'] = (
lambda a:
float(a.num) / float(a.den)
)(tags['GPS GPSAltitude'].values[0])
except KeyError:
pass
return gps_data