I need to rotate an image around its x-axis (or y-axis). I can easily create such an animation with avisynth, but now I need to implement that effect with Python's moviepy module. I can easily rotate an image with the following script but need some clues how to rotate it in 2D or 3D.
from moviepy.editor import *
clip = ImageClip('my_image.jpg')
rotated_clip = (clip.add_mask()
.fx(vfx.resize, width=300, height=300)
.fx(vfx.rotate, lambda t: 90*t, expand=False)
.set_duration(5))
final_clip = CompositeVideoClip([rotated_clip.set_pos("center")], size=(800,800), bg_color=3*[255])
final_clip.write_videofile("test.mp4", fps=25, codec="libx264")
Here is the avisynth script that actually generated that example image. Please note, it does require "QUAD" plugin.
function stars(clip c, int r) {
c.Overlay(x=rand(c.width),y=rand(c.height),BlankClip(c,width=1,height=1,color=$030301*rand(85)))
(r==0)? last : stars(r-1)
Trim(0,-1).Loop(c.Framecount, 0, 0)
}
width= 800
height=600
length=100000
Tcolor=$000040
Bcolor=$000018
StackVertical(BlankClip(length=length,width=2,height=1,color=TColor,pixel_type="RGB32"),BlankClip(length=length,width=2,height=1,color=BColor)).BilinearResize(width,2*height,src_top=0,src_height=2).Crop(0,height/2,0,-height/2).Stars(width*height/3072)
ImageSource("path_to_image.png", start=0, end=total_time, fps=300, pixel_type="RGB32")
#BlankClip(length=length,FPS=25,width=640,height=480,color=$000018,pixel_type="RGB32")
#ColorBars()
HALFCYCLE=10 # Frames in 1 HALF rotation (spinning clip)
NSPIN = 1 # Number of HALF rotations in spinning clip
NSTILL = 10 # Frames in STILL clip
V = 0.2 # Tilt/Yaw
tim = PI / HALFCYCLE
ScriptClip("""
c=last
t=tim*current_frame
t1x= 0.5 - 0.5 * cos(t) # BOTH Left
t2x= 0.5 + 0.5 * cos(t) # BOTH Right
#
t1y= 0.0 + V * sin(t) # ] both Top's opposite sign
t2y= 0.0 - V * sin(t) # ]
t3y= 1.0 + V * sin(t) # [ both Bottoms opposite sign
t4y= 1.0 - V * sin(t) # [
ResetMask
quad(t1x,t1y, t2x,t2y, t2x,t3y, t1x,t4y, normal=true)
#Overlay(c,last,mask=last.ShowAlpha())
""")
SPIN=Trim(0,-(NSPIN*HALFCYCLE +1)) # Spinning clip, + 1 to complete last spin
STILL=SPIN.Trim(SPIN.FrameCount-1,-1).Loop(NSTILL,0,0)
SPIN2=Trim((NSPIN%2 ==0)?0:HALFCYCLE,-(NSPIN*HALFCYCLE +1))
SPIN ++ STILL ++ SPIN2
Return Last

One way to do this is to use Vapory, another library by the author of MoviePy, which facilitates the operation of POV-Ray via Python. You can create a rectangle within a 3D scene and rotate it around whatever axis you like, saving frames into a MoviePy clip at intervals.
MoviePy + Vapory code
Output GIF
Other thoughts:
The main things you might want to change are
img_path,t_rev(the time for a full 360 degree revolution),t_still, and the output frame rate.I removed one column of pixels from your example image to get it down to an even width (150 px). It's not important if you only want to make GIFs, but if you want to produce an x264-encoded MP4, you should probably use mod2 dimensions.
It seems like overkill to use a ray tracer for this problem, but it's the first working solution I came up with. I wanted to represent the image as a 2D rectangle in a 3D scene, where I could simply specify an angle of rotation and the 3D library would handle the rest.
It should be possible to solve this problem using a projective transform from scikit-image, as in this MoviePy example. Note specifically, the
trapzWarpfunction near the middle of that code listing.