How do I create a pickleable file from a PIL Image object such that you could save those images as a single pickle file then maybe upload to another computer such as a server running PIL and unpickle it there?
You can convert the Image object into data then you can pickle it:
image = {
'pixels': im.tostring(),
'size': im.size,
'mode': im.mode,
}
And back to an Image:
im = Image.fromstring(image['mode'], image['size'], image['pixels'])
NOTE: As astex
mentioned, if you're using Pillow (which is recommended instead of PIL), the tostring()
method is deprecated for tobytes()
. Likewise with fromstring()
for frombytes()
.
Slight variation of Gerald's answer using keyword args
create pickleable object
image = {'data': im.tostring(), 'size':im.size, 'mode':im.mode}
or
image = dict(data=im.tostring(), size=im.size, mode=im.mode)
unpickle back to image
im = Image.fromstring(**image)
From related question Saving a dataset with ImagingCore objects pickle, but seems helpful to include here to expand on other answers.
The other answers are great for how to pull pickleable data out of PIL.Image
.
Persistence of External Objects in the pickle
docs shows how to write your own pickler that can handle custom types. Reworking the sample code for our image case it should be something like this (untested):
import pickle
from PIL import Image # Assuming Pillow
from collections import namedtuple
# Proxy the PIL.Image by storing the bytes.
ImageProxy = namedtuple("ImageProxy", "pixels, size, mode")
class PilPickler(pickle.Pickler):
def persistent_id(self, obj):
if isinstance(obj, Image):
# Create our proxy that (I think) will get pickled instead of a PIL object.
return ImageProxy(
pixels=obj.tobytes(),
size=obj.size,
mode=obj.mode,
)
else:
# Fallback to default pickle.
return None
class PilUnpickler(pickle.Unpickler):
def persistent_load(self, pid):
# pid is the object returned by PilPickler.
if isinstance(pid, ImageProxy):
return Image.frombytes(pid.mode, pid.size, pid.pixels)
else:
# Always raise an error if you cannot return the correct object.
raise pickle.UnpicklingError("unsupported persistent object")
def main():
import io
import pprint
images = [] # [... make images here ...]
# Save the records using our custom PilPickler.
file = io.BytesIO()
PilPickler(file).dump(images)
print("Pickled records:")
pprint.pprint(images)
# Load the records from the pickle data stream.
file.seek(0)
images = PilUnpickler(file).load()
print("Unpickled records:")
pprint.pprint(images)
if __name__ == "__main__":
main()
This custom Pickler solution allows you to keep your existing setup and any PIL.Image
s inside your data structures will get pickled.
© 2022 - 2025 — McMap. All rights reserved.
Image.tostring()
is now deprecated inPillow
in favor ofImage.tobytes()
. For the sake of posterity, it may be better to change the above (or at least leave a note). – Parasang