【第4回】にっこちゃんを描いてやんわりと関数・モジュールを学ぶ(解説編)

にっこちゃん pythonで簡単プログラミング

#python #モジュール #関数 #変数 #クラス #オブジェクト #絵 #線 #円 #円弧 #色

今回は前回の『にっこちゃん』のプログラムの中身について解説します。

本記事では、主としてWindows、および、python3を前提にしています。
スポンサーリンク

前回掲載のプログラム

にっこちゃんのプログラムを再掲載します。

from PIL import Image, ImageDraw

im = Image.new('RGB', (500, 500), (255, 255, 255))
draw = ImageDraw.Draw(im)

draw.ellipse((20, 20, 480, 480), fill=(255, 255, 0), outline=(0, 0, 0))
draw.ellipse((150, 100, 200, 200), fill=(0, 0, 0), outline=(0, 0, 0))
draw.ellipse((300, 100, 350, 200), fill=(0, 0, 0), outline=(0, 0, 0))
draw.line((250, 250, 250, 280), fill=(0, 0, 0), width=30)
draw.arc((100, 200, 400, 400), 0, 180, fill=(0, 0, 0), width=30)

im.show()

モジュールとは

プログラムの最初の行に記載してある、以下の部分で、”PIL”というものが モジュール と呼ばれるものです。

from PIL import Image, ImageDraw

モジュール とは、よく使われる関数などを1つにまとめたもののことです。
そのため、モジュールがないと、自分で1からプログラムを作成する必要があるのですが、モジュールがあることで、そういったことが必要なくなります。
他の言語では”ライブラリ”や”パッケージ”と呼ばれることがあります。

なお、上のプログラムでは、import Image, ImageDrawと記載されていますが、これは、PILモジュールの中から、Image, ImageDrawというクラスを取り出すということを表しています。
クラスとは分類のことで、そういう分類の仕方で中身が分類されているのだなと考えれば充分です。
また、Image, ImageDrawクラスは、後でプログラム中で使うからこそ、取り出しているのだということです。必要のないものを取り出すことも可能ですが、その場合、単に無駄となります。

関数とは

関数とは、中学で習う y = f(x1,x2,…) の形になるものです。
x1, x2, … という入力を与えると、f() で計算した結果が出力となって y に入ります。
プログラムの場合も、似たようなものですが、少々違います。
それは、

・ 入力する x1, x2, … が無いことがある
・ 計算だけでない動きがある(例 画面に描く、音を鳴らす、機械を操作する)
・ 結果が返らないことがある つまり y に代入できるものが無いことがある
・ 計算や動きの途中でエラーになったり突然終了することもある

という点です。
にっこちゃんのプログラムにおいては、最初の行以外は全て関数を実行しています。

from PIL import Image, ImageDraw

im = Image.new('RGB', (500, 500), (255, 255, 255))             ⇦ 関数を実行
draw = ImageDraw.Draw(im)                                                ⇦ 関数を実行

draw.ellipse((20, 20, 480, 480), fill=(255, 255, 0), outline=(0, 0, 0))  ⇦ 関数を実行
draw.ellipse((150, 100, 200, 200), fill=(0, 0, 0), outline=(0, 0, 0))   ⇦ 関数を実行
draw.ellipse((300, 100, 350, 200), fill=(0, 0, 0), outline=(0, 0, 0))   ⇦ 関数を実行
draw.line((250, 250, 250, 280), fill=(0, 0, 0), width=30)          ⇦ 関数を実行
draw.arc((100, 200, 400, 400), 0, 180, fill=(0, 0, 0), width=30)      ⇦ 関数を実行

im.show()                                                              ⇦ 関数を実行

上述のプログラム中の関数が何をしているのかを見ていきます。

画像を描くキャンバスの作成

im = Image.new('RGB', (500, 500), (255, 255, 255))

この行では、にっこちゃんを描くためのキャンバス(Imageオブジェクト(*1))を作成しています。
Image.new()がImageオブジェクトを作るという処理になります。
作ったキャンバスは後で使うので、 im という変数(変化する数:ここでは入れ物と考えます)に覚えさせています。

Image.new()には ’RGB’, (500, 500), (255, 255, 255) と3つの入力を渡しています。
‘RGB’は、色の情報を指定しています。
これは、最後に渡している(255, 255, 255)という入力を RGB形式(Red, Green, Blueの形式)にすることを指定しています。 それぞれ 0 〜 255 で色の濃さが決まります。
つまり、Red = 255, Green = 255, Blue = 255 という3原色を混ぜた色を指定していて、”白”になります。
絵の具とは違って、数字が大きいほど色が濃くなりますが、同時に輝度が上がるので白になるのです。
にっこちゃんを描くキャンバスの色を白にすること を指定しています。

もし、(0,0,0)を指定すると黒、(255,0,0)だと赤、(0,255,0)だと緑、(0,0,255)だと青になります。

2つ目の入力、(500, 500)は、キャンバスのサイズを 500ドット ✕ 500ドット にしています。
ノートPCの画面の場合、1366 ✕ 768 などのサイズが多いと思いますが、この場合、(1366, 768)を指定すると画面一杯の大きさになります。

*1 オブジェクトとは、直訳すると物のことで、プログラミングの世界では、実際に目の前に物があるわけではないので、物として扱える情報の塊のことを指します。
この情報の塊は、パソコンやサーバーの中にあるメモリ(記憶チップ)の中をちょっとだけ切り取って、そこに記憶されます。
オブジェクトに関しては、本来はもっと厳密な説明が必要なものです。
小生のブログでもいずれ説明していきますが、興味のある方は『オブジェクト指向』について調べると、より厳密に理解できると思います。

書く絵を覚えておくバケツを作成する

draw = ImageDraw.Draw(im)

この行では、変数im(=キャンバス)をImageDraw.Draw関数に渡して、描く絵を覚えておくためのバケツ(ImageDrawオブジェクト)を作成しています。
作ったバケツは、後で使うためにdrawという変数に覚えさせています。

顔の輪郭と目を描く

draw.ellipse((20, 20, 480, 480), fill=(255, 255, 0), outline=(0, 0, 0))   ・・・輪郭
draw.ellipse((150, 100, 200, 200), fill=(0, 0, 0), outline=(0, 0, 0))    ・・・右目
draw.ellipse((300, 100, 350, 200), fill=(0, 0, 0), outline=(0, 0, 0))    ・・・左目

上記では顔の輪郭と目を描くために、楕円(ellipse)を描いています。
1行目の輪郭について、見てみます。
1つ目の入力に(20, 20, 480, 480)と書いていますが、これは下記のように楕円を描く左上隅と右下隅の位置を表しています。
位置は、(x, y)座標で表し、左上がx,yともに小さく、右下がx,yともに大きくなる座標になっています。

2つ目の入力に、fill=(255, 255, 0) という指定をしていますが、これは、”fill”とは、満たす、つまり塗りつぶしをすることを指定しています。
そして、RGB形式の色情報が(255, 255, 0)、つまり黄色を指定しています。
3つ目の入力には、outline=(0, 0, 0) という指定をしていますが、”outline”とは輪郭のことで、縁取りの指定をしています。
そして、RGB形式の色情報が(0, 0, 0)、つまり黒を指定しています。

左目、右目については、位置をそれぞれの位置に、サイズを小さめにして、黒で塗りつぶす指定になっています。

鼻を描く

draw.line((250, 250, 250, 280), fill=(0, 0, 0), width=30

鼻を描くために、draw.line()関数で、線を引いています。
1つ目の入力 (250, 250, 250, 280)は、線の視点(255, 255) から終点(250, 280)へ上から下へ線を引くことを指定しています。
2つ目の入力の fill=(0, 0, 0)は、楕円と同じく、黒で塗りつぶすことを指定しています。
3つ目の入力、width=30は、width=幅、つまり線の幅太さを30ドットにすることを指定しています。

口を描く

draw.arc((100, 200, 400, 400), 0, 180, fill=(0, 0, 0), width=30)

口の形は弓の形=弧(arc)になるため、draw.arc()で描きます。
1つ目の入力 (100, 200, 400, 400) は、楕円と同じように、弧の左上隅(100,200)と右下隅(400,400)の位置を指定しています。
2つ目と3つ目の入力 0 と180 は、時計の3時の位置を0度として、どこから弧を描き始めてどこで終わるのかを指定しており、0度〜180度まで時計回りで描くことを指定しています。
4つ目と5つ目の入力は、鼻と同じ指定をしています。

バケツに溜めた絵を画面に表示させる

im.show()

ようやく、バケツにさんざん溜めていった絵を表示させるときが来ました。
ここに来るまで、”描く”と言っていましたが、実はバケツの中に放り込んでいただけです。
im.show()で画面に表示されます。
単に表示をするだけのため、入力も出力もありません。

最後に

いかがでしたでしょうか?
今回はプログラムの中身を解説しました。
お題がにっこちゃんのお絵かきのため、お絵かきをする関数ばかりでしたが、それでも、

など、いろいろな要素が詰まっていました。

これだけの要素が出てくる題材はコンピューターグラフィックス(CG)だからこそですので、CGを描くのではないプログラムはもっとシンプルです。

ということで、次回にまた面白い題材をご用意しますので、ご期待ください!

この記事へのお問い合わせや、一歩踏み込んだサポートが必要な場合は、
ホームページからメールで受け付けています。お気軽にご連絡ください。

0

コメント

タイトルとURLをコピーしました