Commits

George Notaras  committed c8bf6d2

Re-arranged classes

  • Participants
  • Parent commits 3510827

Comments (0)

Files changed (3)

File src/thumbnail_works/fields.py

 from django.db.models.fields.files import ImageField, ImageFieldFile
 
 
-from thumbnail_works.core import ImageObject, Thumbnail
 from thumbnail_works.exceptions import ImageSizeError
-from thumbnail_works.utils import get_width_height_from_string, get_thumbnail_path
+from thumbnail_works.utils import get_width_height_from_string, \
+    get_thumbnail_path, process_content_as_image
 from thumbnail_works import settings
 from thumbnail_works import image_processors
 
 
 
 
+class Thumbnail:
+    
+    def __init__(self, name, size, source):
+        self.name = self._get_name(name)    # the thumbnail name as set in the dictionary
+        self.width, self.height = get_width_height_from_string(size)
+        self.url = get_thumbnail_path(source.url, self.name)
+    
+    def _get_name(self, name):
+        return name.replace(' ', '_')
+
 
         
 class EnhancedImageFieldFile(ImageFieldFile):
+    """Enhanced version of the default ImageFieldFile.
+    
+    The EnhancedImageFieldFile supports:
+    
+    - resizing the original image before saving it to the specified storage.
+    - generating thumbnails of the original image on the same storage.
+    - deleting the previously generated thumbnails from the specified storage.
+    - a mechanism of accessing the thumbnails as attributes of the model's
+      EnhancedImageField.
+      
+    For instance, we have the following model definition::
+      
+        from thumbnail_works.fields import EnhancedImageField
+          
+        class MyModel(models.Model):
+            photo = EnhancedImageField(
+                resize_source = '512x384',
+                thumbnails = {'avatar': '80x60', 'large': '200x150',}
+            )
+    
+    Thumbnail attributes can be accessed as follows::
+    
+        photo.avatar.url
+    
+    For information about the attributes of each thimbnail object, read the
+    ``Thumbnail`` docstring.
+    
+    """
     
     def __init__(self, *args, **kwargs):
+        """Constructor.
+        
+        Notes for development:
+        
+        Throughout this class the following attributes that are inherited
+        from ``ImageFieldFile`` are used:
+        
+        - instance: The instance of the model that contains the
+          EnhancedImageField.
+        - field: The instance of the EnhancedImageField.
+        - storage: The ``storage`` attribute of the EnhancedImageField instance.
+        - _committed: boolean attribute that indicates whether the file object
+          has been committed to the database and therefore saved to the
+          storage or the file has been deleted from the database and therefore
+          deleted from the filesystem.
+        
+        If thumbnails have been specified, instanciate them using the
+        ``Thumbnail`` class and add them as attributes to the
+        ``EnhancedImageFieldFile`` object.
+        
+        """
         super(EnhancedImageFieldFile, self).__init__(*args, **kwargs)
         
-        # Set thumbnail objects as instance attributes
+        # Set thumbnail objects as attributes
         if self.field.thumbnails:
-            for thumbnail_name, thumbnail_size in self.field.thumbnails.items():
-                thumbnail_obj = Thumbnail(thumbnail_name, thumbnail_size, self)
-                setattr(self, thumbnail_name, thumbnail_obj)
+            for thumb_name, thumb_size in self.field.thumbnails.items():
+                thumb_obj = Thumbnail(thumb_name, thumb_size, self)
+                setattr(self, thumb_name, thumb_obj)
     
     def save(self, name, content, save=True):
         """
         name: is the path on the filesystem of the original image
         """
-        
+        print name
+        print dir(content)
         
         # Before saving, resize the source image if a size has been set
         #content = copy.copy(content)
+        """
         img_obj = ImageObject()
         im = img_obj.get_img_data_from_file(content)
         im = image_processors.resize(im, self.field.resize_source)
         im = image_processors.sharpen(im)
         resized_content = img_obj.get_file_for_img_data(im)
+        """
+        processed_content = process_content_as_image(
+            content, resize_to=self.field.resize_source, sharpen=True)
         
-        super(EnhancedImageFieldFile, self).save(name, resized_content, save)
+        super(EnhancedImageFieldFile, self).save(name, processed_content, save)
         
         # self.name has been re-set in the save() above
         # use self.name to generate the thumbnail filename
         
         # Generate thumbnails
         if self.field.thumbnails:
-            for thumbnail_name, thumbnail_size in self.field.thumbnails.items():
+            for thumb_name, thumb_size in self.field.thumbnails.items():
                 #new_content = copy.deepcopy(content)
-                print "Doing: ", thumbnail_name, thumbnail_size
+                print "Doing: ", thumb_name, thumb_size
+                """
                 img_obj = ImageObject()
                 im = img_obj.get_img_data_from_file(content)
                 image_processors.resize(im, thumbnail_size)
                 thumbnail_content = img_obj.get_file_for_img_data(im)
-                path = get_thumbnail_path(name, thumbnail_name)
+                """
+                processed_content = process_content_as_image(
+                    content, resize_to=thumb_size, sharpen=True)
+                path = get_thumbnail_path(name, thumb_name)
                 print path
-                path_saved = self.storage.save(path, thumbnail_content)
+                path_saved = self.storage.save(path, processed_content)
                 
                 # check if path == path_saved
     

File src/thumbnail_works/image_processors.py

 #  limitations under the License.
 #
 
-import StringIO
 from PIL import Image, ImageFilter
 
-from django.core.files.base import ContentFile
-from django.core.files import File
-
-from thumbnail_works.utils import get_width_height_from_string
-from thumbnail_works import settings
-
 
 def resize(im, size):
     """
     """
     
     # Requested dimensions
-    width_req, height_req = get_width_height_from_string(size)
+    width_req, height_req = size
     # Source image dimensions
     width_source, height_source = im.size
     

File src/thumbnail_works/utils.py

 #
 
 import os
+import StringIO
+from PIL import Image
+
+from django.core.files.base import ContentFile
+from django.core.files import File
 
 from thumbnail_works.exceptions import ImageSizeError
+from thumbnail_works import image_processors
+from thumbnail_works import settings
 
 
 def get_width_height_from_string(size):
     base_filename, ext = os.path.splitext(filename)
     return os.path.join(root_dir, '%s.%s.%s' % (base_filename, thumbnail_name, ext))
 
+
+def process_content_as_image(content, resize_to=None, sharpen=False):
+    
+    # Image.open() accepts a file-like object, but it is needed
+    # to rewind it back to be able to get the data,
+    content.seek(0)
+    im = Image.open(content)
+    
+    # Convert to RGB if necessary
+    if im.mode not in ('L', 'RGB', 'RGBA'):
+        im = im.convert('RGB')
+    
+    # Process
+    if resize_to is not None:
+        im = image_processors.resize(im, get_width_height_from_string(resize_to))
+    if sharpen:
+        im = image_processors.sharpen(im)
+    
+    io = StringIO.StringIO()
+    
+    if settings.THUMBNAILS_FORMAT == 'JPEG':
+        im.save(io, 'JPEG', quality=settings.THUMBNAILS_QUALITY)
+    elif settings.THUMBNAILS_FORMAT == 'PNG':
+        im.save(io, 'PNG')
+    
+    return ContentFile(io.getvalue())
+