元記事はこちら
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();