# Path: gallery/imgutil.py
# def make_thumbnail(image_name, thumb_name, preset,
#                    image_storage, thumb_storage):
# 
#     options = getattr(settings, 'GALLERY_RESIZE_OPTIONS', {})
#     presets = getattr(settings, 'GALLERY_RESIZE_PRESETS', {})
# 
#     # Load the image
#     image = Image.open(image_storage.open(image_name))
#     format = image.format
# 
#     if format == 'JPEG':
#         # Auto-rotate JPEG files based on EXIF information
#         try:                                                # pragma: no cover
#             # Use of an undocumented API — let's catch exceptions liberally
#             orientation = image._getexif()[274]
#             image = exif_rotations[orientation](image)
#         except Exception:
#             pass
# 
#         # Increase Pillow's buffer from 64k to 4MB to avoid JPEG save errors
#         ImageFile.MAXBLOCK = 4194304
# 
#     # Pre-crop if requested and the aspect ratios don't match exactly
#     image_width, image_height = image.size
#     thumb_width, thumb_height, crop = presets[preset]
#     if crop:
#         if thumb_width * image_height > image_width * thumb_height:
#             target_height = image_width * thumb_height // thumb_width
#             top = (image_height - target_height) // 2
#             image = image.crop((0, top, image_width, top + target_height))
#         elif thumb_width * image_height < image_width * thumb_height:
#             target_width = image_height * thumb_width // thumb_height
#             left = (image_width - target_width) // 2
#             image = image.crop((left, 0, left + target_width, image_height))
# 
#     # Resize
#     image.thumbnail((thumb_width, thumb_height), Image.ANTIALIAS)
# 
#     # Save the thumbnail
#     thumb_bytes_io = io.BytesIO()
#     image.save(thumb_bytes_io, format, **options.get(image.format, {}))
#     thumb_bytes_io.seek(0)
#     thumb_storage.save(thumb_name, thumb_bytes_io)
# 
# Path: gallery/test_storages.py
# class MemoryStorage(Storage):
#     """
#     Limited implementation of an in-memory file storage.
# 
#     This class does the bare minimum for tests to pass. It doesn't implement
#     accessed/created/modified_time.
# 
#     """
#     def __init__(self, *args, **kwargs):
#         super().__init__(*args, **kwargs)
#         self.files = {}
# 
#     def _open(self, name, mode='rb'):
#         assert mode == 'rb'
#         return io.BytesIO(self.files[name])
# 
#     def _save(self, name, content):
#         content = content.read()
#         assert isinstance(content, bytes)
#         self.files[name] = content
#         return name
# 
#     def delete(self, name):
#         self.files.pop(name, None)
# 
#     def exists(self, name):
#         return name in self.files
# 
#     def listdir(self, name):
#         dirs, files = [], []
#         for filename in sorted(self.files):
#             filename = filename[len(name):]
#             if '/' in filename:
#                 dirs.append(filename.partition('/')[0])
#             else:
#                 files.append(filename)
#         return dirs, files
# 
#     def size(self, name):
#         return len(self.files[name])


import io
from django.test import TestCase
from django.test.utils import override_settings
from PIL import Image, ImageDraw
from .imgutil import make_thumbnail
from .test_storages import MemoryStorage
    'thumbnail': (8, 8, True),
    'preview': (16, 16, False),
})
class ThumbnailTests(TestCase):

    def setUp(self):
        super().setUp()
        self.storage = MemoryStorage()

    def make_image(self, width, height,
                   image_name='original.jpg', format='JPEG', mode='RGB'):
        make_image(self.storage, image_name, width, height, format, mode)

    def make_thumbnail(self, preset,
                       image_name='original.jpg', thumb_name='thumbnail.jpg'):
        make_thumbnail(image_name, thumb_name, preset,
                       self.storage, self.storage)

    def open_image(self, thumb_name='thumbnail.jpg'):
        return Image.open(self.storage.open(thumb_name))

    def test_horizontal_thumbnail(self):
        self.make_image(48, 36)
        self.make_thumbnail('thumbnail')

        im = self.open_image()
        self.assertEqual(im.size, (8, 8))

    def test_horizontal_preview(self):
        self.make_image(48, 36)

# Path: gallery/imgutil.py
# def make_thumbnail(image_name, thumb_name, preset,
#                    image_storage, thumb_storage):
# 
#     options = getattr(settings, 'GALLERY_RESIZE_OPTIONS', {})
#     presets = getattr(settings, 'GALLERY_RESIZE_PRESETS', {})
# 
#     # Load the image
#     image = Image.open(image_storage.open(image_name))
#     format = image.format
# 
#     if format == 'JPEG':
#         # Auto-rotate JPEG files based on EXIF information
#         try:                                                # pragma: no cover
#             # Use of an undocumented API — let's catch exceptions liberally
#             orientation = image._getexif()[274]
#             image = exif_rotations[orientation](image)
#         except Exception:
#             pass
# 
#         # Increase Pillow's buffer from 64k to 4MB to avoid JPEG save errors
#         ImageFile.MAXBLOCK = 4194304
# 
#     # Pre-crop if requested and the aspect ratios don't match exactly
#     image_width, image_height = image.size
#     thumb_width, thumb_height, crop = presets[preset]
#     if crop:
#         if thumb_width * image_height > image_width * thumb_height:
#             target_height = image_width * thumb_height // thumb_width
#             top = (image_height - target_height) // 2
#             image = image.crop((0, top, image_width, top + target_height))
#         elif thumb_width * image_height < image_width * thumb_height:
#             target_width = image_height * thumb_width // thumb_height
#             left = (image_width - target_width) // 2
#             image = image.crop((left, 0, left + target_width, image_height))
# 
#     # Resize
#     image.thumbnail((thumb_width, thumb_height), Image.ANTIALIAS)
# 
#     # Save the thumbnail
#     thumb_bytes_io = io.BytesIO()
#     image.save(thumb_bytes_io, format, **options.get(image.format, {}))
#     thumb_bytes_io.seek(0)
#     thumb_storage.save(thumb_name, thumb_bytes_io)
# 
# Path: gallery/test_storages.py
# class MemoryStorage(Storage):
#     """
#     Limited implementation of an in-memory file storage.
# 
#     This class does the bare minimum for tests to pass. It doesn't implement
#     accessed/created/modified_time.
# 
#     """
#     def __init__(self, *args, **kwargs):
#         super().__init__(*args, **kwargs)
#         self.files = {}
# 
#     def _open(self, name, mode='rb'):
#         assert mode == 'rb'
#         return io.BytesIO(self.files[name])
# 
#     def _save(self, name, content):
#         content = content.read()
#         assert isinstance(content, bytes)
#         self.files[name] = content
#         return name
# 
#     def delete(self, name):
#         self.files.pop(name, None)
# 
#     def exists(self, name):
#         return name in self.files
# 
#     def listdir(self, name):
#         dirs, files = [], []
#         for filename in sorted(self.files):
#             filename = filename[len(name):]
#             if '/' in filename:
#                 dirs.append(filename.partition('/')[0])
#             else:
#                 files.append(filename)
#         return dirs, files
# 
#     def size(self, name):
#         return len(self.files[name])


# Path: gallery/test_imgutil.py
import io
from django.test import TestCase
from django.test.utils import override_settings
from PIL import Image, ImageDraw
from .imgutil import make_thumbnail
from .test_storages import MemoryStorage

    'thumbnail': (8, 8, True),
    'preview': (16, 16, False),
})
class ThumbnailTests(TestCase):

    def setUp(self):
        super().setUp()
        self.storage = MemoryStorage()

    def make_image(self, width, height,
                   image_name='original.jpg', format='JPEG', mode='RGB'):
        make_image(self.storage, image_name, width, height, format, mode)

    def make_thumbnail(self, preset,
                       image_name='original.jpg', thumb_name='thumbnail.jpg'):
        make_thumbnail(image_name, thumb_name, preset,
                       self.storage, self.storage)

    def open_image(self, thumb_name='thumbnail.jpg'):
        return Image.open(self.storage.open(thumb_name))

    def test_horizontal_thumbnail(self):
        self.make_image(48, 36)
        self.make_thumbnail('thumbnail')

        im = self.open_image()
        self.assertEqual(im.size, (8, 8))

    def test_horizontal_preview(self):
        self.make_image(48, 36)

        self.make_thumbnail('preview')