diff --git a/elodie/media/media.py b/elodie/media/media.py index e27e1c4..b12bb73 100644 --- a/elodie/media/media.py +++ b/elodie/media/media.py @@ -23,8 +23,6 @@ Media class for general video operations class Media(object): # class / static variable accessible through get_valid_extensions() __name__ = 'Media' - video_extensions = ('avi','m4v','mov','mp4','3gp') - photo_extensions = ('jpg', 'jpeg', 'nef', 'dng', 'gif') """ @param, source, string, The fully qualified path to the video file @@ -88,41 +86,6 @@ class Media(object): def is_valid(self): return False - - """ - Get the date which the photo was taken. - The date value returned is defined by the min() of mtime and ctime. - - @returns, time object or None for non-photo files or 0 timestamp - """ - def get_date_taken(self): - if(not self.is_valid()): - return None - - source = self.source - seconds_since_epoch = min(os.path.getmtime(source), os.path.getctime(source)) - # We need to parse a string from EXIF into a timestamp. - # EXIF DateTimeOriginal and EXIF DateTime are both stored in %Y:%m:%d %H:%M:%S format - # we use date.strptime -> .timetuple -> time.mktime to do the conversion in the local timezone - # EXIF DateTime is already stored as a timestamp - # Sourced from https://github.com/photo/frontend/blob/master/src/libraries/models/Photo.php#L500 - exif = self.get_exif() - for key in self.exif_map['date_taken']: - try: - if(key in exif): - if(re.match('\d{4}(-|:)\d{2}(-|:)\d{2}', str(exif[key].value)) is not None): - seconds_since_epoch = time.mktime(exif[key].value.timetuple()) - break; - except BaseException as e: - if(constants.debug == True): - print e - pass - - if(seconds_since_epoch == 0): - return None - - return time.gmtime(seconds_since_epoch) - """ Read EXIF from a photo file. We store the result in a member variable so we can call get_exif() often without performance degredation diff --git a/elodie/media/photo.py b/elodie/media/photo.py index 02646e8..959232b 100644 --- a/elodie/media/photo.py +++ b/elodie/media/photo.py @@ -86,7 +86,41 @@ class Photo(Media): return None """ - Check the file extension against valid file extensions as returned by get_valid_extensions() + Get the date which the photo was taken. + The date value returned is defined by the min() of mtime and ctime. + + @returns, time object or None for non-photo files or 0 timestamp + """ + def get_date_taken(self): + if(not self.is_valid()): + return None + + source = self.source + seconds_since_epoch = min(os.path.getmtime(source), os.path.getctime(source)) + # We need to parse a string from EXIF into a timestamp. + # EXIF DateTimeOriginal and EXIF DateTime are both stored in %Y:%m:%d %H:%M:%S format + # we use date.strptime -> .timetuple -> time.mktime to do the conversion in the local timezone + # EXIF DateTime is already stored as a timestamp + # Sourced from https://github.com/photo/frontend/blob/master/src/libraries/models/Photo.php#L500 + exif = self.get_exif() + for key in self.exif_map['date_taken']: + try: + if(key in exif): + if(re.match('\d{4}(-|:)\d{2}(-|:)\d{2}', str(exif[key].value)) is not None): + seconds_since_epoch = time.mktime(exif[key].value.timetuple()) + break; + except BaseException as e: + if(constants.debug == True): + print e + pass + + if(seconds_since_epoch == 0): + return None + + return time.gmtime(seconds_since_epoch) + + """ + Check the file extension against valid file extensions as returned by self.extensions @returns, boolean """ @@ -98,7 +132,6 @@ class Photo(Media): if(imghdr.what(source) is None): return False; - # we can't use self.__get_extension else we'll endlessly recurse return os.path.splitext(source)[1][1:].lower() in self.extensions """ @@ -174,4 +207,4 @@ class Photo(Media): """ @classmethod def get_valid_extensions(Photo): - return Media.photo_extensions + return Photo.extensions diff --git a/elodie/tests/files/no-exif.jpg b/elodie/tests/files/no-exif.jpg new file mode 100644 index 0000000..0a65ad2 Binary files /dev/null and b/elodie/tests/files/no-exif.jpg differ diff --git a/elodie/tests/files/plain.jpg b/elodie/tests/files/plain.jpg index 6461606..bd59831 100644 Binary files a/elodie/tests/files/plain.jpg and b/elodie/tests/files/plain.jpg differ diff --git a/elodie/tests/files/with-album-and-title-and-location.jpg b/elodie/tests/files/with-album-and-title-and-location.jpg index 22002c0..6abebbc 100644 Binary files a/elodie/tests/files/with-album-and-title-and-location.jpg and b/elodie/tests/files/with-album-and-title-and-location.jpg differ diff --git a/elodie/tests/files/with-album-and-title.jpg b/elodie/tests/files/with-album-and-title.jpg index 8e7ab00..14d6039 100644 Binary files a/elodie/tests/files/with-album-and-title.jpg and b/elodie/tests/files/with-album-and-title.jpg differ diff --git a/elodie/tests/files/with-album.jpg b/elodie/tests/files/with-album.jpg index 5a5d7fc..5444576 100644 Binary files a/elodie/tests/files/with-album.jpg and b/elodie/tests/files/with-album.jpg differ diff --git a/elodie/tests/files/with-location-and-title.jpg b/elodie/tests/files/with-location-and-title.jpg index ad15505..a89552d 100644 Binary files a/elodie/tests/files/with-location-and-title.jpg and b/elodie/tests/files/with-location-and-title.jpg differ diff --git a/elodie/tests/files/with-location.jpg b/elodie/tests/files/with-location.jpg index f4bc4d1..0a88870 100644 Binary files a/elodie/tests/files/with-location.jpg and b/elodie/tests/files/with-location.jpg differ diff --git a/elodie/tests/files/with-title.jpg b/elodie/tests/files/with-title.jpg index 4e74f6d..93499c3 100644 Binary files a/elodie/tests/files/with-title.jpg and b/elodie/tests/files/with-title.jpg differ diff --git a/elodie/tests/media/photo_test.py b/elodie/tests/media/photo_test.py index 01e0a09..831254f 100644 --- a/elodie/tests/media/photo_test.py +++ b/elodie/tests/media/photo_test.py @@ -3,14 +3,10 @@ import os import sys -import hashlib -import random -import re +import datetime import shutil -import string import tempfile import time -import datetime from nose.plugins.skip import SkipTest @@ -25,7 +21,7 @@ os.environ['TZ'] = 'GMT' def test_photo_extensions(): photo = Photo() - extensions = photo.photo_extensions + extensions = photo.extensions assert 'jpg' in extensions assert 'jpeg' in extensions @@ -75,6 +71,29 @@ def test_get_coordinate_longitude(): assert coordinate == -122.033383611, coordinate +def test_get_coordinates_without_exif(): + photo = Photo(helper.get_file('no-exif.jpg')) + latitude = photo.get_coordinate('latitude') + longitude = photo.get_coordinate('longitude') + + assert latitude is None, latitude + assert longitude is None, longitude + +def test_get_date_taken(): + photo = Photo(helper.get_file('plain.jpg')) + date_taken = photo.get_date_taken() + + assert date_taken == (2015, 12, 5, 0, 59, 26, 5, 339, 0), date_taken + +def test_get_date_taken_without_exif(): + source = helper.get_file('no-exif.jpg') + photo = Photo(source) + date_taken = photo.get_date_taken() + + date_taken_from_file = time.gmtime(min(os.path.getmtime(source), os.path.getctime(source))) + + assert date_taken == date_taken_from_file, date_taken + def test_is_valid(): photo = Photo(helper.get_file('with-location.jpg')) @@ -141,10 +160,6 @@ def test_set_title(): photo = Photo(origin) origin_metadata = photo.get_metadata() - # Verify that original photo has no location information - assert origin_metadata['latitude'] is None, origin_metadata['latitude'] - assert origin_metadata['longitude'] is None, origin_metadata['longitude'] - status = photo.set_title('my photo title') assert status == True, status @@ -166,10 +181,6 @@ def test_set_title_non_ascii(): photo = Photo(origin) origin_metadata = photo.get_metadata() - # Verify that original photo has no location information - assert origin_metadata['latitude'] is None, origin_metadata['latitude'] - assert origin_metadata['longitude'] is None, origin_metadata['longitude'] - status = photo.set_title('形声字 / 形聲字') assert status == True, status