I'm not sure what the resulting image should look like (do you have an example?), but if you want to unpack an packed image where each pixel has 12 bits into a 16-bit image, you could use this code:
import io
from PIL import Image
rawbytes = b'_\x00`\x00[\x00^\x00`\x00`\x00\\\x00\\\x00Z\x00\\\x00_\x00[\x00\\\x00\\\x00`\x00]\x00\\\x00^\x00_\x00\\\x00\\\x00]\x00]\x00_\x00]\x00]\x00Z\x00\\\x00^\x00\\\x00Z\x00^\x00_\x00]\x00^\x00Z\x00\\\x00Z\x00\\\x00]\x00_\x00]\x00^\x00Z\x00[\x00[\x00X\x00]\x00]\x00Z\x00'
im = Image.frombuffer("I;16", (5, 10), rawbytes, "raw", "I;12")
im.show()
Answer from Michiel Overtoom on Stack OverflowMy function accepts bytes to internaly opens them as a PIL.Image object. The function works as expected when bytes are passed to it. But I would like to write a couple of tests to it. So I need to generate images, turn them into bytes and pass them to my function so that it can turn it again back into an image.
Basically I wanna do something like this:
from PIL import Image from io import BytesIO orig = Image.new(mode='RGBA', size=(240, 60)) image_bytes = orig.tobytes() stream = BytesIO(image_bytes) new = Image.open(stream)
But what I don't understand is that it is not working and I get this Traceback:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "/Users/crane/PycharmProjects/my_project/venv/lib/python3.9/site-packages/PIL/Image.py", line 3030, in open
raise UnidentifiedImageError(
PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x104f86950>How do I convert an bytes image from BytesIO to a PIL image in python? - Stack Overflow
python - PIL cannot identify image file for io.BytesIO object - Stack Overflow
Loading image from bytes
python - How to write PNG image to string with the PIL? - Stack Overflow
(This solution is from the author himself. I have just moved it here.)
SOLUTION:
# This portion is part of my test code
byteImgIO = io.BytesIO()
byteImg = Image.open("some/location/to/a/file/in/my/directories.png")
byteImg.save(byteImgIO, "PNG")
byteImgIO.seek(0)
byteImg = byteImgIO.read()
# Non test code
dataBytesIO = io.BytesIO(byteImg)
Image.open(dataBytesIO)
The problem was with the way that Image.tobytes()was returning the byte object. It appeared to be invalid data and the 'encoding' couldn't be anything other than raw which still appeared to output wrong data since almost every byte appeared in the format \xff\. However, saving the bytes via BytesIO and using the .read() function to read the entire image gave the correct bytes that when needed later could actually be used.
On some cases the same error happens when you are dealing with a Raw Image file such CR2. Example: http://www.rawsamples.ch/raws/canon/g10/RAW_CANON_G10.CR2
when you try to run:
byteImg = Image.open("RAW_CANON_G10.CR2")
You will get this error:
OSError: cannot identify image file 'RAW_CANON_G10.CR2'
So you need to convert the image using rawkit first, here is an example how to do it:
from io import BytesIO
from PIL import Image, ImageFile
import numpy
from rawkit import raw
def convert_cr2_to_jpg(raw_image):
raw_image_process = raw.Raw(raw_image)
buffered_image = numpy.array(raw_image_process.to_buffer())
if raw_image_process.metadata.orientation == 0:
jpg_image_height = raw_image_process.metadata.height
jpg_image_width = raw_image_process.metadata.width
else:
jpg_image_height = raw_image_process.metadata.width
jpg_image_width = raw_image_process.metadata.height
jpg_image = Image.frombytes('RGB', (jpg_image_width, jpg_image_height), buffered_image)
return jpg_image
byteImg = convert_cr2_to_jpg("RAW_CANON_G10.CR2")
Code credit if for mateusz-michalik on GitHub (https://github.com/mateusz-michalik/cr2-to-jpg/blob/master/cr2-to-jpg.py)
You can use the BytesIO class to get a wrapper around strings that behaves like a file. The BytesIO object provides the same interface as a file, but saves the contents just in memory:
import io
with io.BytesIO() as output:
image.save(output, format="GIF")
contents = output.getvalue()
You have to explicitly specify the output format with the format parameter, otherwise PIL will raise an error when trying to automatically detect it.
If you loaded the image from a file it has a format property that contains the original file format, so in this case you can use format=image.format.
In old Python 2 versions before introduction of the io module you would have used the StringIO module instead.
For Python3 it is required to use BytesIO:
from io import BytesIO
from PIL import Image, ImageDraw
image = Image.new("RGB", (300, 50))
draw = ImageDraw.Draw(image)
draw.text((0, 0), "This text is drawn on image")
byte_io = BytesIO()
image.save(byte_io, 'PNG')
Read more: http://fadeit.dk/blog/post/python3-flask-pil-in-memory-image
So I'm writing a bit of spyware to learn the extents of python, and I'm running into an issue. I need to use BytesIO to save a bytes object to png through memory, and not hard drive. https://github.com/novazzz/screengrabber https://www.reddit.com/r/learnpython/comments/4o9bt8/how_did_this_code_turn_out/ If you have a suggustion that would work, great. It just can't save a png to memory and has to be able to be attached to an email.
