I'm trying to paste a png on a jpg. Here is the code:
#!/usr/bin/env python3
from PIL import Image
from PIL import ImageDraw
im = Image.open("existing.jpg")
logo = Image.open("python-32.png")
back = Image.new('RGBA', im.size)
back.paste(im)
poly = Image.new('RGBA', (512,512))
pdraw = ImageDraw.Draw(poly)
pdraw.polygon([(128,128),(384,384),(128,384),(384,128)],
fill=(255,255,255,127),outline=(255,255,255,255))
back.paste(poly, (0,0), mask=poly)
back.paste(logo, (im.size[0]-logo.size[0], im.size[1]-logo.size[1]), mask=logo)
back.show()
When I execute the code above, I can see that a PNG image is shown with a random name like tmpc8rb455z.PNG.
I also try to save it with the format jpg but failed. Meaning that when I add back.save('res.jpg', 'JPEG') and execute it, I get such an error:
Traceback (most recent call last):
File "test.py", line 32, in <module>
back.save('res.jpg', 'JPEG')
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/Image.py", line 1893, in save
save_handler(self, fp, filename)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/PIL/JpegImagePlugin.py", line 604, in _save
raise IOError("cannot write mode %s as JPEG" % im.mode)
OSError: cannot write mode RGBA as JPEG
Then I try to save it as PNG:
back.save('res.png')
It works but the size of res.png is 5 times larger than existing.jpg. I can not accept such a huge image.
You're attempting to save an RGBA image in the JPEG format, which does not support transparency (A in RGBA stands for Alpha channel).
It works when you save it as a PNG, because that format supports transparency, but the file size tends to be larger because PNG doesn't compress image data as much as JPEG.
If you want to save PIL images as JPEG, you will need to first convert it to RGB, if transparency isn't important to you. This can be done as follows:
im = im.convert("RGB")
Related
I'm working on a project where I receive a stream of JPEG images over WiFi, convert them to a bytearray, save them as PNG images and read them. The PIL.UnidentifiedImageError occurs when I attempt to open an saved PNG image.
This is how I save the bytearray of JPEG images into PNG images:
idx = random.randint(0,300)
image = Image.open(io.BytesIO(imgdata))
image.save(os.getcwd() + '/Frames/%d.png' % idx)
This is how I open the saved PNG images:
for file in os.listdir('/home/bitcraze/Desktop/AIdeck_examples/NINA/Frames/.'):
print (file)
if file.endswith(".png"):
full_file_path = '/home/Desktop/Frames/' + file
img_file = Image.open(full_file_path)
I checked other posts related to PIL.UnidentifiedImageError and it seems like it could be because the image is corrupted. The picture below shows how I receive the JPEG images:
EDIT: someone suggested I should include how I show the image.
img_loader = GdkPixbuf.PixbufLoader()
img_loader.write(imgdata)
img_loader.close()
pix = img_loader.get_pixbuf()
GLib.idle_add(self._update_image, pix)
The object list_of_contents[0] is based64. I am trying to convert it to it's original image.
image_64_decode = base64.b64decode(list_of_contents[0])
image_result = open('test.jpg', 'wb')
image_result.write(image_64_decode)
img = Image.open(r'C:\Users\st-am\CANCER_APP\test.jpg')
However, I get the following error:
PIL.UnidentifiedImageError: cannot identify image file 'C:\\Users\\st-am\\CANCER_APP\\test.jpg'
Anybody has an idea why PIL cannot identify the image?
Here is the image
I am trying to insert an ICC color profile into an image. Using code from this post as an example my code looks like this:
from PIL import Image, ImageCms
# Read image
img = Image.open(IMG_PATH)
# Read profile
profile = ImageCms.getOpenProfile(PROFILE_PATH)
# Save image with profile
img.save(OUT_IMG_PATH, icc_profile=profile)
I get the following error
Traceback (most recent call last):
File "/home/----/Documents/code_projects/hfss-misc/icc_profiles/insert_icc_profile_into_image.py", line 17, in <module>
img.save(OUT_IMG_PATH, icc_profile=srgb_profile)
File "/home/----/.virtualenvs/color-correction/lib/python3.6/site-packages/PIL/Image.py", line 2102, in save
save_handler(self, fp, filename)
File "/home/----/.virtualenvs/color-correction/lib/python3.6/site-packages/PIL/JpegImagePlugin.py", line 706, in _save
markers.append(icc_profile[:MAX_DATA_BYTES_IN_MARKER])
TypeError: 'PIL._imagingcms.CmsProfile' object is not subscriptable
I thought that there might be a problem with my ICC profile so I tried to use one generated by Pillow.
from PIL import Image, ImageCms
# Read image
img = Image.open(IMG_PATH)
# Creating sRGB profile
profile = ImageCms.createProfile("sRGB")
# Save image with profile
img.save(OUT_IMG_PATH, icc_profile=profile)
I still get the same error, however.
Does anyone know what the cause for this error is?
My system environment is as follows:
Ubuntu 18.04
Python 3.6
Pillow==7.0.0
The answer from github at (https://github.com/python-pillow/Pillow/issues/4464) was to use profile.to_bytes():
img.save(OUT_IMG_PATH, icc_profile=profile.tobytes())
I'm trying to convert a base64 string to image and get the following error.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 2288, in open
% (filename if filename else fp))
IOError: cannot identify image file <cStringIO.StringI object at 0x7fe6d9e88828>
There is no prefix like data:image/png;base64. I get the base64 string from an image and try to convert it back to an image. Here is my code.
# -*- coding: utf-8 -*-
import requests
import base64
from PIL import Image
from cStringIO import StringIO
import zipfile
r = requests.get('https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png', stream=False)
img = Image.open(StringIO(r.content))
b64str = base64.b64encode(img.tobytes())
data = base64.b64decode(b64str)
newimg = Image.open(StringIO(data))
And I get the error above. Can anyone help? Thanks!
You open .PNG file from the web and get the RAW image, which is RGB values, then encode that into base64 and back, which still gives you RAW RGB values which cannot be read by Image.open() because these are not an image file (jpg, png, etc), but RAW RGB values.
The most reasonable would be:
newImg = data # that's it
Or if you want to make an Image:
newImg = Image.frombytes(img.mode, img.size, data)
and get mode and size from the original image.
from PIL import Image
image = Image.open("image.jpg")
file_path = io.BytesIO();
image.save(file_path,'JPEG');
image2 = Image.open(file_path.getvalue());
I get this error TypeError: embedded NUL character on the last statement Image.open on running the program
What is the correct way to open a file from streams?
http://effbot.org/imagingbook/introduction.htm#more-on-reading-images
from PIL import Image
import StringIO
buffer = StringIO.StringIO()
buffer.write(open('image.jpeg', 'rb').read())
buffer.seek(0)
image = Image.open(buffer)
print image
# <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=800x600 at 0x7FE2EEE2B098>
# if we try open again
image = Image.open(buffer)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 2028, in open
raise IOError("cannot identify image file")
IOError: cannot identify image file
Make sure you call buff.seek(0) before reading any StringIO objects. Otherwise you'll be reading from the end of the buffer, which will look like an empty file and is likely causing the error you're seeing.
Using BytesIO is much more simple, it took me a while to figure out. This allows you to read and write to zip files for example.
from PIL import Image
from io import BytesIO
# bytes of a simple 2x2 gif file
gif_bytes = b'\x47\x49\x46\x38\x39\x61\x02\x00\x02\x00\x80\x00\x00\x00\xFF\xFF\xFF\x21\xF9\x04\x00\x00\x00\x00\x00\x2C\x00\x00\x00\x00\x02\x00\x02\x00\x00\x02\x03\x44\x02\x05\x00\x3B'
gif_bytes_io = BytesIO() # or io.BytesIO()
# store the gif bytes to the IO and open as image
gif_bytes_io.write(gif_bytes)
image = Image.open(gif_bytes_io)
# optional proof of concept:
# image.show()
# save as png through a stream
png_bytes_io = BytesIO() # or io.BytesIO()
image.save(png_bytes_io, format='PNG')
print(png_bytes_io.getvalue()) # outputs the byte stream of the png