Pythonで手描きアニメGIF その3 Tkinter版



先日の記事のつづき

ペイントツールで絵を描く様子をアニメGIFで再現するソフト。先日はPyGame用でしたが、Pythonに標準でついてくるTkinterで書き直しました。
ついでに、色も使えるように。

サンプル
http://boxheadroom.com/wp/wp-content/uploads/2009/05/ehen7.gif
急にヴィックスドロップのコピー思いついたのでメモ(違
サイズ ( 15.4 KB )

スクリーンショット
http://boxheadroom.com/wp/wp-content/uploads/2009/05/gifpaint.png

必要なライブラリ

関連

Tkinterの解説記事

こちらのページで勉強しますた。

Tkinterは以前つかった時はややこしーと思ったのですけれども、何度も使って少しだけ慣れてきました。

つかいかた

  • gifpaint.pyw などの名前で保存
  • gifmaker2.pyを同じフォルダにおく
  • gifpaint.pywをダブルクリックで起動
  • 適当にお絵かき。セーブボタンで保存
    (4分の1に縮小されます)
# -*- coding: utf-8 -*-
"gif_paint.pyw"

from gifmaker2 import GifMaker
from functools import partial

# Pyton 3では、'Tkinter'ではなく'tkinter'らしい
import  Tkinter as tk
from Tkinter import Tk,Frame,Button,Label,IntVar,Scale,Canvas,NW
from tkFileDialog import asksaveasfilename
import tkMessageBox as msg
import Image as pil
import ImageDraw,ImageTk
import os

#ColorPicker
class ColorPicker(Frame):
  def __init__(self, master=None):
    self.root=Frame.__init__(self, master)
    # スケールの値を格納する
    self.red=IntVar(self)
    self.red.set(0)
    self.green=IntVar(self)
    self.green.set(0)
    self.blue=IntVar(self)
    self.blue.set(0)
    self.color=(0,0,0)
  # ボタン
    self.bcolor = Button(self, text = 'color', bg = '#000')
    self.bcolor.pack(fill = 'both');

    # スケール
    self.s1 = Scale(self, bg="#f00",label = 'red', orient = 'h',
             from_ = 0, to = 2, variable = self.red,
             command = self.change_color)

    self.s2 = Scale(self,  bg="#0f0",label = 'green', orient = 'h',
             from_ = 0, to = 2, variable = self.green,
             command = self.change_color)

    self.s3 = Scale(self, bg="#00f",label = 'blue', orient = 'h',
             from_ = 0, to = 2, variable = self.blue,
             command = self.change_color)
  # ウィジェットの配置
    self.s1.pack(fill = 'both')
    self.s2.pack(fill = 'both')
    self.s3.pack(fill = 'both')
  # ラベルの背景色を変更
  def change_color( self ,n):
    r,g,b=self.red.get(),self.green.get(),self.blue.get()
    r= r*128-1 if r else 0
    g= g*128-1 if g else 0
    b= b*128-1 if b else 0
    self.color=(r,g,b)
    self.bcolor.configure(bg = '#%02x%02x%02x' % self.color)

class GifPaint(Frame):
  def __init__(self,master=None):
    Frame.__init__(self,master)

    self.gm=GifMaker(trans=False,mode="P",loop=0,duration=0,cls=GifMaker.cls_bg)
    self.master.title(u"アニメGIF作成")
    self.pack()

    #変数
    self.W,self.H=640,480
    self.WH4=self.W//4,self.H//4
    self.last=[-1000,-1000]

    #PIL
    self.im=pil.new("RGB",(self.W,self.H))
    self.draw=ImageDraw.ImageDraw(self.im)
    self.draw.rectangle((0,0,self.W-1,self.H-1),(255,255,255))
    self.im_p=ImageTk.PhotoImage(self.im)
    self.im_p.paste(self.im)

    #ヘッダ
    self.hed=Frame(self)
    #白紙ボタン
    self.bcls = Button(self.hed, text=u'白紙',
          command=self.cls)
    self.hed.grid(row=0,column=0)
    self.bcls.pack(side = 'left')

    #キャンバス
    self.cv=Canvas(self, bd=0,width=self.W,height=self.H)
    self.cv.create_image(0,0,image=self.im_p,anchor=NW)
    self.cv.bind("<Button-1>",self.f_pset)
    self.cv.bind("<Button1-Motion>",self.f_pset)
    self.cv.grid(row=1, column=0)
    #サイドバー
    self.side=Frame(self)

    #カラーピッカー
    self.cp=ColorPicker(self.side)
    #ペンサイズ
    self.psize=IntVar(self.side)
    self.psize.set(8)
    self.pslider= Scale(self.side, label = 'pen size', orient = 'h',
               from_ = 1, to = 64, variable = self.psize)

    #サイドバー配置
    self.side.grid(row=1,column=1)
    self.cp.pack()
    self.pslider.pack()

    #セーブボタン
    self.bsave = Button(self, text='セーブ',
          command=self.save)
    self.bsave.grid(row=0, column=1)
    #終了ボタン
    self.bend = Button(self, text='終了',
                       command=lambda  :self.save() or self.master.destroy())
    self.bend.grid(row=2, column=1)

    #
    self.cv.focus_set()
    self.cls((255,255,255))

  def f_pset(self,event):
      x=event.x
      y=event.y
      lastx,lasty=self.last
      r=self.psize.get()
      self.draw.ellipse((x-r,y-r,x+r,y+r),fill=self.cp.color)
      self.im_p.paste(self.im)
      dx=x-lastx ; dy=y-lasty
      if (dx**2+dy**2 )>2048 :#32**2 :
        self.gm.writeframe(self.im.resize(self.WH4,0),duration=1)
        self.last[0]=x; self.last[1]=y

  def cls(self,color=None):
    if not color :
      color=self.cp.color
    self.draw.rectangle((0,0,self.W-1,self.H-1),color)
    self.im_p.paste(self.im)
    self.gm.writeframe(self.im.resize(self.WH4,0),duration=100)

  def save(self):
    fname=asksaveasfilename(
        filetypes = [('Animated GIF', ('.gif',))],
        title=u"アニメGIFとして保存")
    if fname :
      if not fname.lower().endswith(".gif"):
        fname+=".gif"
        print fname
      self.gm.writeframe(self.im.resize(self.WH4,0),duration=0)
      self.gm.save(fname,wait=500)
    else:
      print "cancel"

    #for i in c,bsave,bend:
    #  i.pack()

if __name__=="__main__":
  w=GifPaint()
  w.mainloop()

Todo

アンドゥー、ロード、などなど

Tags: ,

Related posts

タグ: ,

コメント / トラックバック3件

  1. 菅原@仙台 より:

    はじめまして。
    今年はチャゲアス30周年、光ゲンジがパラダイス銀河でレコード大賞取って20年経つなあ。あの頃、電脳倶楽部に勢いだけで作ったMessage.Xを投稿したら、魂の叫びのコーナーができて嬉しかったな。と、ふと懐かしくなって、”電脳倶楽部 魂の叫び”で検索して、ここに辿り着きました(笑)。

    暇プロからはすっかり遠ざかってしまっていますが、とても楽しそうなので、Pythonを勉強してみたいと思います。うちのMacで動くんでしょうか・・・。

    ありがとうございました。ではまた。

  2. boxheadroom より:

    Message.Xの作者さんにコメントを頂いて恐縮です(^^; 

    Python自身は、最初からOS Xにインストールされてたと思います
    このプログラムの場合、拡張モジュール「PIL」が必要になるのですが、私自身はMacを持ってないのでインストール方法がよくわかりません(ごめんなさい)

    、「Python Mac PIL インストール」 で検索すると。、いくつか日本語記事が出てきたので、多分使えるんじゃないかと。。。思います。 (適当ですんません)

  3. 菅原@仙台 より:

    おかげさまで、Macでも動きました。
    懐かしくて、涙ちょちょぎれです(笑)。
    早速、チャゲアスのSNSに投稿してみます。

    ありがとうございました。