September 2007

Entries Title

Preview 用に画像を crop & scale する

Date
2007-09-05 (Wed)
Category
Processing

画像を受け取って、それからPreview 用の Thumbnail を生成する、というのは Web app でよくあるシチュエーションだと思います。自分用の備忘録として、今日思いついた方法をメモしておきます。

変換元 / 変換先がどんな画像であれ、crop & scale に必要な情報は

  • 元画像 (source)
    • X 座標
    • Y 座標
    • 高さ
  • 先画像 (destination)
    • X 座標
    • Y 座標
    • 高さ

この8つです。今回はこの8つのうち、4つの情報、変換元 / 変換先それぞれの幅と高さがわかっている状態から、出来るだけ、aspect 比を変えないようにするアルゴリズムを考えてみました。PHP で手続き風に書きますが、言語(当然ですが)は問いません。

function calcResizedBounds ($w0, $h0, $w1, $h1)
{
  switch (true)
  {
    case ($w0 > $h0):
      $r = processLandscape($w0, $h0, $w1, $h1);
    break;
case ($w0 < $h0): $r = processPortrait($w0, $h0, $w1, $h1); break;
case ($w0 == $h0): $r = processSquare($w0, $w1, $h1); break; } return $r; }
function processLandscape ($w0, $h0, $w1, $h1) { $src_y = 0; $src_h = $h0; $ratio = $h0 / $h1; $src_w = floor($w1 * $ratio); $src_x = floor(($w0 - $src_w) / 2); return array($src_x, $src_y, $src_w, $src_h); }
function processPortrait ($w0, $h0, $w1, $h1) { $src_x = 0; $src_w = $w0; $ratio = $w0 / $w1; $src_h = floor($h1 * $ratio); $src_y = floor(($h0 - $src_w) / 2); return array($src_x, $src_y, $src_w, $src_h); }
function processSquare ($side, $w1, $h1) { switch (true) { case ($w1 > $h1): $src_x = 0; $src_w = $side; $ratio = $side / $w1; $src_h = floor($h1 * $ratio); $src_y = floor(($side - $src_w) / 2); break;
case ($w1 < $h1): $src_y = 0; $src_h = $side; $ratio = $side / $h1; $src_w = floor($w1 * $ratio); $src_x = floor(($side - $src_w) / 2); break;
case ($w1 == $h1): $src_x = 0; $src_y = 0; $src_w = $side; $src_h = $side; break; } return array($src_x, $src_y, $src_w, $src_h); }

こんな風に使います。

$dst_x = 0;
$dst_y = 0;
$dst_w = $w1;
$dst_h = $h1;
$src_x = null;
$src_y = null;
$src_w = null;
$src_h = null;
list($src_x, $src_y, $src_w, $src_h) = calcResizedBounds($w0, $h0, $w1, $h1);

Symfony で Json を出力

Date
2007-09-05 (Wed)
Category
symfony

Symfony にも、Prototype と連携する plugin や、Askeet のサンプルでも出てくる Symfony 同梱の helper などがあります。でも最終的には結局しっくりこないで、自分でみっちりチューニングした javascript を書いてしまうことが僕は多いです。。そんな時に、僕だけかもしれないけれど、Symfony で JSON 形式の書き出しをする事があります。Symfony 側、例えば app.yml に設定を集中して書いて interface を司る javascript でも同じ設定を使い回すため、とか。

で、今日すこしハマったので、tip として挙げておきます。どういう理由なのか、自分ではさっぱりわからなかったのだけれど…

例えば、以下のような Symfony の View があります。(抜粋)

var Setting = {};
<?php foreach ($arr as $key => $val): ?>
Setting.<?php echo $key; ?> = '<?php echo $val; ?>';
<?php endforeach; ?>

これを <script src="〜〜"></script> として読み込ませてみるんだけど、javascript runtime が解釈してくれない。。ソースを browser で見て、普通にテキストとしてコピペすると、使えるのに…全体が読み込まれないならまだわかるんだけど、一部だけってのも不可解すぎた。

諦めかけた時に、ふと、ページの content-type を text/javascript から、application/x-javascript に変えてみたら、全てのオブジェクトが認識されるようになりました。/apps/modules/MODULE/config/view.yml に以下のように書きました。

default:
 has_layout:     off
 http_metas:
   content-type: application/x-javascript

white space の扱い、とかそういうのだと思うけれど。こういう事もありますよ、という事で。

Return to Page Top