Is there an easy way to do this? In Python, I created a script to get a "square box" from an image...based on the center.
However, that killed some of my brain cells. Is there an easy way to do this for a 3x2 (3 width, 2 height), based on the center?
This is my "square box" script, but I don't feel like modifying it for the 3x2.
def letterbox(f,thumb_w=None,thumb_h=None):
try:
im = Image.open(StringIO(f))
imagex = int(im.size[0])
imagey = int(im.size[1])
thumb_size = (thumb_w,thumb_h) #what if it is too small!?? fix it.
if imagex > imagey:
setlen = imagey
left = (imagex - setlen)/2
top = 0
height = setlen
width = setlen
if imagey > imagex:
setlen = imagex
le开发者_开发百科ft = 0
top = (imagey - setlen)/2
heigth = setlen
width = setlen
if imagex == imagey:
left = 0
top = 0
height = imagey
width = imagex
box = (left,top,left+width,top+height)
im = im.crop(box)
#im.thumbnail(thumb_size,Image.ANTIALIAS)
new_file = StringIO()
im.save(new_file,'JPEG')
new_file.seek(0)
except Exception, e:
pass
return new_file
Is there a script online that can do what I need?
Use an aspect ratio which is defined as imagex/imagey, so you use 3/2 for 3:2, 16/9 for 16:9 etc.
def letterbox(f,aspect_ratio=1):
try:
im = Image.open(StringIO(f))
imagex = int(im.size[0])
imagey = int(im.size[1])
width = min(imagex, imagey*aspect_ratio)
height = min(imagex/aspect_ratio, imagey)
left =(imagex - width)/2
top = (imagey - height)/2
box = (left,top,left+width,top+height)
im = im.crop(box)
new_file = StringIO()
im.save(new_file,'JPEG')
new_file.seek(0)
except Exception, e:
pass
return new_file
You might want to check for roundoff errors at some point, but otherwise this does it.
First of all, the name of your function is misleading because what it does is not letterbox images (regardless of the specific height/width [aspect ratio] involved) -- so here it's been renamed aspectcrop()
to better describe what it does.
def aspectcrop(f, ratio=1.0):
try:
im = Image.open(StringIO(f))
imagewidth,imageheight = im.size
# determine the dimensions of a crop area
# which is no wider or taller than the image
if int(imagewidth*ratio) > imageheight:
cropheight,cropwidth = imageheight,int(imageheight/ratio)
else:
cropwidth,cropheight = imagewidth,int(imagewidth*ratio)
# center the crop area on the image (dx and/or dy will be zero)
dx,dy = (imagewidth-cropwidth)/2,(imageheight-cropheight)/2
# crop, save, and return image data
im = im.crop((dx,dy,cropwidth+dx,cropheight+dy))
new_file = StringIO()
im.save(new_file,'JPEG')
new_file.seek(0)
except Exception, e:
new_file = None # prevent exception on return
pass
return new_file
If any aspect ratio
argument you pass to it is not naturally a whole number, make sure it's in floating point, as in 3./2.
not 3/2
. The default (1.0
) could have been integer, but I explicitly made it floating point as a reminder. It might be better to pass it in as two separate integers and compute the ratio internally.
Lastly, I noticed that your example script had some visible traces of what looks like an attempt to create a thumbnail of the image, so my answer to the related question What's the simplest way in Python to resize an image to a given bounded area? might also be of interest (and could probably be integrated into this function without too much trouble).
精彩评论