HSP | 透過 PNG で gmode 7 する (その2)

HSP | 透過 PNG で gmode 7 する (その2)

前回はアレで満足してしまったのですが、後になって色々考えてみたら、もっとプログラムを簡単に、しかも処理速度を速くできることに気が付いてしまったので「その2」として書きます (^^;
前の記事を修正するだけで済ませようかとも思いましたが、かなり大部分が書き変わっていて、前の記事の大部分を直さないといけなくなりそうだったので、別記事にすることにしました (^^;

モジュール

主に「#deffunc local draw」の中身が書き変わりました

/**
 * モジュール
 */
#module Pixela

// 
// フィールド
// 
#define global picload_pixela(%1) picload_pixela@Pixela %1

/**
 * 画像ファイルをピクセルアルファブレンドコピーに対応させて読み込み
 * 
 * gmode 7
 */
#deffunc local picload_pixela str fname

load@Pixela fname
draw@Pixela

return

/**
 * 画像読み込み
 */
#deffunc local load str fname

// 出力ウィンドウ
BUFFER_ID_PIXELA = ginfo_sel

// 背景黒バッファ
BUFFER_ID_BG_BLACK = ginfo_newid

buffer BUFFER_ID_BG_BLACK

picload fname, 2

/* 画像サイズ取得 */
img_height = ginfo_winy
img_width  = ginfo_winx

// 背景白バッファ
BUFFER_ID_BG_WHITE = ginfo_newid

buffer BUFFER_ID_BG_WHITE, img_width, img_height

pos 0, 0 : picload fname, 1

// 出力ウィンドウ 初期化
type = ginfo_type(BUFFER_ID_PIXELA)
if ( type == 1 ) {
buffer BUFFER_ID_PIXELA, img_width * 2, img_height
} else : if ( type == 2 ) {
screen BUFFER_ID_PIXELA, img_width * 2, img_height
} else : if ( type == 3 ) {
bgscr  BUFFER_ID_PIXELA, img_width * 2, img_height
}

return

/**
 * ウィンドウの種類取得
 * 
 * 1 = buffer, 2 = screen, 3 = bgscr
 */
#defcfunc local ginfo_type int id
mref bmscr, 96 + id // mref bmscr, 67
return bmscr.17

/**
 * RGBA を計算し出力
 */
#deffunc local draw

gsel BUFFER_ID_PIXELA
mref img_rgba, 66

// アルファ値
gmode 6, , , 256
pos img_width, 0 : gcopy BUFFER_ID_BG_WHITE, 0, 0, img_width, img_height
gmode 5, , , 256
pos img_width, 0 : gcopy BUFFER_ID_BG_BLACK, 0, 0, img_width, img_height

// RGB
gmode 0
pos 0, 0 : gcopy BUFFER_ID_BG_BLACK, 0, 0, img_width, img_height // VRAM のインデックス算出高速化のためにもコピー

index = 0
index_width = img_width * 3
repeat img_height
repeat img_width * 3
alpha = peek(img_rgba, index + index_width)
if ( alpha ) : poke img_rgba, index, 255 * peek(img_rgba, index) / alpha
index++
loop
index += index_width
loop

return

#global

※サンプルはそのまま

変更点1.アルファ値を、HSP の標準機能の加算合成・減算合成を用いて算出

アルファ値の算出の式、よく見たら、「白」に「黒背景画像」を減産合成して「白背景画像」を加算合成してるのと同じじゃないですかっ! (^^;
というわけで、gmode, gcopy だけでアルファ値を算出できます。
HSP の内部での処理に任せた方が断然速いです!

変更点2.RGB 値算出時に、アルファ値 (正規化はしない) を使用

前回の記事で「アルファ値を用いなくても RGB を算出できます」と書きましたが、よく見たら、アルファ値の算出式と全く同じものを書いていました (^^;
ただ、やはり正規化しても処理時間が遅くなるのと、アルファ値を使うにしても、「黒背景画像」に除算をかけるだけで済みます。
…参考にした元のプログラムだと、わざわざ「黒背景画像」と「白背景画像」を加算合成しているのですけど、これ意味ないですよね… (^^;

変更点3.アルファ値 0 の対応

HSP の gcopy の加算・減算合成の誤差??のせいで、アルファ値 0 のパターンがテストできなかったのですが、本来はあるはずなので、アルファ値が 0 の場合は、「黒背景画像」をそのまま残すこととしました。
アルファ値 0 のとき、元の色が算出できないわけですが、そもそも表示されないので何色でもいいですね。

変更点その他

このプログラムを見ただけだと勘違いしやすいですが、画像の下から上に RGB 値を計算していってます。上から下ではありません (^^;
また、「黒背景画像」を一回出力画面にコピーしているのですが、これをしなくても直接 VRAM から色を取得しても良いのですが、画像の横幅が出力画面と異なるため、VRAM のインデックスを別に計算しなければいけなくなり、処理時間が余計にかかるので、gcopy の速度を信じて一回コピーすることにしました (^^;

雑談

もしかしたらまだ何か間違ってるかもしれません…。
アルファ値ズレてるし…なんでだろ??
…また機会があれば調べてみます (^^;
それではまたいつか~ ノシ