Commits

Luke Plant committed 0b2a898

[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

Comments (0)

Files changed (2)

django/core/files/images.py

         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
     finally:
         if close:
             file.close()
+        else:
+            file.seek(file_pos)

tests/regressiontests/file_storage/tests.py

             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)