2008年7月24日木曜日

(Code: sh) h2rgb

#!/bin/sh

for ((h=0;h<360;h++)) ;do
if [ $h -ge 0 ] && [ $h -lt 60 ] ;then
F=$[$h * 255 / 60]
P=0
Q=$[255 - $F]
T=$F
R=255 ;G=$T ;B=$P
elif [ $h -ge 60 ] && [ $h -lt 120 ] ;then
F=$[$[$h - 60] * 255 / 60]
P=0
Q=$[255 - $F]
T=$F
R=$Q ;G=255 ;B=$P
elif [ $h -ge 120 ] && [ $h -lt 180 ] ;then
F=$[$[$h - 120] * 255 / 60]
P=0
Q=$[255 - $F]
T=$F
R=$P ;G=255 ;B=$T
elif [ $h -ge 180 ] && [ $h -lt 240 ] ;then
F=$[$[$h - 180] * 255 / 60]
P=0
Q=$[255 - $F]
T=$F
R=$P ;G=$Q ;B=255
elif [ $h -ge 240 ] && [ $h -lt 300 ] ;then
F=$[$[$h - 240] * 255 / 60]
P=0
Q=$[255 - $F]
T=$F
R=$T ;G=$P ;B=255
elif [ $h -ge 300 ] && [ $h -lt 360 ] ;then
F=$[$[$h - 300] * 255 / 60]
P=0
Q=$[255 - $F]
T=$F
R=255 ;G=$P ;B=$Q
fi
echo "($R $G $B)"
done

(Code) seq-text.scm

(
(define (my-indexget List i)
(let*
(
(j 0)
)

(while (< j i)
(set! List (cdr List))

(set! j (+ j 1))
)
(car List)
))

(define (my-seq-filename-jpg N i)
(let*
(
(str_i (number->string i))
(LEN_i (string-length str_i))
(LEN_N (string-length (number->string (- N 1))))
(N_zero (- LEN_N LEN_i))
(Zeros)
(i)
)

(set! Zeros "")
(set! i 0)
(while (< i N_zero)
(set! Zeros (string-append Zeros "0"))
(set! i (+ i 1))
)
(string-append "src/text/" Zeros str_i ".jpg")
))

(define (seq-text Lists)
(let*
(
(W 704) (H 396)
(fontsize 64)
(font "DejaVu Sans Mono Bold")

(theImage
(car
(gimp-image-new W H RGB)
))
(theLayer
(car
(gimp-layer-new
theImage
W H
RGBA-IMAGE
"base"
100
NORMAL
)))

(N) (i 0)
(List)
(Color)
(Color_inv)
(text)

(theText)
(w) (h)
(offset_x) (offset_y)

(filename)
)

(gimp-image-add-layer theImage theLayer 0)

(set! N (length Lists))
(while (< i N)
(set! List (my-indexget Lists i))
(set! Color (car List))
(set! Color_inv (car (cdr List)))
(set! text (car (cdr (cdr List))))
(gimp-context-set-background Color)
(gimp-drawable-fill theLayer BACKGROUND-FILL)
(gimp-context-set-foreground Color_inv)
(set! theText
(car
(gimp-text-fontname
theImage theLayer
0 0
text
0
TRUE
fontsize PIXELS
font
)))
(set! w (car (gimp-drawable-width theText)))
(set! h (car (gimp-drawable-height theText)))
(set! offset_x (/ (- W w) 2))
(set! offset_y (/ (- H h) 2))
(gimp-layer-set-offsets theText offset_x offset_y)
(gimp-floating-sel-anchor theText)

(set! filename (my-seq-filename-jpg N i))
(file-jpeg-save
1 theImage theLayer filename filename 1 0 0 0 "" 0 0 0 0)

(set! i (+ i 1))
)
))

(seq-text '(<lists>))
(gimp-quit 0)
)

(Code: sh) seq-text

#!/bin/sh

FILE=src/text.txt
if [ ! -f $FILE ] ;then
echo "Error: file \"$FILE\" not exist" >&2
exit 1
fi

LISTS=`cat $FILE |tr '\n' ' '`
cat script/seq-text.scm \
|sed -e 's/;.*//g' -e 's/<lists>/'"$LISTS"'/' \
|gimp -i -b -

2008年7月22日火曜日

GIMP script-fu 弄り

GIMPのscript-fuの練習です。「警告」テキストをモチーフにバリエーションつくってみました。

紅白サイクル


紅白点滅 ※再生危険※ 光過敏性発作を誘発する危険性有


スクロールループ



Scheme弄りに徐々になれてきた!

(アニメ) ひだまりスケッチのMAD

レベル高すぎて感動した。



※著作権法的にどうななよ?的な話はゴメンなさい

GIMPをscript-fuで自動化

GIMPの動作中の画像です。




Schemeというプログラム言語"LISP"の一種があるんですが、
GIMPではこれで自動化スクリプトをコーディングします。
GIMP内では"script-fu"と呼ばれてます。スクリプト・フー。
以下はその例です。

(
(define (my-test-seq-filename-jpg i N)
(let*
(
(str_i (number->string i))
(LEN_i (string-length str_i))
(LEN_N (string-length (number->string N)))
(N_zero (- LEN_N LEN_i))
(Zeros)
(i)
)

(set! Zeros "")
(set! i 0)
(while (< i N_zero)
(set! Zeros (string-append Zeros "0"))
(set! i (+ i 1))
)
(string-append "src/" Zeros str_i ".jpg")
))

(define (my-test-func theLayer i TIME_CYCLE FPS)
(let* (
(Color)
(color)
(PI (acos -1))
)

(set! color
(* 255
(/ (+ (cos (+ PI (/ (* 2 (* PI i)) (* TIME_CYCLE FPS)))) 1) 2)))
(set! Color (list 255 color color))
(gimp-context-set-background Color)
(gimp-drawable-fill theLayer BACKGROUND-FILL)
theLayer
))

(define (my-test)
(let*
(
(W 704)
(H 396)
(TIME 20)
(TIME_CYCLE 2)
(FPS 25)
(N (* TIME FPS))

(theImage
(car
(gimp-image-new W H RGB)
))
(theLayer
(car
(gimp-layer-new
theImage
W
H
RGB-IMAGE
"layer 1"
100
NORMAL
)))

(i)
(filename)
)

(gimp-image-add-layer theImage theLayer 0)

(set! i 0)
(while (< i N)
(set! theLayer (my-test-func theLayer i TIME_CYCLE FPS))

(set! filename (my-test-seq-filename-jpg i N))
(file-jpeg-save
1 theImage theLayer filename filename 1 0 0 0 "" 0 0 0 0
)

(set! i (+ i 1))
)
))

(my-test)
(gimp-quit 0)
)


このようなスクリプト(script.scm)を用意して

$ cat script.scm | gimp -i -b -


とgimpに渡してやると、連番画像ファイルが作成されます。上の例では500枚。
この連番画像ファイルをFFmpegで動画化できます。


GIMP+FFmepgで製作した動画


紅白サイクル


紅白点滅 ※危険※ 光過敏性発作の危険がありますので再生には注意ください



他の動画作成ソフトを使えばall-in-oneですべて済みそうなものですが、
原理的に1frameづつGIMPで可能なあらゆる処理を適用できる点、楽しい動画作成方法です。
コマンドベースですのでシェルスクリプトで連番画像作成や動画化をバッチ処理できます。
ガツガツ製作できそうです。

2008年7月21日月曜日

ソフトキャプチャとffmpegでエンコ

キャプ板を使わずに動画をつくりたいな、と前から考えていたんですが
スクリーンショットを連続取得(ソフトキャプチャ)→ffmpegで動画化(エンコ)、の手順で製作できた!
というレビューです。

ためしに、うちで動いてるスクリーンセーバーを動画化してみました。こんな感じ。




おおまかな製作手順は以下の3ステップです。

25fpsで20秒間(画像500枚分)の動画を製作するとします。
スクリーンショットのダンプファイルはディレクトリ"src"以下に保存します。
スクリーンショットの画像ファイルはディレクトリ"seq"以下に保存します。
(あらかじめsrc、seqをmkdirしておきます。
それぞれ大量のファイル(500枚)が生成されるので別ディレクトリにしてます。)


(1) コマンド"xwd"を使って特定のウインドのスクリーンショットをダンプ
$ for ((i=0;i<250;i++)) ; do xwd -silent -id 0x2200042 -out src/`printf '%03d' $i`.wd ; sleep 0.040 ; done

※ 25fps = スクリーンショットの取得間隔 40ミリ秒 (sleep 0.040)
※ 特定のウインドを示す"-id"の引数"0x220042"はコマンド"xwininfo"で調べる



(2) コマンド"convert"を使ってxwdのダンプファイル(*.wd)をJPEGファイルに変換
$ for i in `ls src` ; do convert src/$i seq/`echo $i | sed 's/wd/jpg/'` ; done


(3) コマンド"ffmpeg"で連番JPEGファイルを動画に変換
$ ffmpeg -i seq/%03d.jpg -vcodec mjpeg -sameq out.avi


キャプ板といった特別なハードは必要なく、適当な速さ(上記例では40ミリ秒)で
スクリーンショットを連続取得さへできれば動画を製作できるのでお手軽でした。


環境

OS: Linux
debian-etch (i386)
linux-2.6.18
Xorg-7.1.1
xscreensaver-5.04
ffmpeg-SVN-r13618

※ xwdはパッケージ"xbase-clients"に含まれる
※ convertはパッケージ"imagemagick"に含まれる