仮眠プログラマーのつぶやき

自分がプログラムやっていて、思いついたことをつぶやいていきます。 2025年からzennに移行

自作ゲームやツール、ソースなどを公開しております。
①ポンコツ自動車シュライシュラー
DOWNLOAD
②流体力学ソース付き
汚いほうDOWNLOAD
綺麗なほうDOWNLOAD
③ミニスタヲズ
DOWNLOAD
④地下鉄でGO
DOWNLOAD
⑤ババドン
DOWNLOAD
⑥圧縮拳(ツール)
DOWNLOAD
⑦複写拳
DOWNLOAD
⑧布シミュレーション
DOWNLOAD
⑨minecraft巨大電卓地形データ
DOWNLOAD
⑩フリュードランダー
デジゲー博頒布α版
DOWNLOAD
⑪パズドラルート解析GPGPU版
DOWNLOAD
⑫ゲーム「流体de月面着陸」
DOWNLOAD

セピア

セピア色変換プログラム② グレースケール+?=セピア

まず簡略化の前に前回言い忘れてたことがあります。
行列の計算はdouble型の変数で行なっていましたってことです。


普通HSP以外では小数入りの計算は整数の計算と比べて劇的に遅く、セピア変換の計算などは整数型の変数を全部1024倍して計算するのが主らしいのですが、私の扱っているHSPは小数の計算も整数と同じくらいの速さなので正直に小数入り変数double型で計算をしている構造になっています。


ところで出力は整数型でいいのに何で小数入り型にしたり1024倍したりするのかは分かりますよね・・?小数切捨てで誤差ができるのを防ぐためです。



ではそろそろ本題のアルゴリズム簡略化に着手しましょう!



まず、どう考えても無駄なのはRGB→YUVの作業のUを決める計算とVを決める計算です。
どうせ2、3行後で定数を代入されるのですから・・・・


で、いっそのことUとVの変数を削除してしまえという結論にたどり着きます。


するとループ内の計算は以下のようになります。



gsel 1

pget cnt,a:r=ginfo_r:g=ginfo_g:b=ginfo_b           ; RGB値を取得し代入

y=0.299*r+0.587*g+0.114*b                 ; 行列の計算1


r=1.0*y+1.402*14.336                  ; 逆行列の計算1

g=1.0*y+0.334*23.296-0.714*14.336         ; 逆行列の計算2

b=1.0*y-1.772*23.296                 ; 逆行列の計算3

gsel 2

color r,g,b

pset cnt,a




あとは掛け算と足し算をあらかじめ計算し終えておけば




gsel 1

pget cnt,a:r=ginfo_r:g=ginfo_g:b=ginfo_b       ; RGB値を取得し代入

y=0.299*r+0.587*g+0.114*b              ; 行列の計算1

r=20.01+y                         ; 逆行列の計算1

g=-2.46+y                         ; 逆行列の計算2

b=-41.28+y                        ; 逆行列の計算3

gsel 2

color r,g,b

pset cnt,a



とこうなり

もう r g bの変数も必要ないと思うようになり


gsel 1

pget cnt,a

y=0.299*ginfo_r+0.587*ginfo_g+0.114*ginfo_b

gsel 2

color 20.01+y,-2.46+y,-41.28+y

pset cnt,a



ここまで簡略化することができました!!

最初r g b y u vの6つだったのがもうyしか変数が残っていません!!


さてここで、プログラムをよく見てほしいのですがこれはグレースケール変換プログラムにすごい似ているのです。

グレースケール変換プログラムはこれです。(ループ内のみ)


gsel 1

pget cnt,a

y=0.299*ginfo_r+0.587*ginfo_g+0.114*ginfo_b

gsel 2

color y,y,y

pset cnt,a


見てください。color の指定以外全部一緒です!

つまりセピア画像はグレースケール画像に色をちょっと加算&減算しただけのもので、セピア限定のなにか特別な処理方法で算出した色ではなかったと言うことです!!


見た目は違えどカレーとシチューみたいに途中まで作り方が同じだったってことに自分で発見したとき驚きでした!!                      (例えに無理あるなw)

「セピア変換プログラム」でググってでてきたページの中に、誰もグレースケールにちょっと色を加えるだけだよ、と書いてなかったのでなんか自分が一番最初に発見した、エライ人みたいな気分になってます(笑)





ところでまた話はそれますがグレースケールの計算でなぜ(R+G+B)/3じゃないのか

って思うかもしれません。


私も最初そう思いました。

一応それでも正解なのだそうですが、人間の目では緑の明るさがより強く感じられるみたいなので、

そこを考慮すると全て3分の1すりゃいいってわけにはいかんみたいなんです。


なので人間の目に対してよりリアルなグレースケール画像を作りたかったら↑の計算式を

コンピューターに対してよりリアルなグレースケールなら全部3分の1って計算でっでいうことでおkみたいです

セピア色変換プログラム① YUV値とは

お恥ずかしながらHSPコンテストに公開したセピアフィルターについて解説したくなったので、勝手にしていきたいと思います。

まずセピア色とは、イカ墨で描かれた茶色っぽい色のことです。
写真などを古く見せたい場合などは、カラー写真をわざとセピア調に変換したりしますよね。



で、プログラムはどうなってるかというとまず1ドットずつR、G、Bを取得しその数値をY、U、Vという形に変換します。そしてU=-23.296V=14.336 としてまたR、G、Bの形に変換してスクリーンに反映させます。


ここで、一応補足ですがR、G、B、Y、U、Vは全部変数で、Rにも0~255の整数が、Gにも0~255が、Bにも0~255が、Yにも0~255、Uには-128~127が、Vにも-128~127が・・・とそれぞれ6つの変数全部が256通りの色の情報を持っています。(24bitフルカラーの場合)



下にRGB→YUVの変換式(回転行列)とその逆行列YUV→RGBを載せました↓

ce107ac6.jpg


 

図では行列が描いてありますが、プログラムではちゃんと計算式に展開しないといけません(少なくともHSPの場合)。


これをすべてのドットで行うと、どんな画像でもちゃんとお望みのセピアになっているはずです!




例えばHSP言語で書くとどうなるか


横30縦20ドットで

1のバッファに変換前2のバッファに変換後の画像が出力されるようなプログラムで行きたいと思います



reepat 20

a=cnt

reepat 30

gsel 1

pget cnt,a:r=ginfo_r:g=ginfo_g:b=ginfo_b ; RGB値を取得し代入

y=0.299*r+0.587*g+0.114*b ; 行列の計算1

u=-0.169*r-0.331*g+0.5*b ; 行列の計算2

v=0.5*r-0.419*g-0.081*b ; 行列の計算3

u=-23.296:v=14.336

r=1.0*y+1.402*v ; 逆行列の計算1

g=1.0*y-0.334*u-0.714*v        ; 逆行列の計算2

b=1.0*y+1.772*u           ; 逆行列の計算3

gsel 2

color r,g,b

pset cnt,a

loop

loop


以上です。

そのままコピペして実行してもエラーになります(バッファの確保は各自でお願いします)



さて今のままでは計算時間が膨大になり非効率なので、次回は↑の変換アルゴリズムをどんどん簡略化していきますよー!

無駄な計算を省いていくと、最後にある発見をします。


次回:セピア色変換プログラム② グレースケール+?=セピア

最近適当になってきたなぁ

気づいたら全然更新していませんでした・・・


でもわざわざブログ書く時間もないので今日は1行プログラムで、


カラーの画像をモノクロ化するプログラムです。


正直1行じゃ誰もわからないと思うので1行を見やすくして40行くらいに展開してみました



dialog "*",16,"画像ファイル読み込み"
picload refstr,1


buffer 1,1280,480,0
buffer 2,640,480,0
color 0,0,0:boxf
mref a2,66
buffer 3,640,480,0
color 0,0,0:boxf
mref a3,66
buffer 4,640,480,0
color 0,0,0:boxf
mref a4,66

gsel 1
redraw 0
pos 0,0:gmode 0:gcopy 0,0,0,640,480
color 255,0,0
boxf 640,0,1280,648

gsel 2
redraw 0
gmode 7,640,480,256
pos 0,0:gcopy 1,0,0,640,480
gmode 3,640,480,170
color 0,0,0:grect 320,240,0,640,480
memcpy a4,a2,480*640*3-2,0,2

gsel 1
color 0,255,0
boxf 640,0,1280,480

gsel 2
color 0,0,0:boxf
gmode 7,640,480,256
pos 0,0:gcopy 1,0,0,640,480
gmode 3,640,480,170
grect 320,240,0,640,480
memcpy a3,a2,480*640*3-1,0,1


gsel 1
color 0,0,255
boxf 640,0,1280,480

gsel 2
color 0,0,0:boxf
gmode 7,640,480,256
pos 0,0:gcopy 1,0,0,640,480
gmode 3,640,480,170
grect 320,240,0,640,480

buffer 1,640,480,0
mref a4,66
color 0,0,0:boxf
gmode 5,640,480,256
pos 0,0:gcopy 2,0,0,640,480
pos 0,0:gcopy 3,0,0,640,480
pos 0,0:gcopy 4,0,0,640,480

gsel 2
color 0,0,0:boxf
memcpy a2,a4,480*640*3-1,1,0

gsel 3
color 0,0,0:boxf
memcpy a3,a4,480*640*3-2,2,0


gsel 0
redraw 0
color 0,0,0:boxf
gmode 5,640,480,256
pos 0,0:gcopy 2,0,0,640,480
pos 0,0:gcopy 3,0,0,640,480
pos 0,0:gcopy 1,0,0,640,480
redraw 1


buffer 4,4,4,0
buffer 3,4,4,0
buffer 2,4,4,0
buffer 1,4,4,0
sdim a2,1
sdim a3,1
sdim a4,1

プロフィール

toropippi

記事検索
アクセスカウンター

    QRコード
    QRコード
    • ライブドアブログ