2013年1月18日金曜日

ghostScriptのラスタライズが正しく透過されない件。

何の話かというと、。。。。

ghostScriptでPDFをPNG出力させてみても、バックが正しく透明にならない。
-sDEVICE=pngalpha を指定しても、『中途半端に透過』しているだけなのだ。
図形があると、そのboundingboxの背景が白くなり、早い話使い物にならない。

ということで、これを正しく透過させるべく、いろいろやってみた。
もちろん、ghostScriptのソースに手をいれればいいのだが、再配布のときにめんどいので、ここではghostScriptには手を入れずにやってみる。

しかしながら、普通に考えたら無理なのである。
透過して白なのか、白い矩形があって白なのかは、ラスタライズされた画像をみても区別がつかないのである。
で、ここでは、どうやってそうするかは別にして、PDFの中のエンティティの色を全て黒くすればそれらしくできるのである。

もちろんPDFの中身のエンティティの色を全て黒にするとなると、それはそれで面倒な話ではあるが、ここではそれには触れない。

ということで、今回やりたかったことは、
↓この画像

を使って、
↓この画像

を生成することである。
そのためには、結論から言えば
↓こういう画像

が必要になるのである。


理論的には、。。。。

透過属性をもつPNG画像を、何かの画像の上に置くならば、その1ピクセルに着目すると、
PIXELの色は、
元々のPIXELの色*(1-PNGの当該PIXELのアルファ値)+PNGの当該PIXELの色*PNGの当該PIXELのアルファ値
である。<br/>
よってこれを逆算すればいいのだ。

以下は実際のコードのLOOPの中で、1ピクセルに対しての処理を行っている部分である。
unsigned int alp = bvalue ^ 0xff;

unsigned char* bp = (unsigned char*)pN;
unsigned int BB = bp[0];
unsigned int GG = bp[1];
unsigned int RR = bp[2];

int vBB = (0xff * (BB - 0xff + alp)) / alp;
int vGG = (0xff * (GG - 0xff + alp)) / alp;
int vRR = (0xff * (RR - 0xff + alp)) / alp;

if(vBB < 0)  vBB = 0; if(vBB > 255) vBB = 255;//いらない気が^^;
if(vGG < 0)  vGG = 0; if(vGG > 255) vGG = 255;//いらない気が^^;
if(vRR < 0)  vRR = 0; if(vRR > 255) vRR = 255;//いらない気が^^;

unsigned int vv = (alp << 24) | (vRR << 16) | (vGG << 8) | vBB;


0 件のコメント:

コメントを投稿