17

I want use PIL .save() method for export my PIL image list to pdf.

in the PIL document , saving part say: enter image description here => we can use append_images option for pdf format.

and in pillow's github page , this issue say : Added append_images to PDF saving #2526

I wrote this code:

import PIL
im1 = PIL.Image.open("1.jpg").convert("RGB")
im2 = PIL.Image.open("2.jpg").convert("RGB")
im3 = PIL.Image.open("3.jpg").convert("RGB")
images = [im1,im2,im3]
images[0].save("out.pdf", save_all=True, append_images=images[1:])

but it doesn't work!

These errors raised:

Traceback (most recent call last):
  File "sample.py", line 13, in <module>
gif.save("out.pdf", save_all=True, append_images=images)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/Image.py", line 1928, in save
save_handler(self, fp, filename)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/PdfImagePlugin.py", line 55, in _save_all
_save(im, fp, filename, save_all=True)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/PdfImagePlugin.py", line 182, in _save
Image.SAVE["JPEG"](im, op, filename)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/JpegImagePlugin.py", line 609, in _save
info = im.encoderinfo
AttributeError: 'Image' object has no attribute 'encoderinfo'
Nimantha
  • 6,405
  • 6
  • 28
  • 69
mkal
  • 223
  • 1
  • 2
  • 10
  • Trivial, but you should write `append_images=images` instead. You can also change your import statement to `from PIL import Image` and then just use `Image.open(..)`. – Vasilis G. Nov 15 '17 at 13:38
  • @VasilisG. ok. but errors don't solved ! :| – mkal Nov 15 '17 at 13:44
  • Take a look [here](https://stackoverflow.com/questions/27327513/create-pdf-from-a-list-of-images). Other than that, I cannot think of something else. – Vasilis G. Nov 15 '17 at 13:55
  • The PDF format is _not_ an image format (although it can contain one or more of them), so PIL/Pillow doesn't know how to save an image in that format. You need to use some other module to create PDF files (and presumably allow you to add images to them). [`reportlab`](https://pypi.python.org/pypi?%3Aaction=search&term=reportlab&submit=search) might be a good one. – martineau Nov 15 '17 at 14:02
  • @martineau recent versions of Pillow can _save_ PDF (I just tested it), but it can't read it. – PM 2Ring Nov 15 '17 at 14:16
  • @martineau tank you . i can export one image to pdf by PIL very easily ... and newly PIL added this feature for multiframe image ! – mkal Nov 15 '17 at 14:24
  • 1
    I think this is a bug. Using Pillow 4.3.0 on Python 3.6.0 I can easily save a single PDF image. And I can call the `.save` method with the `append_images` arg to write a correct multiframe GIF. And if the source images are GIF, I can even save a multiframe PDF, but when I inspect the resulting PDF file it's not correct. I used 3 images in my test, and the output PDF consists of 3 pages, each containing 3 images in a column, with the top and bottom images appearing to be the 1st image in my list, and the middle image an incorrectly decoded version of my 1st image. :( – PM 2Ring Nov 15 '17 at 14:25
  • mkal: I didn't realize the Pillow had added that enhancement—it's been a while since I've used or paid much attention to its latest enhancements. I suspect @PM2Ring is likely correct about it being a bug, as I have encountered a couple of them in past releases. Nice thing is you can get them fixed by reporting them to the developers (unlike with `PIL` nowadays). – martineau Nov 15 '17 at 15:21
  • Meanwhile, as a workaround, you can use `reportlab` along with what is described in this [answer](https://stackoverflow.com/a/12627459/355230) to a related question to get a quick start. – martineau Nov 15 '17 at 15:47
  • @VasilisG. This statement isn't correct "Trivial, but you should write append_images=images instead." If the first image in the sequence is images[0], and the appended images are images[1:], then you will be appending page 1, when it has already been added as the first image. – Matts Apr 22 '20 at 02:28

3 Answers3

6

Try this format

from PIL import Image
im1 = PIL.Image.open("1.jpg").convert("RGB")
im2 = PIL.Image.open("2.jpg").convert("RGB")
im3 = PIL.Image.open("3.jpg").convert("RGB")
images = [im2,im3]
im1.save("out.pdf", save_all=True, append_images=images)
murty kalyan
  • 71
  • 1
  • 1
  • 1
    The problem isn't that the OP's code is wrong, it's that the version of PIL that they were using had a bug. Posting a slightly reordered version of the OP's code is not useful. – snakecharmerb Aug 16 '20 at 11:50
2

This problem is solved in PIL ver 5.0.0 (https://pillow.readthedocs.io/en/latest/).

mkal
  • 223
  • 1
  • 2
  • 10
  • 17
    Could you link to the actual part in the docs that says how to do this? – Daniel Porteous Sep 30 '19 at 02:20
  • For posterity, the documentation for the `Image.save()` method can be found [here](https://pillow.readthedocs.io/en/latest/reference/Image.html#PIL.Image.Image.save) and the list of supported file formats and the corresponding parameters that can be passed to `Image.save()` can be found [here](https://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html) ([PDF file format](https://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html#pdf)). – Jacob Lee Feb 21 '22 at 16:50
-3

Somewhat off topic, but if you have a large number of images to convert, using list comprehension is the way to go.

from PIL import Image

im1=Image.open('1.png').convert('RGB')
images = [Image.open(f”{imgNumber}.png”).convert('RGB') for imgNumber in range(2, 100)]
im1.save("imgBook.PDF", save_all=True, append_images=images)
Jacob Lee
  • 4,405
  • 2
  • 16
  • 37
0x029A
  • 7
  • 1
  • List comprehension sacrifices readability in this case and it quite unnecessary; using a standard `for` lop would be better in this scenario. – Jacob Lee Feb 21 '22 at 06:10
  • 1
    It doesn't sacrifice readability if you comprehend list comprehension ;) – 0x029A Feb 22 '22 at 13:54
  • No, it still does sacrifice readability. ;) – Jacob Lee Feb 22 '22 at 14:56
  • 1
    Have to disagree with ya there bud. List comprehension is generally considered more readable and pythonic. Worthwhile to look into & understand. https://towardsdatascience.com/python-basics-list-comprehensions-631278f22c40 – 0x029A Feb 23 '22 at 15:23