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;


2013年1月15日火曜日

プロットされた点を曲線で結ぶ件。

久々の更新。 どーもFBには書くけど、BLOGの更新をしないようになってしまった。
今年はもうちょっと書こう。
 ってことで、ありがちだけど、プロットされた点を結んで曲線補完。  
今回の条件は、
【XによってYが一意に決まること。】
よって、曲線としては滑らかであっても、XによってYが2つ3つ値をとるようでは困るので、
 制御点の取り方を工夫。 

また、最初と最後(点A-B間、D-E間)に関しては、 制御点を2つ取れないので、
この部分は2次Bスプラインで考える。
1つの点を共用して3次(ベジェ)で考えてもいいのだが、
やってみたらあまり滑らかな線にならなかったので、2次とした。

 流れ。
A,B,C,D,Eが与えられる。
B,C,D(最初と最後を除いた点)については、その左右に制御点をとる。
制御点の取り方だが、Bを例にして考えるならば、B1-B-B2は一直線となり、
直線A-Cと平行になるような点をとる。
あとは、B1-B、B-B2の長さだが、B1-B2が直線A-Cの長さの固定倍とし、
Bが内分する点となるようにするのだが、 今回はX座標の比率(X(B-A):X(C-B)の比率となるように、 B1,B2をとってみた。 

まぁ所詮、曲線補完なので、何が正しいってわけじゃないので、
今回の要件はこの程度で。。

 2次のBスプラインの説明は、
http://opentype.jp/fontguide_doc2.htm
ベジェの説明は、
http://opentype.jp/fontguide_doc3.htm

がわかりやすい。と思う。思うだけかも。。