I am attempting to convert a tiff  file into a PDF using Pillow and PyPDF. I was able to get this to work using an earlier version of Pillow, although I cannot which version.
I recently upgraded to Pillow 3.1.0, and now I ran into issues. This is the previously working code.
import os
import traceback
from PIL import Image
from PyPDF2 import PdfFileReader, PdfFileMerger
to_merge = []
with Image.open('my_tif.tif') as img:
    seeker = 0
    while True:
        try: 
            # temp file name for PDF
            img_pdf = 'temp_{}.pdf'.format(seeker)
            #seeks to next image with TIFF
            img.seek(seeker)
            # saves the image as a PDF
            img.save(img_pdf)
            seeker += 1
            to_merge.append(img_pdf)
        except Exception as err:
            traceback.print_exc()
            break                
merger = PdfFileMerger()
for f in to_merge:
    merger.append(PdfFileReader(f))
    os.remove(f)
merger.write('merged.pdf')
Beforehand, it generated a PDF for each image within the tiff and then merged the PDFs together with no problem.
After I upgraded to Pillow 3.1.0 it loops through all of the images, but then throws a ValueError on the final image.
Traceback (most recent call last):
  File "C:/Code/Python/tiff_to_pdf.py", line 16, in <module>
    img.save(img_pdf)
  File "C:\Python27\lib\site-packages\PIL\Image.py", line 1675, in save
    save_handler(self, fp, filename)
  File "C:\Python27\lib\site-packages\PIL\PdfImagePlugin.py", line 155, in _save
    im.seek(pageNumber)
  File "C:\Python27\lib\site-packages\PIL\TiffImagePlugin.py", line 930, in seek
    self._seek(max(frame, 0))  # Questionable backwards compatibility.
  File "C:\Python27\lib\site-packages\PIL\TiffImagePlugin.py", line 956, in _seek
    self.fp.seek(self._frame_pos[frame])
ValueError: I/O operation on closed file
What would be the cause of the ValueError?
Problem
There can be two problems.
Image.Image.seek() 
If the image is a single-frame image, the file will be closed in this
method after the frame is read. If the image is a multi-frame image, (e.g.
multipage TIFF and animated GIF) the image file is left open so that
Image.Image.seek() can load the appropriate frame.
Image.Image.close() 
Closes the file and destroys the core image object.
The Pillow context manager will also close the file, but will not destroy
the core image object.
Solution
If you are using Image.Image.seek() function to read the image and want to
re-use the image again without opening it.
What you can do, is copy the loaded image into another variable and perform operation.
loaded_image = Image.open("test.jpg")
temp = loaded_image.copy()
Now you can use temp.sheek() to read the image and your loaded image
will be safe
If you are not using Image.Image.seek() and facing the same issue then
you are using Image.Image.close() function that is destroying the
image.
So, do not use Image.Image.close() if you want to re use the image.
Solution Source
File Handling in Pillow Read the Image Lifecycle section
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With