I need to generate an easy animation video in Python (I use PIL to create every frame, then combine them using avconv
). The animation is just an image being zoomed out.
That's my code:
for i in xrange(zoom_length):
# zoom level on this step
zoom = 1.0 - 1.0 * i * (max_zoom / zoom_length)
# "size" is the resulting video frame size
# "img.size" is the source image size (around 2.5x bigger than the frame)
anti_zoomed_frame_size = int(size[0] / zoom), int(size[1] / zoom)
anti_zoomed_frame_margins = (img.size[0] - anti_zoomed_frame_size[0]) / 2, (img.size[1] - anti_zoomed_frame_size[1]) / 2
anti_zoomed_frame = img.crop(anti_zoomed_frame_margins +
(anti_zoomed_frame_size[0] + anti_zoomed_frame_margins[0],
anti_zoomed_frame_size[1] + anti_zoomed_frame_margins[1]))
frame = anti_zoomed_frame.resize(size, resample=Image.BILINEAR)
print i, img.size, anti_zoomed_frame_size, anti_zoomed_frame_margins
# frame No for debugging
draw = ImageDraw.Draw(frame)
draw.text((size[0] - 200, size[1] - 100), str(i), (0,0,0), font=font)
yield frame
So what happens is I crop out of the source image a rectangle of size frame_size / zoom
, then I resize it zoom
times to get the needed frame size. zoom <= 1.0
so doing it in this order seems to be a good idea, though I also tried doing it the other way (resize, then crop).
Anyway in both cases the resulting video is kind of shaking at times. It seems that the problem is in rounding the numbers. The math I'm doing inevitably leads to non-integers, yet PIL requires integers everywhere (also the resulting frame size is obviously a pair of integer constants). This rounding operation seems to affect the smoothness of the animation badly.
How smooth zooming is implemented in real life?