Repository: python-pillow/Pillow

Issue:
JPEG 2K, PyImaging_Jpeg2KDecoderNew function takes at most 6 arguments (7 given)
### What did you do?
Try to upload a JPEG 2000

### What did you expect to happen?
Validate width and height

### What actually happened?
Exception

### What versions of Pillow and Python are you using?
Pillow 5.0.0
Python 2.7.12

Image: http://ghpublic.s3-us-west-1.amazonaws.com/relax.jp2

> TypeError: function takes at most 6 arguments (7 given)
>   File "django/core/handlers/exception.py", line 41, in inner
>     response = get_response(request)
>   File "django/core/handlers/base.py", line 249, in _legacy_get_response
>     response = self._get_response(request)
>   File "django/core/handlers/base.py", line 187, in _get_response
>     response = self.process_exception_by_middleware(e, request)
>   File "django/core/handlers/base.py", line 185, in _get_response
>     response = wrapped_callback(request, *callback_args, **callback_kwargs)
>   File "newrelic/hooks/framework_django.py", line 527, in wrapper
>     return wrapped(*args, **kwargs)
>   File "django/contrib/auth/decorators.py", line 23, in _wrapped_view
>     return view_func(request, *args, **kwargs)
>   File "gh_admin/views.py", line 917, in ajax_image_uploader
>     if None in [image.image.height, image.image.width]:
>   File "django/core/files/images.py", line 23, in height
>     return self._get_image_dimensions()[1]
>   File "django/core/files/images.py", line 29, in _get_image_dimensions
>     self._dimensions_cache = get_image_dimensions(self, close=close)
>   File "django/core/files/images.py", line 59, in get_image_dimensions
>     p.feed(data)
>   File "PIL/ImageFile.py", line 411, in feed
>     self.decoder = Image._getdecoder(im.mode, d, a, im.decoderconfig)
> ```
> a | ['jp2', 0, 0, -1, 1024, <_io.BytesIO object at 0x7f67f5a86710>]
> d | 'jpeg2k'
> data | '\x00\x00\x00\x0cjP  \r\n\x87\n\x00\x00\x00\x14ftypjp2 \x00\x00\x00\x00jp2 \x00\x00\x01Yjp2h\x00\x00\x00\x16ihdr\x00\x00\x01,\x00\x00\x01\x90\x00\x03\x07\x07\x01\x00\x00\x00\x01!colr\x02\x00\x00\x00\x00\x01\x16\x00\x00\x00\x00\x02 \x00\x00scnrRGB XYZ \x07\xd1\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00acsp\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\xf6\xd6\x00\x01\x00\x00\x00\x00\xd3-\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\...
> e | [0, 0, 400, 300]
> flag | False
> fp | <_io.BytesIO object at 0x7f67f5a86710>
> im | <PIL.Jpeg2KImagePlugin.Jpeg2KImageFile image mode=RGB size=400x300 at 0x7F67F5C7EA90>
> o | 0
> self | <PIL.ImageFile.Parser object at 0x7f67f5d8a290>
> ```
>   File "PIL/Image.py", line 435, in _getdecoder
>     return decoder(mode, *args + extra)
>  ```
> args | ['jp2', 0, 0, -1, 1024, <_io.BytesIO object at 0x7f67f5a86710>]
> decoder | <built-in function jpeg2k_decoder>
> decoder_name | 'jpeg2k'
> extra | []
> mode | 'RGB'
> ```

On PyImaging_Jpeg2KDecoderNew


Discussion:
Hi. Thanks for the traceback. Could you provide us with a few lines of code to reproduce the exception?
Making the example we have realized that the issue is not related to Pillow. Sorry guys.
I found how you can reproduce it.

Python 2.7.12
Django 1.11
Pillow 5.0.0

```python
from django.core.files.images import get_image_dimensions
get_image_dimensions('/tmp/relax.jp2')

/lib/python2.7/site-packages/django/core/files/images.pyc in get_image_dimensions(file_or_path, close)
     57                 break
     58             try:
---> 59                 p.feed(data)
     60             except zlib.error as e:
     61                 # ignore zlib complaining on truncated stream, just feed more

/lib/python2.7/site-packages/PIL/ImageFile.pyc in feed(self, data)
    409                     im.tile = []
    410                     self.decoder = Image._getdecoder(
--> 411                         im.mode, d, a, im.decoderconfig
    412                         )
    413                     self.decoder.setimage(im.im, e)

/lib/python2.7/site-packages/PIL/Image.pyc in _getdecoder(mode, decoder_name, args, extra)
    433         decoder = getattr(core, decoder_name + "_decoder")
    434         # print(decoder, mode, args + extra)
--> 435         return decoder(mode, *args + extra)
    436     except AttributeError:
    437         raise IOError("decoder %s not available" % decoder_name)

TypeError: function takes at most 6 arguments (7 given)
```
Okay. So here is code to reproduce the problem without Django -

```python
from PIL import ImageFile
with open('relax.jp2', 'rb') as f:
	data = f.read()
p = ImageFile.Parser()
p.feed(data)
```

This also happens with the .jp2 Pillow test images, except for unbound_variable.jp2
FWIW, I'm having the same issue with Pillow 5.0.0, python 3.6.3 and Django 2.0.2.
Looks like Pillow 3.3.0 has the `TypeError` and 3.2.0 does not.

git bisect points to d3b0413780cf687204df458e0d796de238eec149 as the first bad commit. It's parent 9f48b1e3d686a72db36aa13a90d7c76477c35f26 has no error.

The `TypeError` comes from here:
https://github.com/python-pillow/Pillow/blob/b9f688301a1c9fa057d2892ba2abb2fa53ba066d/src/PIL/ImageFile.py#L406-L412

(The single-letter variables are elsewhere `decoder_name`, `extents`, `offset`, `args`.)

Where:
* `a == ('jp2', 0, 0, -1, 16298L, <_io.BytesIO object at 0x1088236b0>)` in d3b0413780cf687204df458e0d796de238eec149
* `a == ('jp2', 0, 0, -1, 16298L)` in 3.2.0

And this change in Jpeg2KImagePlugin.py is the culprit:

https://github.com/python-pillow/Pillow/commit/d3b0413780cf687204df458e0d796de238eec149#diff-d690458820fedd3e2fd4224a2113bc8eL195

Removing `self.fp` at least removes the TypeError.

Resolving patch:
diff --git a/src/PIL/Jpeg2KImagePlugin.py b/src/PIL/Jpeg2KImagePlugin.py
--- a/src/PIL/Jpeg2KImagePlugin.py
+++ b/src/PIL/Jpeg2KImagePlugin.py
@@ -192,7 +192,7 @@ def _open(self):
                 length = -1
 
         self.tile = [('jpeg2k', (0, 0) + self.size, 0,
-                      (self.codec, self.reduce, self.layers, fd, length, self.fp))]
+                      (self.codec, self.reduce, self.layers, fd, length))]
 
     def load(self):
         if self.reduce:


Test patch:
diff --git a/Tests/test_file_jpeg2k.py b/Tests/test_file_jpeg2k.py
--- a/Tests/test_file_jpeg2k.py
+++ b/Tests/test_file_jpeg2k.py
@@ -176,6 +176,19 @@ def test_unbound_local(self):
         with self.assertRaises(IOError):
             Image.open('Tests/images/unbound_variable.jp2')
 
+    def test_parser_feed(self):
+        # Arrange
+        from PIL import ImageFile
+        with open('Tests/images/test-card-lossless.jp2', 'rb') as f:
+            data = f.read()
+
+        # Act
+        p = ImageFile.Parser()
+        p.feed(data)
+
+        # Assert
+        self.assertEqual(p.image.size, (640, 480))
+
 
 if __name__ == '__main__':
     unittest.main()