DEVELOPERS BLOGデベロッパーズブログ

  1. HOME > 
  2. 加藤 正人のデベロッパーズブログ > 
  3. UploadPack で四苦八苦・再び

加藤 正人のデベロッパーズブログ

加藤 正人

氏名
加藤 正人
役職
多分SE
血液型
秘密
出没
美味しいもののあるところ
特色
タヒチ大好き。ちょいメタボ。

PhpSpreadsheet でExcel ファイルを読み込む (CakePHP3)

2013/07/27

PhpSpreadsheet でExcel ファイルを読み込む (CakePHP3)

 

UploadPack で「band」リサイズ (縦横比を保って出力サイズにフィットするようにリサイズし、余白ができた場合は白色余白を付加) する場合に妙な挙動をすることがあった。

例えば、400px × 300px (幅×高さ) の4:3画像を、480px × 270px (幅×高さ) の16:9領域に余白を付けてフィットさせたいとしよう。

この場合、期待する結果としては

  1. 元画像を高さに合わせて縮小 (400 x 300 ⇒ 360 x 270)
  2. センタリングして左右に60px×270pxの余白を補って 480px×270px に収める

となるが、UploadPack で処理すると横長画像は全て横幅に合わせてしまう。このため、処理結果がオリジナルよりさらに横長の場合、天地が切り詰めれられるので 'best' モードと同じ処理になってしまう。

問題の箇所は {$APP}/Plugin/UploadPack/Model/Behavior/UploadBehavior.php (旧 Cake 1.x 対応版の場合は {$APP}/plugins/upload_pack/models/behaviors/upload.php) の UploadBehavior::_resize() プライベートメソッドにある。「band」時のリサイズ処理後の幅と高さを

	if ($srcW > $srcH) $ratio = $destW/$srcW;
	else $ratio = $destH/$srcH;
	$resizeW = $srcW*$ratio;
	$resizeH = $srcH*$ratio;

で計算しているが、この方法だと常に縦長画像の場合は高さ、横長画像の場合は幅を合わせてしまう。そのため、元画像が縦長の場合、出力サイズが元画像より縦長だと両脇をカットされてしまう。同様に元画像が横長の場合は天地がカットされてしまう。

従って、元画像の縦横比で判定するのではなく元画像と出力領域のどちらがより縦長または横長であるかを判定して揃える辺を決定する必要がある。例えば、

	$srcRatio = $srcW / $srcH; // >1: 横長 =1: 正方形 <1: 縦長
	$destRatio = $destW / $destH;
	if ( $srcRatio > $destRatio )
	{
		// ソースの方が表示領域より横長 ⇒ 幅合わせ
		$resizeW = $destW;
		$resizeH = $resizeW / $srcRatio;
	}
	else
	{
		// ソースの方が表示領域より縦長 ⇒ 高さ合わせ
		$resizeH = $destH;
		$resizeW = $resizeH * $srcRatio;
	}

のようなコードにすることで正しく余白付け (banding) することができる。

関連タグ: CakePHP  UploadPack