18

I'd like to create a PIL image from raw data. I believe I'm supposed to use PIL.Image.frombytes. But it has a size argument. I don't know the size of the image, isn't that supposed to come as part of the image? I don't know the size of the image in advance. How am I supposed to call the function with no size?

Ram Rachum
  • 84,019
  • 84
  • 236
  • 374
  • If you have the raw image data, then you must have some information about the image's dimensions, pixel format, bit depth, etc. Because otherwise there is no way to "guess" their value. – Jan Spurny Jul 28 '14 at 13:40
  • Could you add some minimal example code demonstrating your problem? – Jan Spurny Jul 28 '14 at 13:41
  • 2
    Perhaps you've misunderstood me. I have a `bytes` object containing the contents of an image file (png, jpg or gif.) Isn't the size contained there? Should I use something other than `frombytes` to load it? I could create a `BytesIO` and use `Image.open` if that's the only way but I think that having to create auxiliary objects for a simple action is stupid, and I hope there's another way. Is there? – Ram Rachum Jul 28 '14 at 14:18
  • yes I have misunderstood you. Because your question is quite misleading. You said wanted help with `Image.frombytes` function to read `raw data`. But `raw data` usually means `raw pixel data`. There was very little from which anyone could have guessed that you actually want just to open image file from memory. – Jan Spurny Jul 28 '14 at 14:30

3 Answers3

20

Since you clarified, that you don't want to read raw pixel data, but rather in-memory image file, the solution is clear: don't use frombytes - it is meant for raw pixel data. Use just open from StringIO:

image = Image.open(StringIO.StringIO(image_data))
Jan Spurny
  • 5,219
  • 1
  • 33
  • 47
9

thanks to @jan-spurny for giving the clue. for anyone else who needs to open an image from bytes

from PIL import Image
import io


image_bytes = ...

im = Image.open(io.BytesIO(image_bytes))
iraj jelodari
  • 3,118
  • 3
  • 35
  • 45
8

The size argument must match the image dimensions, which are not encoded in a raw pixel buffer (e.g. a buffer of length n can represent any grid of k×m pixels for k, m > 0, k×m = n). You have to know this size in advance.

Some example code to demonstrate both tobytes and frombytes:

>>> img = PIL.Image.open("some_image.png")
>>> img.size
(482, 295)
>>> raw = img.tobytes()
>>> img2 = PIL.Image.frombytes(img.mode, img.size, raw)
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • So you're saying that if you open png image in a hex editor, and sent me the hex of the file, I would have no way of knowing the size of the image? – Ram Rachum Jul 28 '14 at 14:20
  • 1
    @RamRachum you've asked wrong question (I suggest edit), from which it looked like you actually have **pixel data** which you want to read - because that's what `Image.frombytes` does. So *larsmans* (and me too in a comment to question) answered that, instead of what you actually needed. – Jan Spurny Jul 28 '14 at 14:26