Switching non-forms back to using normal pass_to_ugettext
[mediagoblin.git] / mediagoblin / tools / exif.py
index c4fc1fe5a5b5bce0422df68da0471c5644f79432..d0f9d0a6917c871b24b15c2e846f31a60ffd4398 100644 (file)
 # 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
+try:
+    from EXIF import process_file, Ratio
+except ImportError:
+    from mediagoblin.tools.extlib.EXIF import process_file, Ratio
+
 from mediagoblin.processing import BadMediaFail
 from mediagoblin.tools.translate import pass_to_ugettext as _
 
@@ -46,7 +50,10 @@ def exif_fix_image_orientation(im, exif_tags):
     Translate any EXIF orientation to raw orientation
 
     Cons:
-    - REDUCES IMAGE QUALITY by recompressig it
+    - Well, it changes the image, which means we'll recompress
+      it... not a problem if scaling it down already anyway.  We might
+      lose some quality in recompressing if it's at the same-size
+      though
 
     Pros:
     - Prevents neck pain
@@ -58,7 +65,7 @@ def exif_fix_image_orientation(im, exif_tags):
             6: 270,
             8: 90}
         orientation = exif_tags['Image Orientation'].values[0]
-        if orientation in rotation_map.keys():
+        if orientation in rotation_map:
             im = im.rotate(
                 rotation_map[orientation])
 
@@ -69,16 +76,12 @@ def extract_exif(filename):
     """
     Returns EXIF tags found in file at ``filename``
     """
-    exif_tags = {}
-
     try:
-        image = open(filename)
-        exif_tags = process_file(image)
+        with file(filename) as image:
+            return process_file(image, details=False)
     except IOError:
         raise BadMediaFail(_('Could not read the image file.'))
 
-    return exif_tags
-
 
 def clean_exif(exif):
     '''
@@ -92,16 +95,15 @@ def clean_exif(exif):
         '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
+    return dict((key, _ifd_tag_to_dict(value)) for (key, value)
+            in exif.iteritems() if key not in disabled_tags)
 
 
 def _ifd_tag_to_dict(tag):
+    '''
+    Takes an IFD tag object from the EXIF library and converts it to a dict
+    that can be stored as JSON in the database.
+    '''
     data = {
         'printable': tag.printable,
         'tag': tag.tag,
@@ -109,16 +111,20 @@ def _ifd_tag_to_dict(tag):
         'field_offset': tag.field_offset,
         'field_length': tag.field_length,
         'values': None}
+
+    if isinstance(tag.printable, str):
+        # Force it to be decoded as UTF-8 so that it'll fit into the DB
+        data['printable'] = tag.printable.decode('utf8', 'replace')
+
     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)
+        data['values'] = [_ratio_to_list(val) if isinstance(val, Ratio) else val
+                for val in tag.values]
     else:
-        data['values'] = tag.values
+        if isinstance(tag.values, str):
+            # Force UTF-8, so that it fits into the DB
+            data['values'] = tag.values.decode('utf8', 'replace')
+        else:
+            data['values'] = tag.values
 
     return data
 
@@ -128,12 +134,7 @@ def _ratio_to_list(ratio):
 
 
 def get_useful(tags):
-    useful = {}
-    for key, tag in tags.items():
-        if key in USEFUL_TAGS:
-            useful[key] = tag
-
-    return useful
+    return dict((key, tag) for (key, tag) in tags.iteritems() if key in USEFUL_TAGS)
 
 
 def get_gps_data(tags):
@@ -150,7 +151,7 @@ def get_gps_data(tags):
             'latitude': tags['GPS GPSLatitude'],
             'longitude': tags['GPS GPSLongitude']}
 
-        for key, dat in dms_data.items():
+        for key, dat in dms_data.iteritems():
             gps_data[key] = (
                 lambda v:
                     float(v[0].num) / float(v[0].den) \
@@ -158,6 +159,9 @@ def get_gps_data(tags):
                     + (float(v[2].num) / float(v[2].den) / (60 * 60))
                 )(dat.values)
 
+        if tags['GPS GPSLatitudeRef'].values == 'S':
+            gps_data['latitude'] /= -1
+
         if tags['GPS GPSLongitudeRef'].values == 'W':
             gps_data['longitude'] /= -1