126

I have this image with size 128 x 128 pixels and RGBA stored as byte values in my memory. But

from PIL import Image

image_data = ... # byte values of the image
image = Image.frombytes('RGBA', (128,128), image_data)
image.show()

throws the exception

ValueError: not enough image data

Why? What am I doing wrong?

Michael Dorner
  • 17,587
  • 13
  • 87
  • 117
  • 2
    the raw data in a `.png` file has headers and compression and stuff, so I don't think you can feed it into `frombytes` and get a coherent result. – Kevin Oct 02 '15 at 13:50
  • How do I get rid of this? – Michael Dorner Oct 02 '15 at 13:51
  • I guess you could open the image with `Image.open("homer.jpg")`, and then call `tobytes` on it to get a buffer suitable for passing to `frombytes`... But there's not much point in doing `image = Image.frombytes(Image.open("homer.jpg").tobytes())` when you can just do `image = Image.open("homer.jpg")`. I'm assuming your actual use case is more complicated and you can't do the latter for some reason. – Kevin Oct 02 '15 at 13:55
  • But I do not want to start at a stored file, but a in-memory bytes-array (coming directly from a socket). – Michael Dorner Oct 02 '15 at 13:57
  • 2
    So your actual question is "how do I read data from a socket?"? – Kevin Oct 02 '15 at 14:00
  • 3
    No, this works already. But instead of _socket -> store image to file -> load from this file -> done_ I want _socket -> done_ . I tried to make the question a little bit more clear! – Michael Dorner Oct 02 '15 at 14:03

2 Answers2

362

The documentation for Image.open says that it can accept a file-like object, so you should be able to pass in a io.BytesIO object created from the bytes object containing the encoded image:

from PIL import Image
import io

image_data = ... # byte values of the image
image = Image.open(io.BytesIO(image_data))
image.show()
Michael Dorner
  • 17,587
  • 13
  • 87
  • 117
Colonel Thirty Two
  • 23,953
  • 8
  • 45
  • 85
  • 4
    Doesn't `Image.open` or `io.BytesIO` needs to know what image format it is being given somehow? – jeromej Oct 03 '17 at 22:10
  • 14
    @JeromeJ Most image formats have a header that identifies the format in use. Pillow uses that to identify the image. See [the PNG header](https://en.wikipedia.org/wiki/Portable_Network_Graphics#File_header) for an example. – Colonel Thirty Two Oct 04 '17 at 00:08
  • This answer is right, just as suggested in the documentation. But, it is still not clear to me what they mean in the documentation by "Note that this function decodes pixel data only, not entire images." when referring to the .fromBytes() method. Any ideas? – BluePython Nov 12 '17 at 09:23
  • 2
    @BluePython `fromBytes` is for raw arrays of pixels, such as a `width*height` long array of `RGBA` values. `open` is for images encoded in a specific format, such as PNG or JPEG, that usually compress the pixel data and may have other data that needs dealing with, such as headers or EXIF info. – Colonel Thirty Two Nov 14 '17 at 13:27
  • 5
    I love how this answer has 10x more upvotes than the accepted one. Also got one from me, since it's a lot better. – user136036 Jan 17 '20 at 20:36
  • 2
    @user136036 I woudn't say it's better, because it uses a different function which is used in different situation that the one OP asked about. OP asked about opening raw image data, this answer shows how to open general image files. But it's still a useful answer for some people (including me). – Jakub Smetana Mar 15 '20 at 22:00
  • 1
    It loses the mode RGB and just has one channel – Gaurav Anand Jun 18 '20 at 16:46
  • Hi, thanks for the answer,..just confirming, the io.BytesIO(image_data)) will create a buffer of image_data in the ram and will return a file-like object. Have I understood it correctly? – Thunder Mar 08 '21 at 04:54
27

You can try this:

image = Image.frombytes('RGBA', (128,128), image_data, 'raw')
Source Code:
def frombytes(mode, size, data, decoder_name="raw", *args):
    param mode: The image mode.
    param size: The image size.
    param data: A byte buffer containing raw data for the given mode.
    param decoder_name: What decoder to use.
Marvelous Jie
  • 302
  • 3
  • 3
  • 2
    The [Image.frombuffer()](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.frombuffer) function can be also useful, as it doesn't create a new buffer, but instead uses (if possible) the original buffer. – Jakub Smetana Mar 15 '20 at 22:04
  • 1
    This answer is unusable due to Image.frombytes lacks good description. I just want to pass jpg image through curl and get problems due to frombytes say completly nothing about what to do with compressed images – Marat Zakirov Apr 29 '20 at 16:20
  • 4
    > Note that this function decodes pixel data only, not entire images. If you have an entire image in a string, wrap it in a BytesIO object, and use open() to load it. – Mattwmaster58 May 06 '20 at 18:44