Sign in to follow this  
Storyyeller

new to python

Recommended Posts

Well there was a particular image rotation animation task that I wanted to automate, and someone suggested making a python script with PIL. So I read some basic tutorials and eventually got a working script, but I figured I should ask if it is 'pythoric'. I've read here that one big pitfall when learning a new language is to attempt to carry over the idioms of the old language. So how can I improve this? My only significant programming experience is in C++, although I did have a brief introduction to Scheme once.
from PIL import Image

def goodrotate(img, theta):
    """Rotate, expand and crop image"""
    img2 = img.rotate(theta,Image.BICUBIC,1)
    return img2.crop(img2.getbbox())

ANGLEINC = 15
NUMFRAMES = 360 / ANGLEINC

loadedimage = Image.open("test.bmp")

imglist = []
for i in range(0,NUMFRAMES):
    imglist.append(goodrotate(loadedimage, i * ANGLEINC))

maxheight = 0
maxwidth = 0

for i in imglist:
    if i.size[0] > maxwidth:
        maxwidth = i.size[0]
    if i.size[1] > maxheight:
        maxheight = i.size[1]

resultimage = Image.new( loadedimage.mode, (maxwidth*NUMFRAMES, maxheight) )
frameoffsetx = 0
for i in imglist:
    pbox = frameoffsetx + (maxwidth-i.size[0])/2, (maxheight-i.size[1])/2
    resultimage.paste(i, pbox)
    frameoffsetx = frameoffsetx + maxwidth

resultimage.save("output.bmp")



Share this post


Link to post
Share on other sites
Perhaps if you don't need help with a game or graphics related issue you should post on a python specific usegroup or forum, seeing as how you don't need help with the script so much as the language conventions.

I think you can get the best direction here: http://groups.google.com/group/comp.lang.python/topics

EDIT: On a side note having used many different languages I have never seen variables or identifiers with 2 words not have some sort of distinction between them i.e "loadedimage" should be "loaded_image" or "loadedImage" .

Share this post


Link to post
Share on other sites
You may want to read the style Guide for Python Code - although that covers more style than what exactly is 'Pythonic'.

Your code looks fine to me. There's just a few things I'd change: the range() function can suffice with only one argument if you're starting at 0, and if you're iterating through a list, use a proper variable name (image instead of i - you may want to name the list rotatedImages, for clarity's sake). The size checks can be replaced with something like maxWidth = max(maxWidth, image.size[0]), and the same for height. Also, Python has a += operator.

Share this post


Link to post
Share on other sites
Quote:
Original post by Captain P
The size checks can be replaced with something like maxWidth = max(maxWidth, image.size[0])


min and max in python can work on sequences so


maxheight = 0
maxwidth = 0

for i in imglist:
if i.size[0] > maxwidth:
maxwidth = i.size[0]
if i.size[1] > maxheight:
maxheight = i.size[1]

can become this:


maxwidth = max( image.size[0] for image in imglist)
maxheight = max( image.size[1] for image in imglist)


although you are now looping over the image list twice, so you'd have to make a choice about whether that is acceptable to you.

you can use list comprehension to compile you imglist e.g.


imglist = []
for i in range(0,NUMFRAMES):
imglist.append(goodrotate(loadedimage, i * ANGLEINC))


becomes


imglist = [ goodrotate(loadedimage, i*ANGLEINC) for i in range(NUMFRAMES) ]


although it looks weird when your not used to it it's a good construct to use.

Share this post


Link to post
Share on other sites
I prefer to lead by example:


from PIL import Image

def rotated_and_bounded(original_image, theta):
rotated = original_image.rotate(theta, Image.BICUBIC, 1)
return rotated.crop(rotated.getbbox())

ANGLE_STEP = 15
FRAME_COUNT = 360 / ANGLE_STEP

base_image = Image.open("test.bmp")

images = [
rotated_and_bounded(base_image, i * ANGLE_STEP)
for i in range(FRAME_COUNT)
]

max_width = max(image.size[0] for image in images)
max_height = max(image.size[1] for image in images)

image_sheet = Image.new(base_image.mode, (max_width * FRAME_COUNT, max_height))

for (i, image) in enumerate(images):
image_sheet.paste(image, (
max_width * i + (max_width - image.size[0]) / 2,
(max_height - image.size[1]) / 2
))


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this