元記事はこちら
http://www.webmotionuk.co.uk/php-jquery-image-upload-and-crop/
そこでCake用を作成してみました。お役に立てれば嬉しいです。では、いってみましょう!
必要なもの
- PHP 4 以上 (PHP5の環境で開発しました)
- PHP GD ライブラリ
- jQueryhttp://jquery.com/
- イメージエリアセレクトプラグイン -> http://odyniec.net/projects/imgareaselect/
導入
まず、「JqImgcrop」というコンポーネントを作成します。
「yourapp/controllers/components/」以下に「jq_imgcrop.php」というファイルを以下の内容で作成します。
Component Class:
<?php class JqImgcropComponent extends Object { function uploadImage($uploadedInfo, $uploadTo, $prefix){ $webpath = $uploadTo; $upload_dir = WWW_ROOT.str_replace("/", DS, $uploadTo); $upload_path = $upload_dir.DS; $max_file = "34457280"; $max_width = 800; $userfile_name = $uploadedInfo['name']; $userfile_tmp = $uploadedInfo["tmp_name"]; $userfile_size = $uploadedInfo["size"]; $filename = $prefix.basename($uploadedInfo["name"]); $file_ext = substr($filename, strrpos($filename, ".") + 1); $uploadTarget = $upload_path.$filename; if(empty($uploadedInfo)) { return false; } if (isset($uploadedInfo['name'])){ move_uploaded_file($userfile_tmp, $uploadTarget ); chmod ($uploadTarget , 0777); $width = $this->getWidth($uploadTarget); $height = $this->getHeight($uploadTarget); // Scale the image if it is greater than the width set above if ($width > $max_width){ $scale = $max_width/$width; $uploaded = $this->resizeImage($uploadTarget,$width,$height,$scale); }else{ $scale = 1; $uploaded = $this->resizeImage($uploadTarget,$width,$height,$scale); } } return array('imagePath' => $webpath.$filename, 'imageName' => $filename, 'imageWidth' => $this->getWidth($uploadTarget), 'imageHeight' => $this->getHeight($uploadTarget)); } function getHeight($image) { $sizes = getimagesize($image); $height = $sizes[1]; return $height; } function getWidth($image) { $sizes = getimagesize($image); $width = $sizes[0]; return $width; } function resizeImage($image,$width,$height,$scale) { $newImageWidth = ceil($width * $scale); $newImageHeight = ceil($height * $scale); $newImage = imagecreatetruecolor($newImageWidth,$newImageHeight); $ext = strtolower(substr(basename($image), strrpos(basename($image), ".") + 1)); $source = ""; if($ext == "png"){ $source = imagecreatefrompng($image); }elseif($ext == "jpg" || $ext == "jpeg"){ $source = imagecreatefromjpeg($image); }elseif($ext == "gif"){ $source = imagecreatefromgif($image); } imagecopyresampled($newImage,$source,0,0,0,0,$newImageWidth,$newImageHeight,$width,$height); if($ext == "png" || $ext == "PNG"){ imagepng($newImage,$image,0); }elseif($ext == "jpg" || $ext == "jpeg" || $ext == "JPG" || $ext == "JPEG"){ imagejpeg($newImage,$image,90); }elseif($ext == "gif" || $ext == "GIF"){ imagegif($newImage,$image); } chmod($image, 0777); return $image; } function resizeThumbnailImage($thumb_image_name, $image, $width, $height, $start_width, $start_height, $scale){ $newImageWidth = ceil($width * $scale); $newImageHeight = ceil($height * $scale); $newImage = imagecreatetruecolor($newImageWidth,$newImageHeight); $ext = strtolower(substr(basename($image), strrpos(basename($image), ".") + 1)); $source = ""; if($ext == "png"){ $source = imagecreatefrompng($image); }elseif($ext == "jpg" || $ext == "jpeg"){ $source = imagecreatefromjpeg($image); }elseif($ext == "gif"){ $source = imagecreatefromgif($image); } imagecopyresampled($newImage,$source,0,0,$start_width,$start_height,$newImageWidth,$newImageHeight,$width,$height); if($ext == "png" || $ext == "PNG"){ imagepng($newImage,$thumb_image_name,0); }elseif($ext == "jpg" || $ext == "jpeg" || $ext == "JPG" || $ext == "JPEG"){ imagejpeg($newImage,$thumb_image_name,90); }elseif($ext == "gif" || $ext == "GIF"){ imagegif($newImage,$thumb_image_name); } chmod($thumb_image_name, 0777); return $thumb_image_name; } function cropImage($thumb_width, $x1, $y1, $x2, $y2, $w, $h, $thumbLocation, $imageLocation){ $scale = $thumb_width/$w; $cropped = $this->resizeThumbnailImage(WWW_ROOT.str_replace("/", DS,$thumbLocation),WWW_ROOT.str_replace("/", DS,$imageLocation),$w,$h,$x1,$y1,$scale); return $cropped; } } ?>
Helper Class:
<?php class CropimageHelper extends Helper { var $helpers = array('Html', 'Javascript', 'Form'); function createJavaScript($imgW, $imgH, $thumbW, $thumbH) { return $this->output("<script type=\"text/javascript\"> function preview(img, selection) { var scaleX = $thumbW / selection.width; var scaleY = $thumbH / selection.height; $('#thumbnail + div > img').css({ width: Math.round(scaleX * $imgW) + 'px', height: Math.round(scaleY * $imgH) + 'px', marginLeft: '-' + Math.round(scaleX * selection.x1) + 'px', marginTop: '-' + Math.round(scaleY * selection.y1) + 'px' }); $('#x1').val(selection.x1); $('#y1').val(selection.y1); $('#x2').val(selection.x2); $('#y2').val(selection.y2); $('#w').val(selection.width); $('#h').val(selection.height); } $(document).ready(function () { $('#save_thumb').click(function() { var x1 = $('#x1').val(); var y1 = $('#y1').val(); var x2 = $('#x2').val(); var y2 = $('#y2').val(); var w = $('#w').val(); var h = $('#h').val(); if(x1==\"\" || y1==\"\" || x2==\"\" || y2==\"\"|| w==\"\" || h==\"\"){ alert('切り取り範囲を選択してください。'); return false; }else{ return true; } }); }); $(window).load(function () { $('#thumbnail').imgAreaSelect({ aspectRatio: '1:1', onSelectChange: preview }); }); </script>"); } function createForm($imagePath, $tH, $tW){ $x1 = $this->Form->hidden('x1', array("value" => "", "id"=>"x1")); $y1 = $this->Form->hidden('y1', array("value" => "", "id"=>"y1")); $x2 = $this->Form->hidden('x2', array("value" => "", "id"=>"x2",)); $y2 = $this->Form->hidden('y2', array("value" => "", "id"=>"y2")); $w = $this->Form->hidden('w', array("value" => "", "id"=>"w")); $h = $this->Form->hidden('h', array("value" => "", "id"=>"h")); $imgP = $this->Form->hidden('imagePath', array("value" => $imagePath)); $imgTum = $this->Html->image($imagePath, array('style'=>'float: left; margin-right: 10px;', 'id'=>'thumbnail', 'alt'=>'Create Thumbnail')); $imgTumPrev = $this->Html->image($imagePath, array('style'=>'position: relative;', 'id'=>'thumbnail', 'alt'=>'Thumbnail Preview')); return $this->output("$imgTum <div style=\"position:relative; overflow:hidden; width:".$tW."px; height:".$tH."px;\"> $imgTumPrev </div> <br style=\"clear:both;\"/>$x1 $y1 $x2 $y2 $w $h $imgP"); } } ?>
これで完成です。使い方を説明しましょう。
使い方
コンポーネントとヘルパーを使用するコントローラに追加します。
var $helpers = array(..., 'Cropimage') var $components = array(..., 'JqImgcrop');
ではフォームを作成しましょう。以下に例を示します。
<?php echo $form->create('YourModel', array('action' => 'createimage_step2', "enctype" => "multipart/form-data"));?> <?php echo $form->input('name'); echo $form->input('image',array("type" => "file")); echo $form->end('アップロード'); ?>
createimage_step2のアクション内に、コンポーネントのアップロード関数を追加します。
$uploaded = $this->JqImgcrop->uploadImage($this->data['YourModel']['image'], '/img/upload/', 'prefix_');
ビューにセットします。
$this->set('uploaded',$uploaded);
コントローラは以下のようになります。
function createimage_step2(){ if (!empty($this->data)) { $uploaded = $this->JqImgcrop->uploadImage($this->data['YourModel']['image'], '/img/upload/', 'prefix_'); $this->set('uploaded',$uploaded); }
2つのJavasctiptライブラリをビュー(上記の例では「createimage_step2.ctp」)に追加します。
<?php if(isset($javascript)): echo $javascript->link('jquery-1.2.6.min.js'); echo $javascript->link('jquery.imgareaselect-0.4.2.min.js'); endif; ?>
cropimageヘルパーを使用してフォームを作成し、Javascriptを追記します
echo $cropimage->createJavaScript($uploaded['imageWidth'],$uploaded['imageHeight'],151,151); echo $cropimage->createForm($uploaded["imagePath"], $width, $height);
幅と高さの2つのパラメータで作成されるサムネイルのサイズを指定します。
IDを「save_thumb」として、「form->submit」を作成します。
echo $form->submit('Done', array("id"=>"save_thumb"));
全体は以下のようになります。
<?php echo $form->create('YourModel', array('action' => 'createimage_step3',"enctype" => "multipart/form-data")); echo $form->input('id'); echo $form->hidden('name'); echo $cropimage->createForm($uploaded["imagePath"], 151, 151); echo $form->submit('Done', array("id"=>"save_thumb")); echo $form->end(); ?>
最後に
画像の切り取りと保存のために、「createimage_step3」というアクションをコントローラに追記します。
<?php $this->JqImgcrop->cropImage(151, $this->data['YourModel']['x1'], $this->data['YourModel']['y1'], $this->data['YourModel']['x2'], $this->data['YourModel']['y2'], $this->data['YourModel']['w'], $this->data['YourModel']['h'], $this->data['YourModel']['imagePath'], $this->data['YourModel']['imagePath']) ?>
以下のパラメータを使用します。
$thumb_width, $x1, $y1, $x2, $y2, $w, $h, $thumbLocation, $imageLocation
$thumb_width は、サムネイルの幅を指定します。
$x1, $y1, $x2, $y2, $w, $h は切り取りパラメータを指定します。
$thumbLocation は、サムネイルの保存先を指定します。
$imageLocation tは、元画像の参照先を指定します。
この関数は生成されたサムネイルのファイル名を返します。
以上です。
http://www.webmotionuk.co.uk の素晴らしい記事に感謝します!
(翻訳終わり)
訳者より
ビュー中のコーディング例ですが、上記はCakePHP 1.2系の記法です。CakePHP 1.3系では以下のようになります。
<?php echo $this->Form->create('YourModel', array('action' => 'createimage_step2', "enctype" => "multipart/form-data"));?> <?php echo $this->Form->input('name'); echo $this->Form->input('image',array("type" => "file")); echo $this->Form->end('アップロード'); ?>
<?php if(isset($this->Javascript)): echo $this->Javascript->link('jquery-1.2.6.min.js'); echo $this->Javascript->link('jquery.imgareaselect-0.4.2.min.js'); endif; ?>
echo $this->Cropimage->createJavaScript($uploaded['imageWidth'],$uploaded['imageHeight'],151,151); echo $this->Cropimage->createForm($uploaded["imagePath"], $width, $height);
echo $this->Form->submit('Done', array("id"=>"save_thumb"));
echo $this->>Form->create('YourModel', array('action' => 'createimage_step3',"enctype" => "multipart/form-data")); echo $this->>Form->input('id'); echo $this->>Form->hidden('name'); echo $this->>Cropimage->createForm($uploaded["imagePath"], 151, 151); echo $this->>Form->submit('Done', array("id"=>"save_thumb")); echo $this->>Form->end();