Calling
image = Image.open(data)
image.thumbnail((36,36), Image.NEAREST)
will maintain the aspect ratio. But I need to end up displaying the image like this:
<img src="/media/image.png" style="height:36px; width:36px" />
Can I have a letterbox style with either transparent or white around the image?
PIL already has a function to do exactly that:
from PIL import Image, ImageOps
thumb = ImageOps.fit(image, size, Image.ANTIALIAS)
Paste the image into a transparent image with the right size as a background
from PIL import Image
size = (36, 36)
image = Image.open(data)
image.thumbnail(size, Image.ANTIALIAS)
background = Image.new('RGBA', size, (255, 255, 255, 0))
background.paste(
image, (int((size[0] - image.size[0]) / 2), int((size[1] - image.size[1]) / 2))
)
background.save("output.png")
EDIT: fixed syntax error
from PIL import Image
import StringIO
def thumbnail_image():
image = Image.open("image.png")
image.thumbnail((300, 200))
thumb_buffer = StringIO.StringIO()
image.save(thumb_buffer, format=image.format)
fp = open("thumbnail.png", "w")
fp.write(thumb_buffer.getvalue())
fp.close()
Update of Cesar Canassa's answer.
This will create a thumbnail of image.jpg as image_thumb.jpg:
from PIL import Image, ImageOps
fname = 'image.jpg'
size = (48,48)
thumb = ImageOps.fit(Image.open(fname), size, Image.ANTIALIAS)
thumb.save('{}_thumb.jpg'.format(fname[:fname.rfind('.')]), "JPEG")
Or this, maybe... (forgive spaghetti)
from PIL import Image
def process_image(image, size):
if image.size[0] > size[0] or image.size[1] > size[1]:
#preserve original
thumb = image.copy()
thumb.thumbnail(size,Image.ANTIALIAS)
img = thumb.copy()
img_padded = Image.new("RGBA",size)
img_padded.paste(image,(int((size[0]-image.size[0])/2),int((size[1]-image.size[1])/2)))
return img_padded
Why not simply use the resize method ?
from PIL import Image
image = Image.open('/path/to/img.png')
image = image.resize((36,36), Image.ANTIALIAS)
See recommendations for image resizing in this release note:
https://pillow.readthedocs.io/en/stable/releasenotes/5.3.0.html
you can wrap Nadia's answer in this function, which gives you control over size and background.
def make_square(im, min_size=36, fill_color=(255, 255, 255, 0)):
x, y = im.size
size = min(min_size, x, y)
new_im = Image.new('RGBA', (size, size), fill_color)
im.thumbnail((256, 256))
new_im.paste(im, (int((x - size) / 2), int((y -size) / 2))
return new_im
Related
Here is an example of the output I want to generate. I'm able to create an image with one color, but I don't have idea of how can use two colors, and how to color only certain parts of the image .
I solved in this way. I created two image with two different colors, and then paste them in another one image.
width = 400
height = 300
img = Image.new( mode = "RGB", size = (width, height), color = (209, 123, 193) )
#First IMG
img2 = Image.new( mode = "RGB", size = (width, height + 400), color = (255, 255, 255) )
#Second IMG
img3 = Image.new('RGB', (img.width, img.height + img2.height)) img3.paste(img, (0, 0)) img3.paste(img2, (img.width, 0))
#IMG + IMG2
I got my result.
when i trying to run this code, my image breaks
User avatar should be transparent
I want make like this:
How can i fix this?
import io
from PIL import Image, ImageDraw
im_rgb = Image.open('cards/customcard1.png')
im_a = Image.new("RGBA", im_rgb.size, 0)
im_a.paste(im_rgb)
draw = ImageDraw.Draw(im_a)
draw.ellipse((92, 193, 403, 504), fill=255)
memberavatar = await _ctx.author.avatar_url.read()
def rounded_avatar(member):
with Image.open(io.BytesIO(member)) as im:
with Image.new("RGBA", im.size) as background:
rgb_avatar = im.convert("RGBA")
with Image.new("L", im.size, 0) as mask:
mask_draw = ImageDraw.Draw(mask)
mask_draw.ellipse([(0, 0), im.size], fill=255)
background.paste(rgb_avatar, (0, 0), mask=mask)
return background
roundedAvatar = rounded_avatar(memberavatar)
roundedAvatar = roundedAvatar.resize((311, 311), Image.ANTIALIAS)
roundedAvatar.save('cards/roundedAva.png')
r = Image.open('cards/roundedAva.png').convert('RGBA')
im_a.paste(r, (92, 193))
im_a.save('C:/Users/RAINGM/desktop/hueta.png')
im_a.show()
I fix this with Image.alpha_composite()
I want to put my pic in my frame.I used this cod :
from PIL import Image
img = Image.open('Pic.jpg')
frame = Image.open('Frame.jpg')
size1 = 354,362
paste_point = 69,339
Pic = img.resize((size1))
frame.paste(img, (paste_point))
frame.show()
When i run the program, my pic doesn't put in my frame.
How can i create a frame in python
your question solution depends always on your pic size and frame size ,so code must be adjusted according to pixel size of your pic
i am giving generic code for your problem maynot fit to your image standards
from PIL import Image
img = Image.open('Pic.jpg')
img_w, img_h = img.size
frame = Image.new('RGBA', (1440, 900), (255, 255, 255, 255))
bg_w, bg_h = frame.size
offset = ((bg_w - img_w) / 2, (bg_h - img_h) / 2)
frame.paste(img, offset)
frame.save('out.png')
I would like to create a Python script to resize images, but not changing its proportions, just by adding a white background
(So, a : 500*700 px image would transform to a 700*700 px image by adding 100 px of a white band on each side)
The three image types I use are .PNG, .JPG and .GIF. I am not even sure it is possible for Gifs, PNG and JPG would already be awesome.
In my case, they have to be squares. But if any of you manage to do it for adaptable to any proportion, it would benefit the maximum number of people that see this thread and you would be even more awesome !
I saw same threads for other languages but not python, do you guys know how you do this ?
PS : I am using Python 3
What I tried :
Combining 3 images together.
If we take our 500*700 px image :
Creating two white images of 100*700px and put one on each side of the image. Inspired by :
Combine several images horizontally with Python
But, I am kind of new on python, and I haven't succeded.
Finally did it :
def Reformat_Image(ImageFilePath):
from PIL import Image
image = Image.open(ImageFilePath, 'r')
image_size = image.size
width = image_size[0]
height = image_size[1]
if(width != height):
bigside = width if width > height else height
background = Image.new('RGBA', (bigside, bigside), (255, 255, 255, 255))
offset = (int(round(((bigside - width) / 2), 0)), int(round(((bigside - height) / 2),0)))
background.paste(image, offset)
background.save('out.png')
print("Image has been resized !")
else:
print("Image is already a square, it has not been resized !")
Thanks to #Blotosmetek for the suggestion, pasting a centered image is definitely simpler than creating images and combining them !
PS : If you don't have PIL yet, the library's name to install it with pip is "pillow", not PIL. But still, you use it as PIL in the code.
Thanks #Jay D., here a bit more general version:
from PIL import Image
def resize(image_pil, width, height):
'''
Resize PIL image keeping ratio and using white background.
'''
ratio_w = width / image_pil.width
ratio_h = height / image_pil.height
if ratio_w < ratio_h:
# It must be fixed by width
resize_width = width
resize_height = round(ratio_w * image_pil.height)
else:
# Fixed by height
resize_width = round(ratio_h * image_pil.width)
resize_height = height
image_resize = image_pil.resize((resize_width, resize_height), Image.ANTIALIAS)
background = Image.new('RGBA', (width, height), (255, 255, 255, 255))
offset = (round((width - resize_width) / 2), round((height - resize_height) / 2))
background.paste(image_resize, offset)
return background.convert('RGB')
The accepted answer is great, I am just happy not to use OpenCV.
As #Nemanja mentioned, if you want to make it work for any aspect ration. Here is the snippet to use. I just twisted the code a bit.
from PIL import Image
def Reformat_Image_With_Ratio(ImageFilePath, desired_aspect_ratio):
image = Image.open(ImageFilePath, 'r')
width = image.width
height = image.height
img_aspect_ratio = width/height
if (img_aspect_ratio != desired_aspect_ratio):
bigside = width if width > height else height
other_side = int(bigside * desired_aspect_ratio)
background = Image.new('RGBA', (other_side, bigside), (255, 0, 0, 255))
offset = (int(round(((bigside - width) / 2), 0)), int(round(((bigside - height) / 2),0)))
background.paste(image, offset)
background.save('out4.png')
print("Image has been resized !")
else:
print("Image is already a valid aspect ratio, it has not been resized !")
Reformat_Image_With_Ratio('test.png', 9/16)
The other answer didn't work for me, I rewrote it and this worked:
def resize_with_pad(im, target_width, target_height):
'''
Resize PIL image keeping ratio and using white background.
'''
target_ratio = target_height / target_width
im_ratio = im.height / im.width
if target_ratio > im_ratio:
# It must be fixed by width
resize_width = target_width
resize_height = round(resize_width * im_ratio)
else:
# Fixed by height
resize_height = target_height
resize_width = round(resize_height / im_ratio)
image_resize = im.resize((resize_width, resize_height), Image.ANTIALIAS)
background = Image.new('RGBA', (target_width, target_height), (255, 255, 255, 255))
offset = (round((target_width - resize_width) / 2), round((target_height - resize_height) / 2))
background.paste(image_resize, offset)
return background.convert('RGB')
I have 2 images:
PNG (99x97) with white, rotated frame and rest is in full transparency.
JPG - is my generated thumbnail (80x80)
Now I want to put thumbnail into my frame so it looks like some kind of painting. What should I do?
EDIT:
I forgot to add, that picture must be under the frame.
Frame image
I have some script but it shows only a frame. There is no picture in it :/
import Image, ImageDraw
img_size = (99,97)
im = Image.open('logo.jpg')
picture = im.crop((0,0,80,80))
frame = Image.open('thumb-frame.png')
picture = picture.convert('RGBA')
background = Image.new('RGBA', img_size, (255, 255, 255, 0))
background.paste(picture, (10,9))
background.paste(frame, (0,0))
background.save('logocopy.png', 'PNG')
EDIT:
Problem solved. I had to add alpha mask to .paste()
import Image
im = Image.open('logo.jpg')
picture = im.crop((0,0,80,80))
picture = picture.convert('RGBA')
frame = Image.open('thumb-frame.png')
background = Image.new('RGBA', frame.size, (255, 255, 255, 0))
background.paste(picture, (10,9))
background.paste(frame, (0,0), frame)
background.save('logocopy.png', 'PNG')
Here you go. This should take original picture and paste transparent frame image above it. Both pictures should be 100x100, but you can add needed resizing.
from PIL import Image
frame = Image.open('frame.png')
img = Image.open('image.jpg')
img_dest = img.copy().convert('RGBA')
img_dest.paste(frame, (0, 0, 100, 100), frame)
img_dest = img_dest.convert('RGB') # Optional, to remove transparency info
img_dest.save('output.png')