Acts on feedback from Chris
authorJoar Wandborg <git@wandborg.com>
Wed, 25 Jan 2012 22:05:47 +0000 (23:05 +0100)
committerJoar Wandborg <git@wandborg.com>
Wed, 25 Jan 2012 22:46:11 +0000 (23:46 +0100)
- Added EXIF tests
- Removed pdb from image processing "ifmain"
- Fixed comment typo in image processing
- Removed unused import in tools.exif

mediagoblin/media_types/image/processing.py
mediagoblin/tests/test_exif.py [new file with mode: 0644]
mediagoblin/tests/test_exif/bad.jpg [new file with mode: 0644]
mediagoblin/tests/test_exif/empty.jpg [new file with mode: 0644]
mediagoblin/tests/test_exif/good.jpg [new file with mode: 0644]
mediagoblin/tests/test_exif/has-gps.jpg [new file with mode: 0644]
mediagoblin/tools/exif.py

index f669e1a5b1251e261e2dfa5c6f5a6758bf711c87..78f64be0c6bc18876be70a33beef2b0266114bf3 100644 (file)
@@ -58,10 +58,13 @@ def process_image(entry):
     # Copy the thumb to the conversion subdir, then remotely.
     thumb_filename = 'thumbnail' + extension
     thumb_filepath = create_pub_filepath(entry, thumb_filename)
+
     tmp_thumb_filename = os.path.join(
         conversions_subdir, thumb_filename)
+
     with file(tmp_thumb_filename, 'w') as thumb_file:
         thumb.save(thumb_file)
+
     mgg.public_store.copy_local_to_storage(
         tmp_thumb_filename, thumb_filepath)
 
@@ -69,7 +72,8 @@ def process_image(entry):
     # file, a `medium.jpg` files is created and later associated with the media
     # entry.
     medium = Image.open(queued_filename)
-    # Fox orientation
+
+    # Fix orientation
     medium = exif_fix_image_orientation(medium, exif_tags)
 
     if medium.size[0] > MEDIUM_SIZE[0] or medium.size[1] > MEDIUM_SIZE[1]:
@@ -77,6 +81,7 @@ def process_image(entry):
 
     medium_filename = 'medium' + extension
     medium_filepath = create_pub_filepath(entry, medium_filename)
+
     tmp_medium_filename = os.path.join(
         conversions_subdir, medium_filename)
 
@@ -130,8 +135,5 @@ if __name__ == '__main__':
     clean = clean_exif(result)
     useful = get_useful(clean)
 
-    import pdb
-    pdb.set_trace()
-
     print pp.pprint(
         clean)
diff --git a/mediagoblin/tests/test_exif.py b/mediagoblin/tests/test_exif.py
new file mode 100644 (file)
index 0000000..9f2219c
--- /dev/null
@@ -0,0 +1,189 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 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/>.
+
+import os
+import pkg_resources
+import Image
+
+from mediagoblin.tools.exif import exif_fix_image_orientation, \
+    extract_exif, clean_exif, get_gps_data, get_useful
+
+GOOD_JPG = pkg_resources.resource_filename(
+    'mediagoblin.tests',
+    os.path.join(
+        'test_exif',
+        'good.jpg'))
+EMPTY_JPG = pkg_resources.resource_filename(
+    'mediagoblin.tests',
+    os.path.join(
+        'test_exif',
+        'empty.jpg'))
+BAD_JPG = pkg_resources.resource_filename(
+    'mediagoblin.tests',
+    os.path.join(
+        'test_exif',
+        'bad.jpg'))
+GPS_JPG = pkg_resources.resource_filename(
+    'mediagoblin.tests',
+    os.path.join(
+        'test_exif',
+        'has-gps.jpg'))
+
+def test_exif_extraction():
+    '''
+    Test EXIF extraction from a good image
+    '''
+    result = extract_exif(GOOD_JPG)
+    clean = clean_exif(result)
+    useful = get_useful(clean)
+    gps = get_gps_data(result)
+
+    # Do we have the result?
+    assert len(result) == 108
+
+    # Do we have clean data?
+    assert len(clean) == 105
+
+    # GPS data?
+    assert gps == {}
+
+    # Do we have the "useful" tags?
+    assert useful == {
+        'EXIF Flash': {
+            'field_type': 3,
+            'printable': 'No',
+            'field_offset': 380,
+            'tag': 37385,
+            'values': [0],
+            'field_length': 2},
+        'EXIF ExposureTime': {
+            'field_type': 5,
+            'printable': '1/125',
+            'field_offset': 700,
+            'tag': 33434,
+            'values': [[1, 125]],
+            'field_length': 8},
+        'EXIF FocalLength': {
+            'field_type': 5,
+            'printable': '18',
+            'field_offset': 780,
+            'tag': 37386,
+            'values': [[18, 1]],
+            'field_length': 8},
+        'Image Model': {
+            'field_type': 2,
+            'printable': 'NIKON D80',
+            'field_offset': 152,
+            'tag': 272,
+            'values': 'NIKON D80',
+            'field_length': 10},
+        'Image Make': {
+            'field_type': 2,
+            'printable': 'NIKON CORPORATION',
+            'field_offset': 134,
+            'tag': 271,
+            'values': 'NIKON CORPORATION',
+            'field_length': 18},
+        'EXIF ExposureMode': {
+            'field_type': 3,
+            'printable': 'Manual Exposure',
+            'field_offset': 584,
+            'tag': 41986,
+            'values': [1],
+            'field_length': 2},
+        'EXIF ISOSpeedRatings': {
+            'field_type': 3,
+            'printable': '100',
+            'field_offset': 260,
+            'tag': 34855,
+            'values': [100],
+            'field_length': 2},
+        'EXIF FNumber': {
+            'field_type': 5,
+            'printable': '10',
+            'field_offset': 708,
+            'tag': 33437,
+            'values': [[10, 1]],
+            'field_length': 8},
+        'EXIF UserComment': {
+            'field_type': 7,
+            'printable': 'Joar Wandborg                       ',
+            'field_offset': 26180,
+            'tag': 37510,
+            'values': [
+                65, 83, 67, 73, 73, 0, 0, 0, 74, 111, 97, 114, 32, 87,
+                97, 110, 100, 98, 111, 114, 103, 32, 32, 32, 32, 32, 32,
+                32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+                32, 32, 32],
+            'field_length': 44}}
+
+def test_exif_image_orientation():
+    '''
+    Test image reorientation based on EXIF data
+    '''
+    result = extract_exif(GOOD_JPG)
+
+    image = exif_fix_image_orientation(
+        Image.open(GOOD_JPG),
+        result)
+
+    # Are the dimensions correct?
+    assert image.size == (428, 640)
+
+    # If this pixel looks right, the rest of the image probably will too.
+    assert image.getdata()[10000] == (41, 28, 11)
+
+def test_exif_no_exif():
+    '''
+    Test an image without exif
+    '''
+    result = extract_exif(EMPTY_JPG)
+    clean = clean_exif(result)
+    useful = get_useful(clean)
+    gps = get_gps_data(result)
+
+    assert result == {}
+    assert clean == {}
+    assert gps == {}
+    assert useful == {}
+
+def test_exif_bad_image():
+    '''
+    Test EXIF extraction from a faithful, but bad image
+    '''
+    result = extract_exif(BAD_JPG)
+    clean = clean_exif(result)
+    useful = get_useful(clean)
+    gps = get_gps_data(result)
+
+    assert result == {}
+    assert clean == {}
+    assert gps == {}
+    assert useful == {}
+
+def test_exif_gps_data():
+    '''
+    Test extractiion of GPS data
+    '''
+    result = extract_exif(GPS_JPG)
+    gps = get_gps_data(result)
+
+    assert gps == {
+        'latitude': 59.336666666666666,
+        'direction': 25.674046740467404,
+        'altitude': 37.64365671641791,
+        'longitude': 18.016166666666667}
+    
diff --git a/mediagoblin/tests/test_exif/bad.jpg b/mediagoblin/tests/test_exif/bad.jpg
new file mode 100644 (file)
index 0000000..4cde23c
--- /dev/null
@@ -0,0 +1,18 @@
+V2UncmUgbm8gc3RyYW5nZXJzIHRvIGxvdmUKWW91IGtub3cgdGhlIHJ1bGVzIGFuZCBzbyBkbyBJ
+CkEgZnVsbCBjb21taXRtZW50J3Mgd2hhdCBJJ20gdGhpbmtpbicgb2YKWW91IHdvdWxkbid0IGdl
+dCB0aGlzIGZyb20gYW55IG90aGVyIGd1eQpJIGp1c3Qgd2FubmEgdGVsbCB5b3UgaG93IEknbSBm
+ZWVsaW4nCkdvdHRhIG1ha2UgeW91IHVuZGVyc3RhbmQKCihDaG9ydXMpCk5ldmVyIGdvbm5hIGdp
+dmUgeW91IHVwCk5ldmVyIGdvbm5hIGxldCB5b3UgZG93bgpOZXZlciBnb25uYSBydW4gYXJvdW5k
+IGFuZCBkZXNlcnQgeW91Ck5ldmVyIGdvbm5hIG1ha2UgeW91IGNyeQpOZXZlciBnb25uYSBzYXkg
+Z29vZGJ5ZQpOZXZlciBnb25uYSB0ZWxsIGEgbGllIGFuZCBodXJ0IHlvdQoKV2UndmUga25vdyBl
+YWNoIG90aGVyIGZvciBzbyBsb25nCllvdXIgaGVhcnQncyBiZWVuIGFjaGluJyBidXQgeW91J3Jl
+IHRvbyBzaHkgdG8gc2F5IGl0Ckluc2lkZSB3ZSBib3RoIGtub3cgd2hhdCdzIGJlZW4gZ29pbmcg
+b24KV2Uga25vdyB0aGUgZ2FtZSBhbmQgd2UncmUgZ29ubmEgcGxheSBpdApBbmQgaWYgeW91IGFz
+ayBtZSBob3cgSSdtIGZlZWxpbicKRG9uJ3QgdGVsbCBtZSB5b3UncmUgdG9vIGJsaW5kIHRvIHNl
+ZQoKKENob3J1cyB4MikKCihHaXZlIHlvdSB1cCwgZ2l2ZSB5b3UgdXApCk5ldmVyIGdvbm5hIGdp
+dmUsIG5ldmVyIGdvbm5hIGdpdmUKKEdpdmUgeW91IHVwKQpOZXZlciBnb25uYSBnaXZlLCBuZXZl
+ciBnb25uYSBnaXZlCihHaXZlIHlvdSB1cCkKCldlJ3ZlIGtub3cgZWFjaCBvdGhlciBmb3Igc28g
+bG9uZwpZb3VyIGhlYXJ0J3MgYmVlbiBhY2hpbicgYnV0IHlvdSdyZSB0b28gc2h5IHRvIHNheSBp
+dApJbnNpZGUgd2UgYm90aCBrbm93IHdoYXQncyBiZWVuIGdvaW5nIG9uCldlIGtub3cgdGhlIGdh
+bWUgYW5kIHdlJ3JlIGdvbm5hIHBsYXkgaXQKSSBqdXN0IHdhbm5hIHRlbGwgeW91IGhvdyBJJ20g
+ZmVlbGluJwpHb3R0YSBtYWtlIHlvdSB1bmRlcnN0YW5kCgooQ2hvcnVzIHgzKQo=
diff --git a/mediagoblin/tests/test_exif/empty.jpg b/mediagoblin/tests/test_exif/empty.jpg
new file mode 100644 (file)
index 0000000..37533af
Binary files /dev/null and b/mediagoblin/tests/test_exif/empty.jpg differ
diff --git a/mediagoblin/tests/test_exif/good.jpg b/mediagoblin/tests/test_exif/good.jpg
new file mode 100644 (file)
index 0000000..0ee956f
Binary files /dev/null and b/mediagoblin/tests/test_exif/good.jpg differ
diff --git a/mediagoblin/tests/test_exif/has-gps.jpg b/mediagoblin/tests/test_exif/has-gps.jpg
new file mode 100644 (file)
index 0000000..c7d2cc9
Binary files /dev/null and b/mediagoblin/tests/test_exif/has-gps.jpg differ
index 445907ba80efd5a7057c70ddf20b7066a92ddf33..3c1aebe53fbfbcb0a7c3cc503fb54b6528cbcc95 100644 (file)
@@ -18,8 +18,6 @@ from mediagoblin.tools.extlib.EXIF import process_file, Ratio
 from mediagoblin.processing import BadMediaFail
 from mediagoblin.tools.translate import pass_to_ugettext as _
 
-from collections import OrderedDict
-
 # A list of tags that should be stored for faster access
 USEFUL_TAGS = [
     'Image Make',
@@ -73,8 +71,7 @@ def extract_exif(filename):
 
 def clean_exif(exif):
     '''
-    Clean the result from anyt
-hing the database cannot handle
+    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.
@@ -129,11 +126,11 @@ def get_gps_data(tags):
     """
     Processes EXIF data returned by EXIF.py
     """
-    if not 'Image GPSInfo' in tags:
-        return False
-
     gps_data = {}
 
+    if not 'Image GPSInfo' in tags:
+        return gps_data
+
     try:
         dms_data = {
             'latitude': tags['GPS GPSLatitude'],