SATySFiでお絵描き

これは2018 SATySFi advent calendar 16日目の記事です。[] [次]

SATySFiには基本的な図形描画機能が備わっていますが、「え…ベクタ描画? そんなハイカラなの難しそう…ドットで描けないの…?」みたいな人もいると思うので、疑似ピクセル単位で画像を描画するコマンドを作ってみました。

https://github.com/youz/satysfi-pixels

使い方

上記リポジトリからpixels.satyhを持ってきて、packagesディレクトリに放り込んで@require: pixelsするか、書いてる文書と同じフォルダに置いて@import: pixelsして下さい。 するとインラインコマンド\Pixelsが使えるようになります。

% Pixelsコマンドのシグネチャ
   \Pixels : [length * length * length; int * int; int -> int -> color] inline-cmd
  • 第1引数は出力する画像の幅, 高さ, 深さのタプル (最終的にinline-graphics関数に渡す値)
  • 第2引数は画像のピクセル数での幅, 高さのタプル
  • 第3引数はx, y座標を受け取ってcolorを返す関数

となっています。

使用例1

@require: stdja
@import: pixels

let get-color x y =
  Gray(float x /. 255.)

in
document (|
  title = {gradation sample 1};
  author = {};
  show-title = false;
  show-toc = false;
|) '<
  +p{
    \Pixels((100pt, 100pt, 0pt))((256, 256))(get-color);
  }
>

get-color関数は受け取ったx座標を255で割り、モノクロ色の値として返します。

本文中の\Pixelsコマンドの引数は、「出力サイズが100pt x 100ptで画素数が256px×256pxのgraphicsを生成して埋め込みます。各ピクセルのRGB値はget-color関数で決定します。」という意味になります。

これをコンパイルすると下図のような画像がインライングラフィクスとして出力されます。

f:id:youz:20181216235710p:plain
サンプル1

もう1つサンプルコード

@require: stdja
@import: pixels

let get-color x y =
  let r = x mod 256 in
  let g = y mod 256 in
  let b = 255 - (x mod 256) in
    RGB(float r /. 255., float g /. 255., float b /. 255.)

in
document (|
  title = {gradation sample 2};
  author = {};
  show-title = false;
  show-toc = false;
|) '<
  +p{
    \Pixels((100pt, 100pt, 0pt))((512, 512))(get-color);
  }
>

今度はモノクロではなくカラーで。 RGB各色を以下のように座標から決定するようにしています。

  • R = x mod 256 / 255
  • G = y mod 256 / 255
  • B = (255 - (x mod 256)) /255

また、画像サイズは変わりませんがピクセル数を512x512に変更しました。(解像度が変わります)

すると今度は下図のような出力になります。

f:id:youz:20181217000714p:plain
サンプル2

その他、ソースリポジトリに入れてあるサンプルを画像だけ紹介

f:id:youz:20181217000818p:plain
bitxor (x ^ y)

f:id:youz:20181217000824p:plain
マンデルブロ集合

f:id:youz:20181217000904p:plain
Ambient Occlusionによるレンダリング (こちらのコードを移植)

楽しいですね。いろいろ関数つっこんで遊んでみて下さい。

なおピクセル数を増やして行くとPDFビュアーでの描画が目に見えて重くなるのでそこはご注意を。