はじめに
今回は、クラスを使ってアニメーション動画を作成します。まず、表示する画像ファイルをファイルダイアログで開きます。それから「アルキメデスの螺旋」に沿って、その画像が1個ずつ追加されていくだけのアニメーションをします。アルキメデスの螺旋とは、要するに渦巻き状の螺旋のことです。
クラスを使って動画の作成
「クラスを使う」と言っても、今までにやってきたことを応用すれば簡単にアニメーション動画を作れます。ゲームプログラミングよりさらに一歩手前の、絵を扱うだけのプログラミングをすることでPython3を簡単に学習するのが本連載の狙いですが、簡単過ぎて物足りないかも知れません。
背景色だけの静止動画
まずは、アニメーションする前にクラスを使って動画を作るテンプレートを作ってみます。単純に第6回の解説をクラス化しただけです。まだ画像ファイルは扱いません。
サンプルをスクリプティングしたら「ウィンドウ」→「ワークスペース」→「Animation」を選択し、画像が90個準備できたら「アニメーションタイムライン」の「▶」でアニメーションを再生できます。まだ静止画像です。
図1:緑色の背景色だけの静止動画
・サンプルスクリプト「class_green.py」
10 | def create_doc(self,width,height): |
11 | self.doc = Krita.instance().createDocument(width, height, "Testing animation", "RGBA", "U8", "", 300.0) |
12 | Krita.instance().activeWindow().addView(self.doc) |
14 | def insertFrames(self, nbFrames): |
15 | tmpPath = tempfile.mkdtemp() |
17 | for imgNumber in range(nbFrames): |
18 | fileName = os.path.join(tmpPath, f"tmp{imgNumber:04}.png") |
19 | files.append(fileName) |
20 | image = self.draw_img(imgNumber) |
22 | self.doc.importAnimation(files, 0, 1) |
23 | self.doc.setFullClipRangeEndTime(nbFrames - 1) |
24 | shutil.rmtree(tmpPath) |
26 | def draw_img(self,number): |
27 | pixmap = QPixmap(self.doc.bounds().size()) |
28 | pixmap.fill(QColor(0,128,0)) |
29 | return pixmap.toImage() |
32 | self.create_doc(800,800) |
33 | self.doc.setFramesPerSecond(8) |
【サンプルスクリプトの解説】
「create_doc」メソッドと「insertFrames」メソッドは第6回をクラス化しただけです。
「draw_img」メソッドで背景を緑色に塗り潰します。
「create」メソッドでドキュメントを作成し1秒間に8コマ(8FPS)にセットし、90コマの動画を作成します。
「Animation」クラスのインスタンスを作成し、「create」メソッドを実行します。
読み込んだ画像をアルキメデスの螺旋状に描画する動画
それでは、図2を右クリックメニューで画像を名前を付けて保存してください。この画像使って、この画像が1個ずつ増えていくだけのアニメーションを作ります。
図2:アニメーションに使用する画像(右クリックで保存)
ちょっと工夫したのは、アルキメデスの螺旋状に広がっていくところです。アルキメデスの螺旋は、次の計算式のように円周の角度が回っていくうちに徐々に円の半径が大きくなっていくだけの単純な計算です。
「アルキメデスの螺旋」の計算
求める座標(X,Y)
X = cosθ*円の半径
Y = sinθ*円の半径
円の半径 += 増分
(ただし実際の計算はサンプルスクリプト「class_animation.py」では「translate」メソッドと「rotate」メソッドに内包されている。一般にプログラミング言語の数学ライブラリのsin関数とcos関数は円の半径1とした場合の値が取得できる。長さ1にすることを正規化するという)
図3:アニメーション動画
・サンプルスクリプト「class_animation.py」
04 | self.pix = QPixmap(self.doc.bounds().size()) |
05 | filter = str('Supported Files (*.jpg *.png);;All files (*)') |
06 | fileName = QFileDialog.getOpenFileName(None,str(''),str(''),filter) |
07 | self.pix.load(fileName[0]) |
10 | def draw_img(self,number): |
11 | pixmap = QPixmap(self.doc.bounds().size()) |
12 | pixmap.fill(QColor(Qt.transparent)) |
15 | cx = int(self.doc.width()/2) |
16 | cy = int(self.doc.height()/2) |
17 | for i in range(0,number): |
19 | painter.translate(cx,cy) |
21 | painter.drawPixmap(i*6,0,self.pix) |
24 | return pixmap.toImage() |
27 | self.create_doc(800,800) |
29 | self.doc.setFramesPerSecond(8) |
【サンプルスクリプトの解説】
「open_img」メソッドでファイルダイアログで画像ファイルを開きます。
「draw_img」メソッドでアルキメデスの螺旋状に画像を1個ずつ描画(「drawPixmap」メソッド)していきます。
「create」メソッドでドキュメントを作成し、ファイルダイアログで画像を開き、8FPSにセットし、90コマのアニメーションを動画にします。
【コラム】Think ITの記事
筆者は「プログラミング」「3DCG」「2DCG」「デザイン」「文筆」「音楽」「動画」など、クリエイティブは全て網羅してきたつもりでした。でも「Think IT」の記事を読んでいると「まだまだ手を付けていない分野が山ほどあるなぁ」と思い知らされます。
これらについては、今後Think ITで解説していきたいと思います。
おわりに
今回は、第6回で解説したアニメーションをクラスを使ってプログラミングする方法を解説しました。さらに、ファイルダイアログで開いた画像でアニメーション動画を作ってみました。