2

I would like to save a PIL.ImageTk.PhotoImage into a file. My approach is to create a file "with open" and call the "write" method, but it wont't work, because I don't know how to get the byte-array from the object.

def store_temp_image(data, image):
    new_file_name = data.number + ".jpg"
    with open(os.path.join("/tmp/myapp", new_file_name), mode='wb+') as output:
        output.write(image)

The error message is as follows:

TypeError: a bytes-like object is required, not 'PhotoImage'

I usually find approaches to convert ImageTk Objects into PIL objects, but not the other way round. From the docs I couldn't get any hints neither.

Semo
  • 783
  • 2
  • 17
  • 38

3 Answers3

4

You can first use the ImageTk.getimage() function (scroll down, near the end) to get a PIL Image, and then use its save() method:

def store_temp_image(data, imagetk):
    # do sanity/validation checks here, if need be
    new_file_name = data.number + ".jpg"
    imgpil = ImageTk.getimage( imagetk )
    imgpil.save( os.path.join("/tmp/myapp", new_file_name), "JPEG" )
    imgpil.close()    # just in case (not sure if save() also closes imgpil)
Harry K.
  • 560
  • 3
  • 7
1

Looking at the source code for the ImageTk module, you can see that it actually creates a tkinter.PhotoImage object and stores it as __photo.

self.__photo = tkinter.PhotoImage(**kw)

this attribute is accessible as _PhotoImage__photo (because of the leading __, it's name has been mangled).
Then, to save your image, you can do:

image._PhotoImage__photo.write("/tmp/myapp"+new_file_name)

Be warned that this only supports a very limited choice of file formats. It worked for me with png files, gif files and ppm files, but not with jpg files.

0

Have a look at this...

http://pillow.readthedocs.io/en/3.1.x/reference/ImageTk.html#PIL.ImageTk.PhotoImage

From there you can get the included Image object. Which has a save(...) method that does the job you're expecting.

http://pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.save

Thus this (untested) code should do the job :

def store_temp_image(data, image):
    new_file_name = data.number + ".jpg"
    new_file_path = os.path.join('/tmp/myapp', new_file_name)
    image.image.save(new_file_path)

Hope this helped!

glenfant
  • 1,298
  • 8
  • 9
  • Thank you. The code did not work, but it helped me to learn, that I could simply concatenate the object chain up, until I reach the correct Image.Image object from another class. But I still found no way to convert a PhotoImage to an Image object. Do I have to call "new" method? How do I pass the object correctly? – Semo Aug 03 '17 at 07:57