I am using a python notebook. In it, I have code that creates images, and am using image.show()
for debugging purposes. However, this has the disadvantage that I cannot name the image, since it has a temporary file name. I am then using image.save("name.png") to save the images with different names, and then using Image.open("name.png") to open it. However, when I do this, only the last image is actually opened. What do I need to do so that I can call Image.open on several images and they all open? For example if I do:
image = Image.fromarray( ... )
image.save("original.png")
Image.open("original.png")
image = Image.fromarray( ... )
image.save("reconstruction.png")
Image.open("reconstruction.png")
only "reconstruction.png" shows.
If I use Image.show() after each of them
image = Image.fromarray( ... )
image.show()
image = Image.fromarray( ... )
image.show()
it will work, but they will have a temporary name, which is meaningless, and if I end up with 7-8 open images I want an easy way to track what is what.
Image.show() is mainly for debugging use:
Displays this image. This method is mainly intended for debugging purposes.
On Unix platforms, this method saves the image to a temporary PPM file, and calls the xv utility.
On Windows, it saves the image to a temporary BMP file, and uses the standard BMP display utility to show it (usually Paint).
You can give a title parameter, but it doesn't show on Windows:
title – Optional title to use for the image window, where possible.
You can use different names for image variable to keep track of them inside Python:
image1 = Image.fromarray( ... )
image1.save("original.png")
Image1.open("original.png")
image2 = Image.fromarray( ... )
image2.save("reconstruction.png")
Image2.open("reconstruction.png")
image1.show("image1")
image2.show("image2")
Also another approach which I used within my IPython/Jupyter/Colab notebook was:
import requests
from IPython.display import Image
from IPython.display import display
img0 = Image("img0_path", width = 140)
img1 = Image("img1_path", width = 140)
img2 = Image("img2_path", width = 140)
img3 = Image("img3_path", width = 140)
display(img0,img1,img2,img3)
Related
I am trying to resize all images in my samples folder and then save all the images back in the test folder. The code below resize the images but it doesn't save them into the destination folder "test". I fail to understand what is the problem and I have referred to all documentation and nothing can help me understand what goes wrong here.
import cv2
import glob
import os
from tqdm import tqdm
imgs = glob.glob('samples/*.jpg')
print('Images files:', imgs)
width = 100
height = 100
folder = 'test'
if not os.path.exists(folder):
os.makedirs(folder)
#Resizing & Saving
for img in tqdm(imgs):
pic = cv2.imread(img, cv2.IMREAD_UNCHANGED)
pic = cv2.resize(pic, (width, height))
cv2.imwrite(os.path.join(folder,img), pic)
print(img)
The script can read the images and resize them successfully, the only part is imwrite doesn't function as expected.
May be the special character. Try to change the name of the image.
I don't have reputation to add this idea as comment. I'm Sorry.
I'm making a web app using Flask, and I want to resize the images that are uploaded. I'm using PIL to do this, but an error is thrown.
The process to do it is like this, but it seems inefficient:
filename = secure_filename(form.image.data.filename)
form.image.data.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
img = Image.open(os.path.join(app.config['UPLOAD_FOLDER'],filename), 'r')
img = img.resize(300, 300)
img.save(filename, quality=100, optimize=True)
What I'm trying to do is save the image after the user uploaded it, open the new file, resize it, and save it again.
How can I fix my error?
Also is there a way to do this more efficiently (without saving the un-resized file), using a Python library?
img = img.resize(300, 300)
=> img = img.resize((300,300))
The most important thing to remember is not to pass the size as object but as a tuple in resize function new_image = image.resize((img_width,img_size))
and NOT AS
new_image = image.resize(img_width,img_size)
I'm working on a project where two imported librairies are not working well with each other, I know it is possible to get the size of an image using :
from PIL import Image
img = Image.open(logo)
width, height = img.size
But I'd like to know if it is also possible to do that usin io ? I couldn't find anything on that
logo = request.FILES.get('logo')
img = io.BytesIO(logo.read())
... ?
I've been having trouble trying to get PIL to nicely downsample images. The goal, in this case, is for my website to automagically downsample->cache the original image file whenever a different size is required, thus removing the pain of maintaining multiple versions of the same image. However, I have not had any luck. I've tried:
image.thumbnail((width, height), Image.ANTIALIAS)
image.save(newSource)
and
image.resize((width, height), Image.ANTIALIAS).save(newSource)
and
ImageOps.fit(image, (width, height), Image.ANTIALIAS, (0, 0)).save(newSource)
and all of them seem to perform a nearest-neighbout downsample, rather than averaging over the pixels as it should Hence it turns images like
http://www.techcreation.sg/media/projects//software/Java%20Games/images/Tanks3D%20Full.png
to
http://www.techcreation.sg/media/temp/0x5780b20fe2fd0ed/Tanks3D.png
which isn't very nice. Has anyone else bumped into this issue?
That image is an indexed-color (palette or P mode) image. There are a very limited number of colors to work with and there's not much chance that a pixel from the resized image will be in the palette, since it will need a lot of in-between colors. So it always uses nearest-neighbor mode when resizing; it's really the only way to keep the same palette.
This behavior is the same as in Adobe Photoshop.
You want to convert to RGB mode first and resize it, then go back to palette mode before saving, if desired. (Actually I would just save it in RGB mode, and then turn PNGCrush loose on the folder of resized images.)
This is over a year old, but in case anyone is still looking:
Here is a sample of code that will see if an image is in a palette mode, and make adjustments
import Image # or from PIL import Image
img = Image.open(sourceFile)
if 'P' in img.mode: # check if image is a palette type
img = img.convert("RGB") # convert it to RGB
img = img.resize((w,h),Image.ANTIALIAS) # resize it
img = img.convert("P",dither=Image.NONE, palette=Image.ADAPTIVE)
#convert back to palette
else:
img = img.resize((w,h),Image.ANTIALIAS) # regular resize
img.save(newSourceFile) # save the image to the new source
#img.save(newSourceFile, quality = 95, dpi=(72,72), optimize = True)
# set quality, dpi , and shrink size
By converting the paletted version to RGB, we can resize it with the anti alias. If you want to reconvert it back, then you have to set dithering to NONE, and use an ADAPTIVE palette. If there options aren't included your result (if reconverted to palette) will be grainy. Also you can use the quality option, in the save function, on some image formats to improve the quality even more.
I have a function in which I'm trying to resize a photo twice from request.FILES['image']. I'm using the image.thumbnail() with the Parser as well. This works fine when I create one thumbnail, but in my view if I repeat the exact same thing again, it fails in the parser via IOError cannot parse image. I'm very confused. I've created StringIO files in memory instead of using Django's UploadedFile object as-is and it still does the same thing. Any help is much appreciated.
Suppose I wanted to do the following twice (with two different thumbnailing sizes) all without retrieving the URL twice:
import urllib2
from PIL import Image, ImageFile, ImageEnhance
# create Image instance
file = urllib2.urlopen(r'http://animals.nationalgeographic.com/staticfiles/NGS/Shared/StaticFiles/animals/images/primary/kemps-ridley-sea-turtle.jpg')
parser = ImageFile.Parser()
while True:
s = file.read(1024)
if not s:
break
parser.feed(s)
image = parser.close()
# make thumbnail
size = (75, 75)
image.thumbnail(size, Image.ANTIALIAS)
background = Image.new('RGBA', size, (255, 255, 255, 0))
background.paste(
image,
((size[0] - image.size[0]) / 2, (size[1] - image.size[1]) / 2))
background.save('copy.jpg')
For instance:
image = parser.close()
image2 = parser.close() # Obviously this doens't work
image2 = image # Obviously this doesn't either but you get what I need to do here
# Do 2 thumbnails with only one original source.
... other code ommitted ...
image.save('copy.jpg')
image2.save('copy.jpg')
If this works once, as you say, the image you retrieved is just fine. There are at least two different ways to get multiple thumbnails out of single PIL images.
You can use PIL's resize method, which will return a resized copy of the original. You just have to calculate the dimensions you'll need if you want to keep the proportions intact.
Use Image.copy() to get a copy of the image.
Like this:
original = parser.close()
...
thumb1 = original.copy()
size = (75,75)
thumb1.thumbnail(size, Image.ANTIALIAS)
...
thumb2 = original.copy()
thumbnail2 = original.resize(size2, Image.ANTIALIAS)
...
This way, the original will not be altered and you can get as many copies as you need.
A simpler solution than copying the original image is to instead reset the file pointer between calls to thumbnail(...) like so:
original.seek(0)
I'm assuming it's failing on the image = parser.close() line with an IOError. so there's probably something wrong with the way ImageFile is getting the image data. Have you tried making reading from a local file instead?
If the parser managed to decode an image, it returns an Image object.
Otherwise, this method raises an IOError exception.
Source.