From ec8d04cffe720477908c7668018102768eb43083 Mon Sep 17 00:00:00 2001 From: Luke Plant Date: Fri, 10 Sep 2010 18:49:45 +0000 Subject: [PATCH] [1.2.X] Fixed #11158 - get_image_dimensions very slow/incorrect after 1 call Thanks to kua for the report, and to kua, SmileyChris and SAn for the patch Backport of [13715] from trunk git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@13716 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/files/images.py | 19 ++++++++++++------- tests/regressiontests/file_storage/tests.py | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/django/core/files/images.py b/django/core/files/images.py index 55008b548a..228a7118c5 100644 --- a/django/core/files/images.py +++ b/django/core/files/images.py @@ -23,23 +23,26 @@ class ImageFile(File): if not hasattr(self, '_dimensions_cache'): close = self.closed self.open() - self._dimensions_cache = get_image_dimensions(self) - if close: - self.close() + self._dimensions_cache = get_image_dimensions(self, close=close) return self._dimensions_cache -def get_image_dimensions(file_or_path): - """Returns the (width, height) of an image, given an open file or a path.""" +def get_image_dimensions(file_or_path, close=False): + """ + Returns the (width, height) of an image, given an open file or a path. Set + 'close' to True to close the file at the end if it is initially in an open + state. + """ # Try to import PIL in either of the two ways it can end up installed. try: from PIL import ImageFile as PILImageFile except ImportError: import ImageFile as PILImageFile - + p = PILImageFile.Parser() - close = False if hasattr(file_or_path, 'read'): file = file_or_path + file_pos = file.tell() + file.seek(0) else: file = open(file_or_path, 'rb') close = True @@ -55,3 +58,5 @@ def get_image_dimensions(file_or_path): finally: if close: file.close() + else: + file.seek(file_pos) diff --git a/tests/regressiontests/file_storage/tests.py b/tests/regressiontests/file_storage/tests.py index 2c5f0f4551..a1470f9f05 100644 --- a/tests/regressiontests/file_storage/tests.py +++ b/tests/regressiontests/file_storage/tests.py @@ -230,3 +230,19 @@ if Image is not None: finally: del images.open self.assert_(FileWrapper._closed) + + class InconsistentGetImageDimensionsBug(TestCase): + """ + Test that get_image_dimensions() works properly after various calls using a file handler (#11158) + """ + def test_multiple_calls(self): + """ + Multiple calls of get_image_dimensions() should return the same size. + """ + from django.core.files.images import ImageFile + img_path = os.path.join(os.path.dirname(__file__), "test.png") + image = ImageFile(open(img_path)) + image_pil = Image.open(img_path) + size_1, size_2 = get_image_dimensions(image), get_image_dimensions(image) + self.assertEqual(image_pil.size, size_1) + self.assertEqual(size_1, size_2)