Hi I'm trying to load my image from Pillow into Pygame using BytesIO.
from PIL import Image
import io
pilImage = Image.open('AgV6E.png')
temp_io = io.BytesIO()
pilImage.save(temp_io, format='PNG')
pygame.image.load(temp_io)
I get the following error:
pygame.image.load(temp_io) pygame.error: Unsupported image format
Strangely enough though simply saving to png works.
from PIL import Image
import io
pilImage = Image.open('AgV6E.png')
pilImage.save("test.png", format='PNG')
pygame.image.load("test.png")
Anybody know how to fix this?
Turns out I needed to run BytesIO.seek(0) before running load to set the stream position back to zero. Here is the updated code.
from PIL import Image
import io
pilImage = Image.open('AgV6E.png')
temp_io = io.BytesIO()
pilImage.save(temp_io, format='PNG')
temp_io.seek(0)
pygame.image.load(temp_io)
seek(0) is probably what allowed it to be read correctly as it moved the stream position back to the beginning.
Thanks to Starbuck5 letting me know the answer.
Related
How can I open an image in pillow that I already opened using open('image','r')
I have an image that I opened using the open() function, but i want to use the image in pillow.
Actually, I encoded it using base64, then the program decodes it,then gives you a variable that is in the same format as the open() function has. Then I just want to show the image, if there is another way to show the image without saving it, please let me know.
Here is the code that I use to decode it, just so you know:
import base64
image_64_encode = 'this-string-is-big-so'
image_64_decode = base64.decodebytes(image_64_encode)
I just want to show the image.
Like this:
from base64 import b64decode
from PIL import Image
import io
# Load useful-looking base64 string of a PNG
b64 = 'iVBORw0KGgoAAAANSUhEUgAAAEAAAABAEAIAAAB1mzrKAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0T///////8JWPfcAAAAB3RJTUUH5QsDDgY2fEahewAAANhJREFUeNrt3LENg0AQRcFFOue4/yIhN9K5jAl4UwHS02flAB977z1h1sxzr1M/xnsVAFszz7W++jHeqwVgBcAKgHUDsBaAFQArANYNwFoAVgCsAFg3AFszv/tz6sd4r15BWAGwbgDWArACYAXACoB1hLEWgBUAKwDWDcBaAFYArADYmvldn24A0wKwAmAFwPodgLUArABYAbBuANYCsAJgBcAKgHWEsRaAFQDr+wCsG4D1CsIKgBUA6wZgLQArAFYArBuAtQCsAFgBsG4A1gKwY++Z/sDe+QP/bITzNFwkpgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMS0xMS0wM1QxNDowNjo1NCswMDowMGz+3A4AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjEtMTEtMDNUMTQ6MDY6NTQrMDA6MDAdo2SyAAAAAElFTkSuQmCC'
# Open it with PIL - no disk access required
im = Image.open(io.BytesIO(b64decode(b64)))
print(im)
# prints: <PIL.PngImagePlugin.PngImageFile image mode=RGB size=64x64 at 0x7FF3B90251C0>
The clue is here in the Pillow documentation where it says:
fp – A filename (string), pathlib.Path object or a file object.
I'm trying to download an svg image and open it in opencv for further processing. What I am doing is to convert from svg to png format with cairosvg, open it using Pillow and finally convert to opencv. The problem here is that the image converted in opencv does not look exactly the same as the one in PIL format.
from io import BytesIO
import numpy as np
import requests
from PIL import Image
from cairosvg import svg2png
import cv2
svg_url = 'https://logincdn.msauth.net/16.000.28611.4/content/images/microsoft_logo_ee5c8d9fb6248c938fd0dc19370e90bd.svg'
# Get svg data
svg_data = requests.get(svg_url).content
# Convert from svg to png
png = svg2png(bytestring=svg_data)
# Open png in PIL
pil_img = Image.open(BytesIO(png))
pil_img.show() # This looks good
# Convert to opencv
cv_img = np.array(pil_img.convert('RGB'))[:, :, ::-1].copy() # Taken from https://stackoverflow.com/questions/14134892/convert-image-from-pil-to-opencv-format
cv2.imshow('cv_img', cv_img) # This does not look right
cv2.waitKey(0)
These are the resulting images from PIL and opencv format respectively:
The opencv image does not look right, e.g. the text does not have space between characters.
Why is that and how can I fix it?
As suggested, you have to preserve alpha channel.
import numpy as np
import requests
from io import BytesIO
from PIL import Image
from cairosvg import svg2png
import cv2
svg_url = 'https://logincdn.msauth.net/16.000.28611.4/content/images/microsoft_logo_ee5c8d9fb6248c938fd0dc19370e90bd.svg'
svg_data = requests.get(svg_url).content
png = svg2png(bytestring=svg_data)
pil_img = Image.open(BytesIO(png)).convert('RGBA')
pil_img.save('output/pil.png')
cv_img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGBA2BGRA)
cv2.imwrite('cv.png', cv_img)
I'd like to work directly with compressed JPEG images. I know that with PIL/Pillow I can compress an image when I save it, and then read back the compressed image - e.g.
from PIL import Image
im1 = Image.open(IMAGE_FILE)
IMAGE_10 = os.path.join('./images/dog10.jpeg')
im1.save(IMAGE_10,"JPEG", quality=10)
im10 = Image.open(IMAGE_10)
but, I'd like a way to do this without the extraneous write and read. Is there some Python package with a function that will take an image and quality number as inputs and return a jpeg version of that image with the given quality?
For in-memory file-like stuff, you can use StringIO.
Take a look:
from io import StringIO # "import StringIO" directly in python2
from PIL import Image
im1 = Image.open(IMAGE_FILE)
# here, we create an empty string buffer
buffer = StringIO.StringIO()
im1.save(buffer, "JPEG", quality=10)
# ... do something else ...
# write the buffer to a file to make sure it worked
with open("./photo-quality10.jpg", "w") as handle:
handle.write(buffer.contents())
If you check the photo-quality10.jpg file, it should be the same image, but with 10% quality as the JPEG compression setting.
Using BytesIO
try:
from cStringIO import StringIO as BytesIO
except ImportError:
from io import BytesIO
def generate(self, image, format='jpeg'):
im = self.generate_image(image)
out = BytesIO()
im.save(out, format=format,quality=75)
out.seek(0)
return out
StringIO is missing in Python3.0, ref to : StringIO in python3
Referring to the answer to this question, I tried to save my own JPG image files, after some basic image processing. I've only applied a rotation and a shear. This is my code:
import numpy as np
import sys
from skimage import data, io, filter, color, exposure
import skimage.transform as tf
from skimage.transform import rotate, setup, AffineTransform
from PIL import Image
mypath = PATH_TO_FILENAME
readfile = FILENAME
img = color.rgb2gray(io.imread(mypath + readfile))
myimg = rotate(img, angle=10, order=2)
afine_tf = tf.AffineTransform(shear=0.1)
editedimg = tf.warp(myimg, afine_tf)
# IF I UNCOMMENT THE TWO LINES BELOW, I CAN SEE THE EDITED IMAGE AS EXPECTED
#io.imshow(editedimg)
#io.show()
saveimg= np.array(editedimg)
result = Image.fromarray((saveimg).astype(np.uint8))
newfile = "edited_" + readfile
result.save(path+newfile)
I know that the image processing was fine because if I display it before saving, it's just the original image with a bit of rotation and shearing, as expected. But I'm doing something wrong while saving it. I tried without the astype(np.uint8)) part but got an error. Then I removed some of the code from the link mentioned above because I guessed it was particularly for Fourier Transforms, since when I included some of their code, then I got an image that was all gray but with white lines in the direction of the shear I'd applied. But now the image that gets saved is just 2KB of nothing but blackness.
And when I tried something as simple as:
result = Image.fromarray(editedimg)
result.save(path+newfile)
then I got this error:
raise IOError("cannot write mode %s as JPEG" % im.mode)
IOError: cannot write mode F as JPEG
I don't really need to use PIL, if there's another way to simply save my image, I'm fine with that.
Look into the PIL fork, Pillow, is is not as outdated and what you should probably be using for this.
Also depending on your operating system you may need a few other libraries to compile PIL with JPEG support properly, see here
This may also help Says you need to convert your image to RGB mode before saving.
Image.open('old.jpeg').convert('RGB').save('new.jpeg')
i want to convert a Pyglet.AbstractImage object to an PIL image for further manipulation
here are my codes
from pyglet import image
from PIL import Image
pic = image.load('pic.jpg')
data = pic.get_data('RGB', pic.pitch)
im = Image.fromstring('RGB', (pic.width, pic.height), data)
im.show()
but the image shown went wrong.
so how to convert an image from pyglet to PIL properly?
I think I find the solution
the pitch in Pyglet.AbstractImage instance is not compatible with PIL
I found in pyglet 1.1 there is a codec function to encode the Pyglet image to PIL
here is the link to the source
so the code above should be modified to this
from pyglet import image
from PIL import Image
pic = image.load('pic.jpg')
pitch = -(pic.width * len('RGB'))
data = pic.get_data('RGB', pitch) # using the new pitch
im = Image.fromstring('RGB', (pic.width, pic.height), data)
im.show()
I'm using a 461x288 image in this case and find that pic.pitch is -1384
but the new pitch is -1383
This is an open wishlist item:
AbstractImage to/from PIL image.