モノノフ日記

普通の日記です

ITMediaの記事がブログに貼りやすくなったらしいので

早速試してみました。

画像にするのはメリットデメリット両方ありそうなんで、ケースバイケースで使い分けようかなと思います。
あと個人的な不満点は、

文章での引用禁止とかは明言していないですよね・・?

PECL::Imagickを試す

GDで展開できない画像*1があったのでImageMagickを試そうと思って導入してみました。

インストール

peclモジュールなのでコマンドライン1発で楽チン。

sudo pecl install imagick

php.iniにライブラリを呼び出す記述を追加

extension=imagick.so

実際に使ってみる

マニュアルはいろいろ探しましたが、PHPマニュアルが一番詳しいと思います。
PHP: Imagick 画像ライブラリ - Manual
しかしPHPマニュアルもAPI一覧のみで詳しい解説は書かれていないので実際に使って試してみました。

サンプル画像はこれです。

リサイズしてみた

APIリストを眺めてみるとリサイズに使いそうなメソッドである下記5つを試してみました。

  • Imagick::adaptiveResizeImage
  • Imagick::cropImage
  • Imagick::thumbnailImage
  • Imagick::resizeImage
  • Imagick::cropThumbnailImage
Imagick::adaptiveResizeImage
メソッドの説明

データに依存する三角測量にもとづいて画像のサイズを変更する, と記述されてますが何のことやら。。引数のcolumns, rowsはマニュアルページのサンプルコードから類推すると、それぞれ縦幅, 横幅の様です。

bool Imagick::adaptiveResizeImage ( int $columns , int $rows )

http://jp2.php.net/manual/ja/function.imagick-adaptiveresizeimage.php
サンプルコード

300x300の正方形にリサイズしています。

<?php
  $image = new Imagick('/path/to/sample.jpg');
  $image->adaptiveResizeImage(300,300);
  header('Content-type: image/jpeg');
  echo $image;
結果
Fatal error: Call to undefined method Imagick::adaptiveResizeImage()

メソッドが無いみたいです。とりあえず次へw

Imagick::cropImage
メソッドの説明

切り取りたい縦・横幅と元画像の切り取り開始位置を引数にとってます。よくあるcropメソッドですね。

bool Imagick::cropImage ( int $width , int $height , int $x , int $y )

http://jp2.php.net/manual/ja/function.imagick-cropimage.php
サンプルコード

300x300の大きさで、元画像の左隅(0,0)からcropさせてみました。

<?php
  $image = new Imagick('/path/to/sample.jpg');
  $image->cropImage(300,300, 0, 0);
  header('Content-type: image/jpeg');
  echo $image;
結果

f:id:Kiske:20080217121007j:image

元画像の左隅の壁の部分がcropできてます。

Imagick::thumbnailImage
メソッドの説明

fitをtrueにすると、columnsかrowsの小さい方の値に合わせてサムネイルが生成される模様です。

bool Imagick::thumbnailImage ( int $columns , int $rows [, bool $fit ] )

画像のサイズを指定したものに変更し、関連付けられたプロパティをすべて削除します。 ウェブ上での表示に適した小さなサムネイル画像を作成します。 3 番目のパラメータに true を指定すると、columns や rows にそれぞれの最大値を使用します。両方のパラメータが、 マッチするまであるいは指定したパラメータより小さくなるまで縮小されます。

http://jp2.php.net/manual/ja/function.imagick-thumbnailimage.php
サンプルコード

300x300の大きさで、filをtrueにしてサムネイル生成

<?php
  $image = new Imagick('/path/to/sample.jpg');
  $image->thumbnailImage(300, 300, true);
  header('Content-type: image/jpeg');
  echo $image;
結果

f:id:Kiske:20080408141932j:image
元画像の比率を維持したまま、サムネイル生成しています。大きさは画像の最大長側(この場合は横幅)を基準としているため300x225にリサイズされています。

Imagick::resizeImage
メソッドの説明

Imagick::thumbnailImage()との違いはfilter, blurを指定できる所の様です。

bool Imagick::resizeImage ( float $columns , float $rows , int $filter , float $blur )

指定した大きさとフィルタで、画像のサイズを変更します。

http://jp2.php.net/manual/ja/function.imagick-resizeimage.php
サンプルコード

マニュアルのサンプルコードをまねて、LANCZOSフィルタ*2を使ってみます。その他の各種フィルタ定数はマニュアルを参考してください

<?php
  $image = new Imagick('/path/to/sample.jpg');
  $image->resizeImage(300, 300, imagick::FILTER_LANCZOS, 0);
  header('Content-type: image/jpeg');
  echo $image;
結果

f:id:Kiske:20080217121007j:image

無理やり300x300に縮小しているので比率がおかしくなっています。

Imagick::cropThumbnailImage
メソッドの説明

縮小してからサムネイルを生成するメソッド。centerから指定した大きさで切り取ってくれてる様です。

bool Imagick::cropThumbnailImage ( int $width , int $height )

固定サイズのサムネイルを作成します。まず画像のサイズを縮小し、指定した範囲を中心から切り取ります。

http://jp2.php.net/manual/ja/function.imagick-cropthumbnailimage.php
サンプルコード

300x300のサムネイルを生成しています。

<?php
  $image = new Imagick('/path/to/sample.jpg');
  $image->cropThumbnailImage(300, 300);
  header('Content-type: image/jpeg');
  echo $image;
結果

f:id:Kiske:20080408143555j:image
元画像と比較すると、左右が切り取りとられていますが比率は維持されています。

まとめ

ざっくりと用途を考えると下みたいな感じでしょうか。

メソッド名 用途
Imagick::adaptiveResizeImage メソッドが存在しないようなので使えない
Imagick::cropImage 元画像から切り取る範囲が決まっている
Imagick::thumbnailImage 比率維持したまま、サムネイル作りたい
Imagick::resizeImage フィルタ使って、サムネイル作りたい
Imagick::cropThumbnailImage 比率維持したまま、中心から任意の範囲を切り取りたい

*1:VQ1005というトイカメラで撮影された画像

*2:aviutlのプラグインで見たことある名前

Vimperator 0.5.3を導入してみた

はてブホッテントリにVimperatorの紹介記事が上がってたのを見て今更ながら導入してみました。

ナレッジエース - Firefoxをキーボード操作できるプラグイン「Vimperator」の使い方に書かれてるリンクを参考に操作を覚えました。

以下、所感を箇条書きで挙げておきます。

  • 普段からvim使ってるので移動操作については特に違和感無し
  • f、;使ったリンク移動も案外すんなりと使える
  • dでタブ削除できるのイイ
  • uで削除したタブをUndoできるのもイイ
    • タブはvimでいうbufferと考えればよいみたい
  • ページ内の文章をコピーするやり方がわからない
  • ブックマークしてるURLをVimperatorから呼ぶ方法がわからない
  • プラグインいれると異様に便利になった
  • CodeReposに挙がってるプラグインは0.6pre用が多いので動かないモノもあった
    • リビジョン古いやつを辿って0.5.3用入れればOK
  • 操作に慣れてきてguioptionsを使わないようになるとブラウザが広く使えて良さそう
  • PC環境が若干非力なせいかちょっと重い時もある

f使ったクイックヒントは使いこなすとブラウジングが非常に高速化しそう。
ブックマークの件はmap使って、コマンドに登録すれば解決するのかな。

2008/04/09追記

id:otsuneさん、id:retletさんからコメント頂いてるように:t, :oでするとブックマーク候補を補完してくれます。実際に試してみました。

実行コマンド

HNの「Kiske」で補完してみます。ちなみに:tと押さなくても、tだけ押しても「:tabopen」とコマンドラインに補完してくれます。oも同じように「:open」に補完。

:t Kiske<tab>
結果

f:id:Kiske:20080409162337p:image
一杯でた。55件もヒット。
ザッと一覧した感じだと、ブックマークしてるURL、キーワード、あとブラウザの履歴からも補完してるみたいです。
これは便利すぐる!ますますマウス触る機会が減って幸せになれました。お二人方あざーっす!

タグクラウドのアルゴリズム

タグクラウドを生成する際のアルゴリズムをオープンソースのコードを参考にして現在考えてます。

symfony公式サイトで見つけたアルゴリズム

<?php
  while ($rs->next())
  {
    if (!$max_popularity)
    {
      $max_popularity = $rs->getInt('count');
    }
 
    $tags[$rs->getString('tag')] = floor(($rs->getInt('count') / $max_popularity * 3) + 1);
  }

すごいシンプルでびっくり。

処理の流れ

  1. タグの最大カウント数をmax_popularityとする
  2. 各タグのカウント数をmax_popularityで割り、タグクラウドの範囲から1引いた値をかける(ここでは3)
  3. 算出された値を切り上げて、0が無くなるように+1

この算出アルゴリズムだと最大の大きさを持つタグは1つだけで、それに小さいタグが群がる感じになります。
ただカウント数の差が大きいと最大の大きさのタグに最小のタグがわらわらと群がるので見た目のバランスが悪くなりました。

もっと平均的に振り分ける方法ないのかなと探してたら、タグクラウドのアルゴリズム (それなりブログ)を発見。

【最も基本的なアルゴリズム】

* 最終的に、各タグの大きさは25段階の範囲で区分される。ソース内ではこれを level と読んでおり、0-24の範囲で指定している。
* level算出方法は以下の通り
1. 最もタグ付けされている回数が多いタグの回数を取得し、それの平方根を求める。以後この値を max と呼ぶ。
2. 最もタグ付けされている回数が少ないタグの回数を取得し、それの平方根を求める。以後この値を min と呼ぶ。
3. max - min の間を均等に 25段階に分け、各タグのタグ付け回数の平方根の値が、その範囲のどこに位置するのかを求め、それが level となる。

http://kjirou.sakura.ne.jp/mt/2007/09/post_57.html

そうか、平方根使えばよかったのかと納得。

追記

PEARのHTML_Tagcloudのソースも見てみた。htmlタグを生成してるところだけ抜粋。

<?php
    private function _buidHTMLTags($param)
    {
        $this->total = count($this->_elements);
        // no tags elements
        if($this->total == 0){
            return array();
        }elseif($this->total == 1){
            $tag = $this->_elements[0];
            return $this->_createHTMLTag($tag, 'latest', $this->baseFontSize);
        }

        $limit = array_key_exists('limit', $param) ? $param['limit'] : 0;
        $this->_sortTags($limit);
        $this->_calcMumCount();
        $this->_calcMumEpoc();

        $range = $this->maxFontSize - $this->minFontSize;
        if($this->_max != $this->_min){
            $this->_factor = $range / (sqrt($this->_max) - sqrt($this->_min));
        }else{
            $this->_factor = 1;
        }

        if($this->_maxEpoc != $this->_minEpoc){
            $this->_epocFactor = count($this->epocLevel)
                                    / (sqrt($this->_maxEpoc) - sqrt($this->_minEpoc));
        }else{
        $rtn = array();
        foreach ($this->_elements as $tag) {
            $countLv = $this->_getCountLevel($tag['count']);
            if (! isset($tag['timestamp']) || empty($tag['timestamp'])) {
                $epocLv = count($this->epocLevel) - 1;
            } else {
                $epocLv  = $this->_getEpocLevel($tag['timestamp']);
            }
            $colorType = $this->epocLevel[$epocLv];
            $fontSize  = $this->minFontSize + $countLv;
            $rtn[] = $this->_createHTMLTag($tag, key($colorType), $fontSize);
        }
        return implode("", $rtn);
    }

やっぱ最大値/最小値の平方根の差を使って係数出してますね。
ただ最大値/最小値の値がタグのカウント数以外に、タイムスタンプも使ってるのが興味深い。タグの新鮮度でもレベル付けできるよってことですね。

しかし、_buidHTMLTagsってのはtypoだよね。すごい気になったw

WordPressでXSSの可能性?

社内のツールでWordPress2.5に対してセキュリティ診断かけたら、
1件Criticalが見つかるという始末。。

ちなみにWordPressはインストールしてすぐのデフォルトスキンの状態です。
コメントとトラックバックは無効にしました。

どこがXSSの原因になるのかと言うと、サイト内検索の結果画面でサイドバーに検索クエリーを表示をエスケープしてません。貼り付けた画像の赤い四角で囲ったところです。
f:id:Kiske:20080402143508j:image

修正箇所はwp-content/themes/default/sidebar.phpの33行目あたりになります。
get_search_query()をエスケープしてやればOKです。

<?php /* If this is a monthly archive */ } elseif (is_search()) { ?>
- <p><?php printf(__('You have searched the <a href="%1$s/">%2$s</a> blog archives for <strong>&#8216;%3$s&#8217;</strong>. If you are unable to find anything in these search results, you can try one of these links.', 'kubrick'), get_bloginfo('url'), get_bloginfo('name'), get_search_query() ); ?></p>
+ <p><?php printf(__('You have searched the <a href="%1$s/">%2$s</a> blog archives for <strong>&#8216;%3$s&#8217;</strong>. If you are unable to find anything in these search results, you can try one of these links.', 'kubrick'), get_bloginfo('url'), get_bloginfo('name'), htmlspecialchars(get_search_query(), ENT_QUOTES) ); ?></p>

しかしコメント不可にしてるし、XSSは出ないだろーと思ったら
思いっきり見つかったので有名なソフトでも安心はできないですね。。

たん清オフに参加してきました

id:i_ogiの人格に魅せられた人々が集まる焼肉パーティーに参加してきました。

たん清の肉はうまいっ!今度会社の人連れてこようとまた来よう。
そして、自分の部の飲み会=たん清という公式を作りたい!

twitterで募集かけただけにも関わらず最終的には16人(くらい?)の大所帯でした。
フレームワークの話やクロージャの話などいろいろ参考になるお話が聞けたので良かったです。

しかしクロージャは他人に説明できるほど自分も完全に理解できていない・・・。
今度の社内勉強会のネタにして調べてみようと思った。

id:i_ogi
幹事お疲れ様でした!

>参加されたみなさん
あまりお話できなかった人もいますが、お疲れ様でした!

第4回KLAB勉強会に参加してきました

先週の金曜日になりますが、第4回KLAB勉強会に参加してきました。
DSAS開発者の部屋:KLab勉強会#4の資料を公開しますで資料が公開されています。

勉強会に参加して思ったことは、やっぱり1元管理超重要。
aliasやシェル関数を駆使してオペレーションミスの発生をできるだけ減らす工夫は
実際に運用してるシステムを見れて非常に参考になりました。
思いつきはするけど、なかなかシステムとして組める所まで持っていけないんですよね。。

あとKLABが既存ツールに頼らずシェルやperlで管理してるのは
いろいろ試行錯誤して試した結果なんだろうなー、と勝手に思ったり。

ペパボの宮下さんのFuncは「なんかすげー」って感じのシステム管理でした。
あんなにプログラマブルな管理だったら管理作業も凄い楽しいんだろうな。
Funcはまだまだ発展途上系みたいですがウオッチしていきたいと思います!

懇親会も自分が座ってたテーブルの方とは名刺交換+お話できてよかったです。
もっと他テーブルに突っ込むスキルを磨いていかないといきませんね。。