2013年2月28日木曜日

で結局、JSONPathのラッパークラスを書く。。

で結局、JSONPathのラッパークラスを書いてみた。
当然、どー使いたいかを書いてからコーディング。
★使い方のイメージ
$p = new gJPath;
$p->setJson($json);
$patstr = $p->getPathOne("$..author2"); // patString所得
$value = $p->getValueDirect($patstr);  // 所得
$p->setValueDirect($patstr,$newValue);  // 設定
こんな感じで。
できたけど、、これからテスト&デバッグ。

今さらながらJSONPath。(PHP)

なぜ今さらながらJSONPathかっていうと、どうにもいい感じにつかえるやつがなかったのです。
http://goessner.net/articles/JsonPath/
LastUpdateが2007年だけど^^;^^;
で、テストコードを書いてみると、ちょっとイイ感じです。
何がイイかって、resultTypeに"PATH"なるものが設定できるところで、この先頭の$を削除してObjectの変数名をつっこみ、
"黒魔術"のevalで、参照したり設定したり。
※javascriptの方も同様にできました。
●テストコード
 require_once "pear/Var_Dump.php";
 require_once "./jsonpath-0.8.1.php";

 $jstr = file_get_contents('samplejson.txt');
 $json = json_decode($jstr,true);

 $match1 = jsonPath($json, "$..author");
 $match2 = jsonPath($json, "$..author", array("resultType" => "PATH"));

 $res1 = Var_Dump::display($match1,true);
 $res2 = Var_Dump::display($match2,true);

 header( "Content-Type:text/html; charset=utf-8");

 $idxstr = $match2[1];
 $idxstr = "\x24json" . substr($idxstr,1);

 eval("\x24aa=" . $idxstr . ";");
 echo "->  {$aa} 
"; $idxstr .= "='A123456789';"; @eval($idxstr); // 失敗してもtry-catchで拾えません^^; $res3 = Var_Dump::display($json,true); echo "-> " . $idxstr . "
"; echo $res1; echo $res2; echo $res3; exit; /* samplejson.txtの中身。 { "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99 }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99 }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99 } ], "bicycle": { "color": "red", "price": 19.95 } } } */ ?>
●表示結果
-> Evelyn Waugh 
-> $json['store']['book'][1]['author']='A123456789';
array(4) {
  0 => string(10) Nigel Rees
  1 => string(12) Evelyn Waugh
  2 => string(15) Herman Melville
  3 => string(16) J. R. R. Tolkien
}
array(4) {
  0 => string(31) $['store']['book'][0]['author']
  1 => string(31) $['store']['book'][1]['author']
  2 => string(31) $['store']['book'][2]['author']
  3 => string(31) $['store']['book'][3]['author']
}
array(1) {
  store => array(2) {
    book => array(4) {
      0 => array(4) {
        category => string(9) reference
        author => string(10) Nigel Rees
        title => string(22) Sayings of the Century
        price => float 8.95
      }
      1 => array(4) {
        category => string(7) fiction
        author => string(10) A123456789
...略...

iOS6未満でOperaMiniでFileUpload、やっぱりダメ

うぅーーん。やっぱり無理でした。
スマフォ用のWebサイトを、『どこまで対応端末としてターゲットにするか』
と言う問題はいつでもついてまわるわけですが、
jQuery+jQueryMobile+jQueryUpload &&
FileUpload de iPhone3G with OperaMini
  ↓
あえなく失敗。。。。^^;^^;
ファイル選択はできてるんですけどねー。。。
アプリにするしかないのか。。。。。

2013年2月27日水曜日

PHPでJSONデータを扱うとき。

PHPでJSONを扱うときの話ですが、
まぁこんなデータを扱う時の話ですが、、、
 //-------------------------------------------
{
 "doc":{
  "pages":{
   "layers":[
    {
     "items":[
      {
       "name":"abcdefgh",
       。。。。データいろいろ。。。。
       "items":[
        {
         。。理論上無限階層下。。データいろいろ。。。。
うん。
*["items > name == {$tareget}"]
セレクタみたいなやつで一発でかけるならいいんですが、、、まぁそういうクラスを書いてもいいんだけど、、、それほどでもなかったので、なめてみるコードを書いてみました
こんな感じで。
 //-------------------------------------------
 // objectのTREEを下っていって、*['name']=$nameのとき*[$tag]=$valueをセットする件。
 //-------------------------------------------
 public static function searchAndSet(&$json,$name,$tag,$value){
  $ar = array_keys($json);
  $n = count($ar);
  for($w=0;$w<$n;$w++){
   $br = @array_keys( $json[ $ar[$w]  ] );
   if(count($br) > 0){
    $ret = xxxxxxxx::searchAndSet($json[$ar[$w]],$name,$tag,$value);
    if($ret != null) return $ret;
   }
   if($json[ $ar[$w] ]['name'] == $name){
    $json[ $ar[$w] ][$tag] = $value;
    return $value;
   }
  }
  return null;
 }
追記) あ、NAMEが一意なのが前提なコードです。

tmhUtilities::php_self()のリバプロ非対応な件

tmhUtilities::php_self();が、リバースプロキシのときに、ちゃんと動いてませんねー。
よって改修しますよ。
●改修前
$url = sprintf('%s://%s%s',
 $protocol,
 $_SERVER['SERVER_NAME'],
 $_SERVER['REQUEST_URI']
);
●改修後
$serverName = $_SERVER['HTTP_X_FORWARDED_HOST'];
if($serverName == "") $serverName = $_SERVER['SERVER_NAME'];
$url = sprintf('%s://%s%s',
 $protocol,
 $serverName,
 $_SERVER['REQUEST_URI']
);
いやしかし、リバプロ対応に関する修正って、いままで数限りなくやってるんですが、いまだになくなりません^^;^^;

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

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