Nanashi-softプログラマ専用Photoshopプラグイン開発


◇Photoshopプラグイン開発 -16bit画像減色(1-

●16bit画像仕様の再確認

16bit画像の仕様を間違えていました
Unity3Dの 16bitテクスチャーを作りたいので,その仕様に合わせる必要があります
R4 G4 B4 A4だそうです
ですから後ろ 4bitをカットする必要があります
if (depth == 32)
	*fPixel = fColor;
else if (depth == 16)
	*bigPixel = bigColor;
else {
	*pixel = *pixel & 0xf0;	//マスクが0xf8では無く0xf0
}

このフィルタを通すと,実際の Unity3Dでの画面とよく似た状態になります
とても残念な画像に……

これをどうにかしたい,というのが今回の企画です('-'*)

●RGBAを見分けたい

この DissolveRectangle関数に来た時には,RGBAのどのカラーかはわかりません
その区別を送ってやるように改造します

InitData関数で,gData->colorArray[1]にセットしたカラーは,gData->colorに格納されています
↓サンプルソースのその部分
~略~
SetColor(gData->colorArray[1], 0, 0, 255, 0);
~略~
for(int a = 1; a < 4; a++){
	ConvertRGBColorToMode(gFilterRecord->imageMode, gData->colorArray[a]);
}
CopyColor(gData->color, gData->colorArray[gParams->disposition]);
~略~

DissolveRectangle関数を呼ぶ直前に,そこから1つずつデータを取り出しています
↓サンプルソースのその部分
~略~
if(plane < expectedPlanes){
	color = gData->color[plane];
}

DissolveRectangle(gFilterRecord->outData,
				  gFilterRecord->outRowBytes,
				  gFilterRecord->maskData,
				  gFilterRecord->maskRowBytes,
				  GetOutRect(), 
				  color,
				  gFilterRecord->depth);
~略~
ですから,この plane変数が RGBAを示すものと推測できます
colorに plane値を入れてしまいます。ある意味 colorと言うのも合っていますし
~略~
color=(uint8)plane;	//planeは0:R,1:G,2:B,3:Aと思われる
DissolveRectangle(gFilterRecord->outData,
~略~
本当にそうなのかを検証してみます
DissolveRectangle関数で *pixelに代入する際に,赤だけ塗りつぶしてみます
if (depth == 32)
	*fPixel = fColor;
else if (depth == 16)
	*bigPixel = bigColor;
else {
	if(color == 0){		//Rの時
		*pixel=0xff;
	}else{
		*pixel=0x00;	//それ以外の時
	}
}
そうするとRだけがMAX状態になりました
これでうまくいきました

●データが失われないように,右のドットに足すロジック

なぜ大きく劣化するのか? それは,右4bit分のデータが失われてしまうからではないか?
と思ったので,カットしたデータを,すぐ右のドットに足してみる

余りを保持するスタティック変数を,関数の先頭に追加
static uint8 amari[4]={0,0,0,0};	//余りを保持する変数
前に捨てたデータを,次のドットに加算します
ただし,255を越えてはいけませんので,その場合は 255に丸め込みます
if (depth == 32)
	*fPixel = fColor;
else if (depth == 16)
	*bigPixel = bigColor;
else {
	if(0xff < (int)*pixel + (int)amari[color]){
		*pixel = 0xff;	//255を越えた場合丸め込む
	}else{
		*pixel = *pixel + amari[color];	//前に捨てたデータを加算
	}
	amari[color] = *pixel & 0x0f;	//捨てるデータを保持

	*pixel = *pixel & 0xf0;
}


グラデーションの縞模様が随分改善されている事がわかる

こういうディザリングを多用した画像は圧縮率が落ちる気がするが,実はテクスチャー圧縮ロジックには関係ない
高速に展開して描画しなければならないので,固定調圧縮が用いられている為です
つまり,どんな画像でもメモリ占有値は同じです

あと透過が無いのであれば,フォーマットを Compressedにするとよりメモリ消費量を抑えられます
Androidの ETC1や iOSの PVRTCも色情報部分は 4bitなので,大体この 16bit減色でいい感じの絵になります

つづく)


TOPプログラマ専用Photoshopプラグイン開発

メイナの実験場~素朴なツインテ娘+たくし上げ~