internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: python-pillow/Pillow

Issue:
Save to PDF broken -> segmentation fault
Hi,

with the pillow version included in Ubuntu 13.04 (2.0.0) I get a segmentation fault with the following code:

  from PIL import Image
  im = Image.new("L",(10,10))
  im.save("test.pdf")

After some debuging I think that the bug was introduced with the commit from 13-03-06 to add qtables support to the JPEG encoder. The code there assumes that the parameter qtables in PyImaging_JpegEncoderNew is set. This is not true when calling ImageFile directly (as the PDF plugin does).

My recommend fix would be setting the qtables local variable to NULL and then checking in get_qtables_arrays that the passed parameter is not NULL (in addition to the Py_None check)

Best regards,
Angel



Discussion:
Thanks,  can you send a pull request with those changes?

With the fix my example works. On the other hand it might be a better idea to pass the JPEG settings to the encoder when saving the image embedded in the PDF. This would require exporting the code in PIL.JpegImagePlugin._save that sets im.encoderconfig. What do you think?

"better" how? I don't have a preference. If it's "cleaner" that way with no other changes (or risks) then feel free to fix


Resolving patch:
diff --git a/PIL/PdfImagePlugin.py b/PIL/PdfImagePlugin.py
--- a/PIL/PdfImagePlugin.py
+++ b/PIL/PdfImagePlugin.py
@@ -149,7 +149,7 @@ def write(self, value):
             im.putdata(data)
         ImageFile._save(im, op, [("hex", (0,0)+im.size, 0, im.mode)])
     elif filter == "/DCTDecode":
-        ImageFile._save(im, op, [("jpeg", (0,0)+im.size, 0, im.mode)])
+        Image.SAVE["JPEG"](im, op, filename)
     elif filter == "/FlateDecode":
         ImageFile._save(im, op, [("zip", (0,0)+im.size, 0, im.mode)])
     elif filter == "/RunLengthDecode":


Test patch:
Repository: python-pillow/Pillow

Issue:
Memory leak when loading corrupted image
Memory seems to be not freed when PIL loads corrupted image.

 This simple script displays that:

``` python
#!/usr/bin/env python

import gc
import resource

from PIL import Image

i = 0L

for x in xrange(1000):
    try:
        Image.open('bad.jpg').load()
    except IOError:
        pass
    i += 1
    if not i % 10:
        print("%i; RSS: %i; Obj: %i"%(i, resource.getrusage(resource.RUSAGE_SELF).ru_maxrss, len(gc.get_objects())))
```

An example of broken image could be found [here](https://raw.github.com/stanvit/pil-memory-issue-201304/master/bad.jpg)

You can find my repo with sample scripts [here](https://github.com/stanvit/pil-memory-issue-201304)

The behaviour is confirmed for, at least, jpeg and png images on the following platforms and PIL/Pillow versions:
- Python 2.7.3/PIL 1.1.7 installed on Debian Linux 3.2.0-3 x86_64, 
- Python 2.7.4/Pillow 2.0.0 on Ubuntu 12.04 32bit (3.5.0-23)
- Python 2.7.1/Pillow 2.0.0 on Mac OS 10.7.5. 



Discussion:
Resource doesn't support Windows but gc object count is a constant value. The memory used by python is steadily growing using both py27 and py3.

edit: after a quick test
edit2: found a flaw in edit code, still looking for leak

edit3: the jpeg decoder is not properly cleaning everything up if he never reaches EOjpegF. JpegDecode.c, the cleanup in case 4 is only used if it is the end of the jpeg-file.
The destructor of the ImagingDecoderObject doesn't seem to catch everything but I don't know how to fix it.
May @wiredfool want to take a look at it.
I've tried to call jpeg_destroy_decompress before the last return after case 4, it closes the leak but screws up the image.

I'll take a look, maybe see what valgrind says. 

So, with your final comment, trying a call to jpeg_destroy_decompress after case 4 is not going to work, since this can get called repeatedly to process the buffer in state 3. (though, I'm not sure how the second if (ok!=1) in state 3 ever gets hit.)

I'm not fresh enough to dig more tonight, since it dives through Image, ImageFile, decode.c JpegImagePlugin, and JpegDecode.c to do this. It looks like it should be calling jpeg_destroy_decompress on an error from within the jpeg library. 

This one looks important-ish. :smiling_imp: 

Yeah, my bandwidth got dropped by 80 degree days. I'm still planning on digging on this.


Resolving patch:
diff --git a/PIL/ImageFile.py b/PIL/ImageFile.py
--- a/PIL/ImageFile.py
+++ b/PIL/ImageFile.py
@@ -209,6 +209,10 @@ def load(self):
                     if not s: # truncated jpeg
                         self.tile = []
 
+                        # JpegDecode needs to clean things up here either way
+                        # If we don't destroy the decompressor, we have a memory leak.
+                        d.cleanup()
+                        
                         if LOAD_TRUNCATED_IMAGES:
                             break
                         else:


Test patch:
Repository: python-pillow/Pillow

Issue:
Image opened twice if imagemagick and xv are installed
If ImageMagick and xv are both installed and you call Image.show() it will open the image twice, once with display and once with xv. This is probably related to the for loop over registered viewers. Not sure why the return 1 isn't working though.



Discussion:

Resolving patch:
diff --git a/PIL/ImageShow.py b/PIL/ImageShow.py
--- a/PIL/ImageShow.py
+++ b/PIL/ImageShow.py
@@ -65,7 +65,7 @@ def show(self, image, **options):
         if base != image.mode and image.mode != "1":
             image = image.convert(base)
 
-        self.show_image(image, **options)
+        return self.show_image(image, **options)
 
     # hook methods
 


Test patch:
Repository: python-pillow/Pillow

Issue:
"Image.convert" documentation is wrong when converting to bilevel
http://pillow.readthedocs.org/en/latest/reference/Image.html#PIL.Image.Image.convert states than converting to bilevel work in the following way: "When translating a greyscale image into a bilevel image (mode “1”), all non-zero values are set to 255 (white). To use other thresholds, use the point() method.". This is not actually true, FLOYDSTEINBERG is used by default.



Discussion:
Yep. Looks like that behavior and documentation dates back to prefork PIL. 


Resolving patch:
diff --git a/PIL/Image.py b/PIL/Image.py
--- a/PIL/Image.py
+++ b/PIL/Image.py
@@ -675,15 +675,18 @@ def convert(self, mode=None, matrix=None, dither=None,
 
             L = R * 299/1000 + G * 587/1000 + B * 114/1000
 
-        When translating a greyscale image into a bilevel image (mode
-        "1"), all non-zero values are set to 255 (white). To use other
-        thresholds, use the :py:meth:`~PIL.Image.Image.point` method.
+        The default method of converting a greyscale ("L") or "RGB"
+        image into a bilevel (mode "1") image uses Floyd-Steinberg
+        dither to approximate the original image luminosity levels. If
+        dither is NONE, all non-zero values are set to 255 (white). To
+        use other thresholds, use the :py:meth:`~PIL.Image.Image.point`
+        method.
 
         :param mode: The requested mode.
         :param matrix: An optional conversion matrix.  If given, this
            should be 4- or 16-tuple containing floating point values.
         :param dither: Dithering method, used when converting from
-           mode "RGB" to "P".
+           mode "RGB" to "P" or from "RGB" or "L" to "1".
            Available methods are NONE or FLOYDSTEINBERG (default).
         :param palette: Palette to use when converting from mode "RGB"
            to "P".  Available palettes are WEB or ADAPTIVE.


Test patch:
Repository: python-pillow/Pillow

Issue:
Loading RGB image with tRNS header ignores transparency
The PNG loader correctly loads palette images with tRNS value, but ignores the tRNS header with RGB images.

Loading RGB image with tRNS header ignores transparency
The PNG loader correctly loads palette images with tRNS value, but ignores the tRNS header with RGB images.



Discussion:

Resolving patch:
diff --git a/PIL/Image.py b/PIL/Image.py
--- a/PIL/Image.py
+++ b/PIL/Image.py
@@ -721,16 +721,10 @@ def convert(self, mode=None, matrix=None, dither=None,
         if dither is None:
             dither = FLOYDSTEINBERG
 
-        # fake a P-mode image, otherwise the transparency will get lost as there is
-        # currently no other way to convert transparency into an RGBA image
-        if self.mode == "L" and mode == "RGBA" and "transparency" in self.info:
-            from PIL import ImagePalette
-            self.mode = "P"
-            bytePalette = bytes(bytearray([i//3 for i in range(768)]))
-            self.palette = ImagePalette.raw("RGB", bytePalette)
-            self.palette.dirty = 1
-            self.load()
-
+        # Use transparent conversion to promote from transparent color to an alpha channel.
+        if self.mode in ("L", "RGB") and mode == "RGBA" and "transparency" in self.info:
+            return self._new(self.im.convert_transparent(mode, self.info['transparency']))
+            
         try:
             im = self.im.convert(mode, dither)
         except ValueError:


Test patch:
diff --git a/Tests/images/rgb_trns.png b/Tests/images/rgb_trns.png
new file mode 100644
Binary files /dev/null and b/Tests/images/rgb_trns.png differ
diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py
--- a/Tests/test_file_png.py
+++ b/Tests/test_file_png.py
@@ -150,6 +150,17 @@ def test_load_transparent_p():
     # image has 124 uniqe qlpha values
     assert_equal(len(im.split()[3].getcolors()), 124)
 
+def test_load_transparent_rgb():
+    file = "Tests/images/rgb_trns.png"
+    im = Image.open(file)
+
+    assert_image(im, "RGB", (64, 64))
+    im = im.convert("RGBA")
+    assert_image(im, "RGBA", (64, 64))
+
+    # image has 876 transparent pixels
+    assert_equal(im.split()[3].getcolors()[0][0], 876)
+
 def test_save_p_transparent_palette():
     in_file = "Tests/images/pil123p.png"
     im = Image.open(in_file)
@@ -171,6 +182,10 @@ def test_save_l_transparency():
     file = tempfile("temp.png")
     assert_no_exception(lambda: im.save(file))
 
+    # There are 559 transparent pixels. 
+    im = im.convert('RGBA')
+    assert_equal(im.split()[3].getcolors()[0][0], 559)
+
 def test_save_rgb_single_transparency():
     in_file = "Tests/images/caption_6_33_22.png"
     im = Image.open(in_file)
Repository: python-pillow/Pillow

Issue:
load ico file with ImageFile will raise an exception
> Traceback (most recent call last):
>   File "t.py", line 12, in <module>
>     p.feed(data)
>   File "/.../lib/python2.7/site-packages/PIL/ImageFile.py", line 383, in feed
>     if flag or len(im.tile) != 1:
> TypeError: object of type 'NoneType' has no len()

```
from PIL import ImageFile
data = open('favicon.ico', 'rb').read()
p = ImageFile.Parser()
p.feed(data)
```

I found when excute `im = im.convert('RGBA')` in function frame() of IcoImagePlugin.py file, im.tile will lose and turn to NoneType. 



Discussion:
Does it work if you just read the file directly?

```
from PIL import Image
im = Image.open('favicon.ico')
im = im.convert('RGBA')
```

The parser class isn't always quite as robust as just simply opening and reading the file. 

It works, but im.tile is still None. So in `feed` function when checking condition `len(im.tile) != 1`, the exception will also raise. I guess it is better to set im.tile's value an empty list instead of None.

Can you post the .ico file so I can take a look?

github editor can't support ico file, so i give a link the ico file i use.
http://www.python.org/favicon.ico

Works for me:

```
(vpy27)erics:~/Pillow/Images$ python
Python 2.7.5+ (default, Sep 19 2013, 13:49:51) 
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from PIL import Image
>>> im = Image.open('python.ico')
>>> im.load()
>>> im.size
(48, 48)
>>> im.convert('RGBA')
<PIL.Image.Image image mode=RGBA size=48x48 at 0x955550C>
>>> 
```

What Pillow are you running? 

[[edit]]  I see, you're still running the ImageFile.Parser class. Is there a reason that you're doing that instead of just opening directly?


Resolving patch:
diff --git a/PIL/IcoImagePlugin.py b/PIL/IcoImagePlugin.py
--- a/PIL/IcoImagePlugin.py
+++ b/PIL/IcoImagePlugin.py
@@ -222,6 +222,10 @@ def load(self):
         self.mode = im.mode
         self.size = im.size
 
+
+    def load_seek(self):
+        # Flage the ImageFile.Parser so that it just does all the decode at the end.
+        pass
 #
 # --------------------------------------------------------------------
 


Test patch:
diff --git a/Tests/images/python.ico b/Tests/images/python.ico
new file mode 100644
Binary files /dev/null and b/Tests/images/python.ico differ
diff --git a/Tests/test_imagefile.py b/Tests/test_imagefile.py
--- a/Tests/test_imagefile.py
+++ b/Tests/test_imagefile.py
@@ -57,6 +57,13 @@ def roundtrip(format):
     # https://github.com/python-imaging/Pillow/issues/78
     #assert_exception(IOError, lambda: roundtrip("PDF"))
 
+def test_ico():
+    with open('Tests/images/python.ico', 'rb') as f:
+        data = f.read()
+    p = ImageFile.Parser()
+    p.feed(data)
+    assert_equal((48,48), p.image.size)
+
 def test_safeblock():
 
     im1 = lena()
Repository: python-pillow/Pillow

Issue:
PNG transparency keyword ignored
In PngImagePlugin.py around line 564 we have the following:

```
    transparency = im.encoderinfo.get('transparency',im.info.get('transparency', None))

    if transparency:
        if im.mode == "P":
            ...
```

For paletted images you are supposed to give the palette index number for the color you want to be transparent. When that number is 0 you will never enter the if block. So maybe it should be something like:

```
    if transparency is not None:
        if im.mode == "P":
            ...
```



Discussion:

Resolving patch:
diff --git a/PIL/PngImagePlugin.py b/PIL/PngImagePlugin.py
--- a/PIL/PngImagePlugin.py
+++ b/PIL/PngImagePlugin.py
@@ -561,7 +561,7 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
 
     transparency = im.encoderinfo.get('transparency',im.info.get('transparency', None))
     
-    if transparency:
+    if transparency or transparency == 0:
         if im.mode == "P":
             # limit to actual palette size
             alpha_bytes = 2**bits


Test patch:
Repository: python-pillow/Pillow

Issue:
Image.paste() is documented to return an Image, but doesn't.
The Image.paste() docstring says it returns an Image, but the operation is actually in-place and returns nothing. The documentation should be updated to match the real behaviour.

This bug is also present in PIL.



Discussion:

Resolving patch:
diff --git a/PIL/Image.py b/PIL/Image.py
--- a/PIL/Image.py
+++ b/PIL/Image.py
@@ -1098,7 +1098,6 @@ def paste(self, im, box=None, mask=None):
            third, the box defaults to (0, 0), and the second argument
            is interpreted as a mask image.
         :param mask: An optional mask image.
-        :returns: An :py:class:`~PIL.Image.Image` object.
         """
 
         if isImageType(box) and mask is None:


Test patch:
Repository: python-pillow/Pillow

Issue:
PNG transparency keyword ignored
In PngImagePlugin.py around line 564 we have the following:

```
    transparency = im.encoderinfo.get('transparency',im.info.get('transparency', None))

    if transparency:
        if im.mode == "P":
            ...
```

For paletted images you are supposed to give the palette index number for the color you want to be transparent. When that number is 0 you will never enter the if block. So maybe it should be something like:

```
    if transparency is not None:
        if im.mode == "P":
            ...
```

PNG transparency keyword ignored
In PngImagePlugin.py around line 564 we have the following:

```
    transparency = im.encoderinfo.get('transparency',im.info.get('transparency', None))

    if transparency:
        if im.mode == "P":
            ...
```

For paletted images you are supposed to give the palette index number for the color you want to be transparent. When that number is 0 you will never enter the if block. So maybe it should be something like:

```
    if transparency is not None:
        if im.mode == "P":
            ...
```



Discussion:

Resolving patch:
diff --git a/PIL/PngImagePlugin.py b/PIL/PngImagePlugin.py
--- a/PIL/PngImagePlugin.py
+++ b/PIL/PngImagePlugin.py
@@ -561,7 +561,7 @@ def _save(im, fp, filename, chunk=putchunk, check=0):
 
     transparency = im.encoderinfo.get('transparency',im.info.get('transparency', None))
     
-    if transparency:
+    if transparency or transparency == 0:
         if im.mode == "P":
             # limit to actual palette size
             alpha_bytes = 2**bits


Test patch:
diff --git a/Tests/test_file_png.py b/Tests/test_file_png.py
--- a/Tests/test_file_png.py
+++ b/Tests/test_file_png.py
@@ -251,6 +251,20 @@ def test_trns_rgb():
     im = roundtrip(im, transparency=(0, 1, 2))
     assert_equal(im.info["transparency"], (0, 1, 2))
 
+def test_trns_p():
+    # Check writing a transparency of 0, issue #528
+    im = lena('P')
+    im.info['transparency']=0
+    
+    f = tempfile("temp.png")
+    im.save(f)
+
+    im2 = Image.open(f)
+    assert_true('transparency' in im2.info)
+
+    assert_image_equal(im2.convert('RGBA'), im.convert('RGBA'))
+        
+    
 def test_save_icc_profile_none():
     # check saving files with an ICC profile set to None (omit profile)
     in_file = "Tests/images/icc_profile_none.png"
Repository: python-pillow/Pillow

Issue:
Check libwebp 0.4.0
We should check Pillow with libwebp 0.4.0 prior to the next 2.4 release. 

https://chromium.googlesource.com/webm/libwebp/+/v0.4.0



Discussion:
How do we do that? We probably need our own CI server(s) so we can do things that Travis won't support

I've got an env that's nearly the same as travis, I just need to download & install. Call it discontinuous integration. 

 I noted it here so that it got on the todo list before 2.4. 

Roger that


Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -80,7 +80,8 @@ def _read(file):
 
 try:
     import _tkinter
-except ImportError:
+except (ImportError, OSError):
+    # pypy emits an oserror
     _tkinter = None
 
 


Test patch:
diff --git a/Tests/test_image_point.py b/Tests/test_image_point.py
--- a/Tests/test_image_point.py
+++ b/Tests/test_image_point.py
@@ -2,6 +2,11 @@
 
 from PIL import Image
 
+if hasattr(sys, 'pypy_version_info'):
+    # This takes _forever_ on pypy. Open Bug,
+    # see https://github.com/python-imaging/Pillow/issues/484
+    skip()
+
 def test_sanity():
 
     im = lena()
diff --git a/Tests/test_imagetk.py b/Tests/test_imagetk.py
--- a/Tests/test_imagetk.py
+++ b/Tests/test_imagetk.py
@@ -3,7 +3,7 @@
 from PIL import Image
 try:
     from PIL import ImageTk
-except ImportError as v:
+except (OSError, ImportError) as v:
     skip(v)
 
 success()
Repository: python-pillow/Pillow

Issue:
ImageDraw.textsize() returns incorrect textsize for truetype fonts
`ImageDraw.textsize()` does not return correct `textsize` for truetype fonts.
The return value does not include offset.

So I have to adjust offset using `FreeTypeFont.getoffset()` to get correct `textsize`.

```python
from PIL import Image, ImageDraw, ImageFont

image = Image.new('RGB', (512, 256), (255, 255, 255))
drawer = ImageDraw.Draw(image)
font = ImageFont.truetype('/usr/share/fonts/truetype/freefont/FreeSerif.ttf', 32)

# drawing text
STRING = 'Hello, python language!'
drawer.text((10, 10), STRING, fill='black', font=font)

# drawing rectangle surrounding text
size = drawer.textsize(STRING, font=font)
offset = font.getoffset(STRING)
drawer.rectangle((10, 10, 10 + size[0] + offset[0], 10 + size[1] + offset[1]), outline='black')

image.save('example.png', 'PNG')
```

is this correct way?

And, I think `ImageDraw.textsize()` should return `textsize` including offset.



Discussion:

Resolving patch:
diff --git a/PIL/ImageFont.py b/PIL/ImageFont.py
--- a/PIL/ImageFont.py
+++ b/PIL/ImageFont.py
@@ -140,7 +140,8 @@ def getmetrics(self):
         return self.font.ascent, self.font.descent
 
     def getsize(self, text):
-        return self.font.getsize(text)[0]
+        size, offset = self.font.getsize(text)
+        return (size[0] + offset[0], size[1] + offset[1])
 
     def getoffset(self, text):
         return self.font.getsize(text)[1]


Test patch:
diff --git a/Tests/images/rectangle_surrounding_text.png b/Tests/images/rectangle_surrounding_text.png
new file mode 100644
Binary files /dev/null and b/Tests/images/rectangle_surrounding_text.png differ
diff --git a/Tests/test_imagefont.py b/Tests/test_imagefont.py
--- a/Tests/test_imagefont.py
+++ b/Tests/test_imagefont.py
@@ -71,11 +71,25 @@ def test_render_equal(self):
             self.assert_image_equal(img_path, img_filelike)
             self._clean()
 
+        def test_textsize_equal(self):
+            im = Image.new(mode='RGB', size=(300, 100))
+            draw = ImageDraw.Draw(im)
+            ttf = ImageFont.truetype(font_path, font_size)
+
+            txt = "Hello World!"
+            size = draw.textsize(txt, ttf)
+            draw.text((10, 10), txt, font=ttf)
+            draw.rectangle((10, 10, 10 + size[0], 10 + size[1]))
+
+            target = 'Tests/images/rectangle_surrounding_text.png'
+            target_img = Image.open(target)
+            self.assert_image_equal(im, target_img)
+
         def test_render_multiline(self):
             im = Image.new(mode='RGB', size=(300, 100))
             draw = ImageDraw.Draw(im)
             ttf = ImageFont.truetype(font_path, font_size)
-            line_spacing = draw.textsize('A', font=ttf)[1] + 8
+            line_spacing = draw.textsize('A', font=ttf)[1] + 4
             lines = ['hey you', 'you are awesome', 'this looks awkward']
             y = 0
             for line in lines: