秋といえば芸術の季節です。秋には各地で芸術祭や展覧会が開催されることから「芸術の秋」なんて言われたりもします。現在は秋の気配どころか立春が過ぎたばかりではありますが、今回は芸術の話です。
なぜに芸術?
現在、六本木の国立新美術館などで「平成27年度[第19回]文化庁メディア芸術祭受賞作品展 」が開催されています(2月14日まで) 。これは昨年秋に発表された「平成27年度[第19回]文化庁メディア芸術祭 」の受賞作品を展示する展覧会です。その一つの「アート部門」の大賞が、CHUNG Waiching Bryanさんによる、「 50. Shades of Grey 」と題した「プログラムのソースコード」だったのです[1] 。
そのコンセプトとか芸術性とか受賞理由は、公式サイトを参照してください。プログラムのソースコードをどのように「展示」しているかというと、「 プリントアウトして額縁に入れて展示」だとか。すごいアナログです。
Ubuntuが関わってくるのはここからです。プログラムのソースコードですから、もちろん実行環境が必要です。この作品は「作者と同年生まれのBASICから2000年のActionScriptまで」の6種類の言語それぞれで、「 黒から白への50階調のグラデーションを表示」するソースコードを記述しています[2] 。つまり6種類の言語の実行環境が必要になるわけです。
その言語は、「 BASIC」「 Fortran」「 Pascal」「 Lisp」「 Lingo」「 ActionScript」の6種類です。作者が過去に触ったことのある郷愁を感じる言語ということなので、若干偏っているかもしれません。作者のサイトの作品ページ を見るとわかるのですが、このうち4つについてはUbuntu上で実行しています。実際、作品展でも実行結果の展示にUbuntuが使われているようです。
ということで、実際にUbuntuで試して現代の「メディア芸術」に触れてみることにしましょう。
「BASIC」編
「BASIC」は初心者向けに開発されたプログラミング言語であり、さまざまな環境に移植された言語です。今回はグラデーションを表示しなくてはならないので、SDLを使ってゲーム開発関連の機能を充実させた 「 sdlBasic 」を利用します。
$ sudo apt-get install sdlbasic
desktopファイルもインストールされますので、たとえばUnityならアプリレンズを開いて「sdlbasic」と 入力して表示されるsdlBasicのアイコンをクリックして起動しましょう。作者のサイトにある以下のコードを入力して、保存します。ファイル名の拡張子は「.sdlbas」としてください。
width = 800 : height = 800 : shades = 50
inc = width / shades
setdisplay ( width , height , 32 , 1 )
paper ( rgb ( 255 , 255 , 255 ))
cls
setautoback ( 25 )
for i = 1 to shades
c = i * 255 / shades
ink ( rgb ( c , c , c ))
bar (( i - 1 )* inc , 0 , i * inc , height )
next
waitkey ( k_escape )
図1 ごくごくシンプルなエディタ画面
保存が完了したら、画面右上の再生ボタン(Goボタン)を押してください。
図2 sdlBasicによる「50. Shades of Grey」
コードのうち、setdisplay()でウィンドウを作成し、peper()とrgb()で背景色を白に設定し、clsで画面をクリアし、setautoback()でダブルバッファリングのために画面を切り替える時間を設定しています。
forブロックでは、黒から白へとRGBの値を50段階で変化させたペンをinc()で作成し、bar()で縦長の長方形を描画することを繰り替えします。最後のwaitkey()では、エスケープキーの入力を待ってプログラムを終了しています。
ちなみにここで出てきた関数はすべてsdlBasic由来のものです。つまり他のBASIC実装ではおそらく動きません。
「Fortran」編
FortranはBASICよりも歴史が古いながらも、今でも仕様の更新が続いているプログラミング言語です。Fortranは数値科学計算が主な用途であり、組み込みのGUI機能がありません。グラデーションを表示させるために「GNUFOR2 」というGnuplotと連携するモジュールを使います。
$ sudo apt-get install gfortran gnuplot-x11
GNUFOR2からGnuplotを実行するため、gnuplot-x11もインストールしています。Qt4版のgnuplot-qtでもかまいません。
Fortranのコードを記述し、fifty.f90として保存します。
program grey
use gnufor2
implicit none
integer , parameter :: Nm = 800
integer :: rgb ( 3 , Nm , Nm )
integer :: i , j , k
integer :: shades
integer :: step
integer :: c
shades = 50
step = Nm / shades
do i = 1 , shades
c = ( i - 1 )* 255 / shades
do j = ( i - 1 )* step , i * step
do k = 1 , Nm
rgb ( 1 , j , k ) = c
rgb ( 2 , j , k ) = c
rgb ( 3 , j , k ) = c
end do
end do
end do
call image ( rgb , pause =- 1.0 , persist = 'no' )
end program grey
fifty.f90と同じディレクトリにGNUFOR2モジュールをダウンロードして、コンパイルし、実行します。
$ wget http://www.math.yorku.ca/~akuznets/gnufor2/gnufor2.f90
$ gfortran gnufor2.f90 fifty.f90 -o fifty.out
$ ./fifty.out
図3 Fortran+Gnuplotによる「50. Shades of Grey」
こちらはBASICの時と違って、Fortran 90をサポートする実装であればほぼそのまま動くでしょう。GNUFOR2の中ではsystem関数越しにgnuplotコマンドを実行しているため、あらかじめgnuplotをインストールしておく必要はあります。
コードの前半はごく普通のFortranです。縦横800ドットにそれぞれRGB値を格納する三次元配列rgbを作成して、そこに一つずつ色の値を放り込んでいます。それをGNUFOR2が提供しているimage()関数に渡しているだけです。「 pause=-1.0」はリターンキーを押すまでプロセスの終了を待ち、「 persist='no'」はgnuplotコマンドが実行されたら 直ちに描画することを意味します。
「Pascal」編
Pascalもまた歴史のあるプログラミング言語の一つです。Ubuntuで使えるPascalコンパイラとしては「Free Pascal 」が存在します。しかしながら今回はGUIのウィンドウを表示する必要があります。「 Lazarus 」はFree Pascal向けの統合開発環境であり、さらに独自のGUIライブラリを持っています。よってこれを使うことにしましょう。
$ sudo apt-get install lazarus
グラフィック関連の開発パッケージも必要になるため、かなりの量のパッケージがインストールされます。sdlBasicと同様にdesktopファイルもインストールされますので、たとえばUnityならアプリレンズを開いて「lazarus」と 入力して表示されるLazarusのアイコンをクリックして起動しましょう。「 パッケージファイルが見つかりません」ダイアログが表示されたら「OK」ボタンを押しておきます。
自動的にテンプレートコードが設定されますが、すべて削除した上で作者のサイトにある以下のコードを入力し、保存します。
unit Unit1 ;
{ $mode objfpc }{ $H +}
interface
uses
Classes , SysUtils , FileUtil , Forms , Controls , Graphics , Dialogs , StdCtrls ;
type
{ TGrey }
TGrey = class ( TForm )
procedure FormPaint ( Sender : TObject );
private
{ private declarations }
public
{ public declarations }
end ;
var
Grey : TGrey ;
idx : integer ;
shades : integer ;
step : integer ;
col : integer ;
implementation
{ $R *. lfm }
{ TGrey }
procedure TGrey . FormPaint ( Sender : TObject );
begin
shades := 50 ;
step := Round ( Grey . width / shades );
for idx := 0 to ( shades - 1 ) do
begin
col := 255 - Round ( idx * 255 / shades );
canvas . Brush . Color := RGBToColor ( col , col , col );
canvas . FillRect ( 0 , 0 , ( shades - idx )* step , Grey . height );
end ;
end ;
end .
図4 マルチウィンドウ形式のLazarus。
次にフォームの名前をコードにあわせて変更します。「 Form1」というタイトルのウィンドウを右クリックし、「 ソース(.lfm)を表示」を選択します。ソースを保存するかどうかは「Yes」と回答してください。unit1.lfmが表示されるので、以下の内容に更新します。
object Grey : TGrey
Left = 182
Height = 800
Top = 243
Width = 800
Caption '50. Shades of Grey'
OnPaint = FormPaint
LCLVersion = '1.0.10.0'
end
さらにLazarusのアイコンが並んだウィンドウを選択し、メニューの「プロジェクト」から「プロジェクトソースを表示」を選択します。18行目の「Application.CreateForm」の行を次のように変更してください。
Application . CreateForm ( TGrey , Grey );
ここまでの編集内容を「Ctrl-S」で保存したらF9キーで実行します。
図5 Pascal on Lazarusによる「50. Shades of Grey」
Lazarusが使っているFree Pascalは、オリジナルのPascalよりはDelphi(Object Pascal)の書式を使えるような実装になっています。そのため上記のコードもどちらかというとObject Pascalです。またcanvasやlfmファイルなどはLazarus独自の実装です[3] 。
「Lisp」編
Lispも歴史あるプログラミング言語の一つです。今でもEmacsの設定を行う際にLispのコードを 書いているEmacsユーザーも多いことと思います。今回はCommon Lispの実行環境であるSBCL とEmacs上でCommon Lispを編集できるSLIME を利用します。またCommon LispライブラリをロードするためにQuicklisp もあわせてインストールしておきましょう。
$ sudo apt-get install slime cl-quicklisp
$ sbcl --load /usr/share/cl-quicklisp/quicklisp.lisp \
--eval '(quicklisp-quickstart:install)' \
--eval '(ql:add-to-init-file)' \
--eval '(quit)'
sdlBasicと同様にdesktopファイルもインストールされますので、たとえばUnityならアプリレンズを開いて「emacs」と 入力して表示されるEmacsのアイコンをクリックして起動しましょう。次に「M-x slime」( 「 Alt+x」のあとに「slime」と入力)を入力した上で「CL-USER>」と表示されたら、次のコードを入力します。
( ql : quickload : lispbuilder-sdl )
( defvar * SIZE * 800 )
( defvar * SHADES * 50 )
( defvar * STEP * (/ * SIZE * * SHADES *))
( defvar * COL * 0 )
( defun box ( n )
( cond ((>= n * SHADES *) nil )
((< n * SHADES *) ( progn
( setq * COL * (/ (* n 255 ) * SHADES *))
( sdl : draw-box- * (* * STEP * n ) 0 * STEP * * SIZE *
: color ( sdl : color : r * COL * : g * COL * : b * COL *))
( box (+ n 1 ))))))
( sdl : with-init ()
( sdl : window * SIZE * * SIZE * : title-caption "50 . Shades of Grey" )
( setf ( sdl : frame-rate ) 60 )
( sdl : with-events ()
(: quit-event () t )
(: key-down-event () ( sdl : push-quit-event ))
(: idle ()
( sdl : clear-display sdl :* black *)
( box 0 )
( sdl : update-display ))))
SDLのライブラリをインストールするため、実行完了までしばらく時間がかかります。
図6 Lisp on Emacsによる「50. Shades of Grey」
SDLを使って800x800のウィンドウを作成し、縦長の長方形を色を変えながら書き込むところは同じです。また、何かキー入力があればウィンドウを閉じて終了します。
「Lingo」編
LingoはAdobe Systemsが開発するAdobe Director で採用されているプログラミング言語です。残念ながらUbuntu上でLingoをビルドする方法は見つけられなかったため、今回はスキップします。
「ActionScript」編
ActionScriptはAdobe Flashで採用されているスクリプト言語です。名前から推測されるとおり、その文法はECMAScriptに似ています。ActionScriptにはActionScript2とActionScript3が存在します。基本的な文法は似通ってはいるのですが、フレームワークの使い方や型の扱いが変わっているなど、ほぼ別の言語と思ったほうが良いでしょう。
作者のコードはActionScript3を採用しています。UbuntuでActionScript3のコンパイラと言えば、「 Haxe 」があります。ただ試してみた限り、基本的なサンプルからしてコンパイルできない状態でした。そこで今回は作者のコードをActionScript2に移植した上で、ActionScript2に対応したコンパイラである「MTASC 」を 使うことにします。
まずはmtascパッケージに加えて、FlashファイルのスタンドアローンプレイヤーであるGnash もインストールします。
$ sudo apt-get install mtasc gnash
以下のソースコードをfifty.asという名前で保存します。
class Fifty {
static var app : Fifty ;
static var shades : Number = 50 ;
static var width : Number = 400 ;
static var height : Number = 300 ;
var step : Number = 256 / shades ;
var w : Number = width / shades ;
function Fifty () {
var fig = _root . createEmptyMovieClip ( "fig" , 1 );
for ( var i = 0 ; i < shades ; i ++) {
var color = ( i * step << 16 ) | ( i * step << 8 ) | ( i * step );
fig . lineStyle ( 0 , color , 100 );
fig . beginFill ( color , 100 );
fig . moveTo ( i * w , 0 );
fig . lineTo ( i * w , height );
fig . lineTo (( i + 1 )* w , height );
fig . lineTo (( i + 1 )* w , 0 );
fig . moveTo ( i * w , 0 );
fig . endFill ();
}
}
static function main ( mc ) {
app = new Fifty ();
}
}
このファイルをmtascでコンパイルして、fifty.swfとして保存します。
$ mtasc -swf fifty.swf -main -header 400:300:30 fifty.as
あとはGnashで実行するだけです。GnashはUnity上では表示されませんので、ファイルブラウザーから fifty.swfを右クリックした上で、「 別のアプリで開く」の「Gnash SWFビューア」を選択してください。
図7 ActionScriptによる「50. Shades of Grey」
「あなたの言語」編
さていかがだったでしょうか。少しは秋の息吹を感じたり、「 ヴィオロンのためいき」を「ひたぶ」れたりしましたでしょうか。冒頭でも述べたように、今回出てきたプログラミング言語は少々偏っています。せっかくなので、最初に触ったプログラミング言語など各個人の思い入れのある言語で「50. Shades of Grey」を実現してみるのも いいかもしれませんね。