Repository: python-pillow/Pillow

Issue:
Conversion of image to array fails
Tried to load and convert an image (attached) to a numpy array. Fails on first try, succeeds on second. Strange! 

Guessing cause may be that the image is slightly corrupted, but this is not detected or reported by PIL. 

### What are your OS, Python and Pillow versions?

* OS: Windows 10 pro
* Python: Python 3.7.3 (default, Apr 24 2019, 15:29:51) [MSC v.1915 64 bit (AMD64)] :: Anaconda, Inc. on win32
* Pillow: 6.0.0

![doesNotConvertToArray](https://user-images.githubusercontent.com/8694392/58248803-6ca9ab00-7d5d-11e9-9dc0-ca024bf63915.jpg)

```python
import numpy as np
from PIL import Image
# This image is to some extent corrupted, but is displayed correctly by viewing programs:
im = Image.open("doesNotConvertToArray.jpg") 
a1 = np.asarray(im) # First conversion fails
print(repr(a1))
# Only a singleton object array is printed: 
# array(<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=2703x1018 at 0x1AA4F6E1048>, dtype=object)

a2 = np.asarray(im) # Succeeds, strangely
print(a2.shape) # Prints correct shape: (1018, 2703, 3)
```



Discussion:
I find that if I add in `ImageFile.LOAD_TRUNCATED_IMAGES = True`, it works.
```python
>>> import numpy as np
>>> from PIL import Image, ImageFile
>>> ImageFile.LOAD_TRUNCATED_IMAGES = True
>>> im = Image.open("doesNotConvertToArray.jpg") 
>>> a1 = np.asarray(im)
>>> print(a1.shape)
(1018, 2703, 3)
>>> a2 = np.asarray(im)
>>> print(a2.shape)
(1018, 2703, 3)
```
@sommerfelt Did that help? Okay to close this issue?
I reported the issue more because it indicates a bug in PIL and not so much because it causes a problem for me. In my case  I will use a1.dtype==object to flag a corrupted image rather than cloaking it by setting ImageFile.LOAD_TRUNCATED_IMAGES = True.

So to conclude: For my purposes the issue is closed if I can rely on this behaviour, but for PIL it remains either a bug (an Exception should be raised unless ImageFile.LOAD_TRUNCATED_IMAGES = True) or if you like, it could be called an undocumented feature.

Resolving patch:
diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py
--- a/src/PIL/ImageFile.py
+++ b/src/PIL/ImageFile.py
@@ -243,7 +243,6 @@ def load(self):
                                 if LOAD_TRUNCATED_IMAGES:
                                     break
                                 else:
-                                    self.tile = []
                                     raise IOError(
                                         "image file is truncated "
                                         "(%d bytes not processed)" % len(b)
diff --git a/src/PIL/PngImagePlugin.py b/src/PIL/PngImagePlugin.py
--- a/src/PIL/PngImagePlugin.py
+++ b/src/PIL/PngImagePlugin.py
@@ -612,7 +612,7 @@ def _open(self):
             rawmode, data = self.png.im_palette
             self.palette = ImagePalette.raw(rawmode, data)
 
-        self.__idat = length  # used by load_read()
+        self.__prepare_idat = length  # used by load_prepare()
 
     @property
     def text(self):
@@ -645,6 +645,7 @@ def load_prepare(self):
         if self.info.get("interlace"):
             self.decoderconfig = self.decoderconfig + (1,)
 
+        self.__idat = self.__prepare_idat  # used by load_read()
         ImageFile.ImageFile.load_prepare(self)
 
     def load_read(self, read_bytes):


Test patch:
diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py
--- a/Tests/test_file_jpeg.py
+++ b/Tests/test_file_jpeg.py
@@ -372,6 +372,10 @@ def test_truncated_jpeg_throws_IOError(self):
         with self.assertRaises(IOError):
             im.load()
 
+        # Test that the error is raised if loaded a second time
+        with self.assertRaises(IOError):
+            im.load()
+
     def _n_qtables_helper(self, n, test_file):
         im = Image.open(test_file)
         f = self.tempfile("temp.jpg")
diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py
--- a/Tests/test_imagefile.py
+++ b/Tests/test_imagefile.py
@@ -113,6 +113,10 @@ def test_truncated_with_errors(self):
         with self.assertRaises(IOError):
             im.load()
 
+        # Test that the error is raised if loaded a second time
+        with self.assertRaises(IOError):
+            im.load()
+
     def test_truncated_without_errors(self):
         if "zip_encoder" not in codecs:
             self.skipTest("PNG (zlib) encoder not available")