Refactor image resize code, with better filenames (#261)
authorBrett Smith <brettcsmith@brettcsmith.org>
Sun, 18 Mar 2012 03:43:46 +0000 (23:43 -0400)
committerBrett Smith <brettcsmith@brettcsmith.org>
Sun, 18 Mar 2012 03:43:46 +0000 (23:43 -0400)
The code to make thumbnail- and medium-sized images in processing.py is
pretty similar, so I rolled that out into a separate function that we call
with different arguments as appropriate.

The new function should work identically to the old code, except it saves
images with filenames based on the original filename, like
`foobar.medium.jpg` instead of just `medium.jpg`.  This fixes bug #261.

mediagoblin/media_types/image/processing.py

index 6ba91a15a840c7a9a4a244725ad34b71a858665c..2a00606a3f743d5f8693ea6084e541436cbd14cf 100644 (file)
@@ -23,6 +23,46 @@ from mediagoblin.processing import BadMediaFail, \
 from mediagoblin.tools.exif import exif_fix_image_orientation, \
     extract_exif, clean_exif, get_gps_data, get_useful
 
+MAX_FILENAME_LENGTH = 255  # the limit in VFAT -- seems like a good baseline
+
+def resize_image(entry, filename, basename, file_tail, exif_tags, workdir,
+                 new_size, size_limits=None):
+    """Store a resized version of an image and return its pathname.
+
+    Arguments:
+    entry -- the entry for the image to resize
+    filename -- the filename of the original image being resized
+    basename -- simple basename of the given filename
+    file_tail -- ending string and extension for the resized filename
+    exif_tags -- EXIF data for the original image
+    workdir -- directory path for storing converted image files
+    new_size -- 2-tuple size for the resized image
+    size_limits (optional) -- image is only resized if it exceeds this size
+
+    """
+    try:
+        resized = Image.open(filename)
+    except IOError:
+        raise BadMediaFail()
+    resized = exif_fix_image_orientation(resized, exif_tags)  # Fix orientation
+
+    if ((size_limits is None) or
+        (resized.size[0] > size_limits[0]) or
+        (resized.size[1] > size_limits[1])):
+        resized.thumbnail(new_size, Image.ANTIALIAS)
+
+    resized_filename = (basename[:MAX_FILENAME_LENGTH - len(file_tail)] +
+                        file_tail)
+    resized_filepath = create_pub_filepath(entry, resized_filename)
+
+    # Copy the new file to the conversion subdir, then remotely.
+    tmp_resized_filename = os.path.join(workdir, resized_filename)
+    with file(tmp_resized_filename, 'w') as resized_file:
+        resized.save(resized_file)
+    mgg.public_store.copy_local_to_storage(
+        tmp_resized_filename, resized_filepath)
+    return resized_filepath
+
 def process_image(entry):
     """
     Code to process an image
@@ -46,50 +86,17 @@ def process_image(entry):
     exif_tags = extract_exif(queued_filename)
     gps_data = get_gps_data(exif_tags)
 
-    try:
-        thumb = Image.open(queued_filename)
-    except IOError:
-        raise BadMediaFail()
-
-    thumb = exif_fix_image_orientation(thumb, exif_tags)
-
-    thumb.thumbnail(THUMB_SIZE, Image.ANTIALIAS)
-
-    # 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)
+    # Always create a small thumbnail
+    thumb_filepath = resize_image(entry, queued_filename, basename,
+                                  '.thumbnail' + extension, exif_tags,
+                                  conversions_subdir, THUMB_SIZE)
 
     # If the size of the original file exceeds the specified size of a `medium`
-    # file, a `medium.jpg` files is created and later associated with the media
+    # file, a `.medium.jpg` files is created and later associated with the media
     # entry.
-    medium = Image.open(queued_filename)
-
-    # Fix orientation
-    medium = exif_fix_image_orientation(medium, exif_tags)
-
-    if medium.size[0] > MEDIUM_SIZE[0] or medium.size[1] > MEDIUM_SIZE[1]:
-        medium.thumbnail(MEDIUM_SIZE, Image.ANTIALIAS)
-
-    medium_filename = 'medium' + extension
-    medium_filepath = create_pub_filepath(entry, medium_filename)
-
-    tmp_medium_filename = os.path.join(
-        conversions_subdir, medium_filename)
-
-    with file(tmp_medium_filename, 'w') as medium_file:
-        medium.save(medium_file)
-
-    mgg.public_store.copy_local_to_storage(
-        tmp_medium_filename, medium_filepath)
+    medium_filepath = resize_image(entry, queued_filename, basename,
+                                   '.medium' + extension, exif_tags,
+                                   conversions_subdir, MEDIUM_SIZE, MEDIUM_SIZE)
 
     # we have to re-read because unlike PIL, not everything reads
     # things in string representation :)