Posted by: sabbour on: May 13, 2008
Update:
Newer version
I needed to upload images to my CakePHP based website and at the same time, I needed to resize and create thumbnails of those images.
I found some different components on the Bakery and I found some code here, but I needed something more, I needed to have the ability to generate square zoomed thumbnails out of the uploaded images.
Since I was new to CakePHP and I wanted to improve my skills, I ended up taking code from several sources, writing some of my own, and integrating them in a component.
Big version resized using scale: 573

Small version resized using scale 110

Small version resized using scale 110 / square

You can download the code from here or here and you can take a look at it below.
<?php
/*
File: /app/controllers/components/image.php
*/
class ImageComponent extends Object
{
/*
* Uploads an image and its thumbnail into $folderName/big and $folderName/small respectivley.
* the generated thumnail could either have the same aspect ratio as the uploaded image, or could
* be a zoomed and cropped version.
* Directions:
* In view where you upload the image, make sure your form creation is similar to the following
* <?= $form->create('FurnitureSet',array('type' => 'file')); ?>
*
* In view where you upload the image, make sure that you have a file input similar to the following
* <?= $form->file('Image/name1'); ?>
*
* In the controller, add the component to your components array
* var $components = array("Image");
*
* In your controller action (the parameters are expained below)
* $image_path = $this->Image->upload_image_and_thumbnail($this->data,"name1",573,80,"sets",true);
* this returns the file name of the result image. You can store this file name in the database
*
* Note that your image will be stored in 2 locations:
* Image: /webroot/img/$folderName/big/$image_path
* Thumbnail: /webroot/img/$folderName/small/$image_path
*
* Finally in the view where you want to see the images
* <?= $html->image('sets/big/'.$furnitureSet['FurnitureSet']['image_path']);
* where "sets" is the folder name we saved our pictures in, and $furnitureSet['FurnitureSet']['image_path'] is the file name we stored in the database
* Parameters:
* $data: CakePHP data array from the form
* $datakey: key in the $data array. If you used <?= $form->file('Image/name1'); ?> in your view, then $datakey = name1
* $imgscale: the maximum width or height that you want your picture to be resized to
* $thumbscale: the maximum width or height that you want your thumbnail to be resized to
* $folderName: the name of the parent folder of the images. The images will be stored to /webroot/img/$folderName/big/ and /webroot/img/$folderName/small/
* $square: a boolean flag indicating whether you want square and zoom cropped thumbnails, or thumbnails with the same aspect ratio of the source image
*/
function upload_image_and_thumbnail($data, $datakey, $imgscale, $thumbscale, $folderName, $square) {
if (strlen($data['Image'][$datakey]['name'])>4){
$error = 0;
$tempuploaddir = "img/temp"; // the /temp/ directory, should delete the image after we upload
$biguploaddir = "img/".$folderName."/big"; // the /big/ directory
$smalluploaddir = "img/".$folderName."/small"; // the /small/ directory for thumbnails
// Make sure the required directories exist, and create them if necessary
if(!is_dir($tempuploaddir)) mkdir($tempuploaddir,true);
if(!is_dir($biguploaddir)) mkdir($biguploaddir,true);
if(!is_dir($smalluploaddir)) mkdir($smalluploaddir,true);
$filetype = $this->getFileExtension($data['Image'][$datakey]['name']);
$filetype = strtolower($filetype);
if (($filetype != "jpeg") && ($filetype != "jpg") && ($filetype != "gif") && ($filetype != "png"))
{
// verify the extension
return;
}
else
{
// Get the image size
$imgsize = GetImageSize($data['Image'][$datakey]['tmp_name']);
}
// Generate a unique name for the image (from the timestamp)
$id_unic = str_replace(".", "", strtotime ("now"));
$filename = $id_unic;
settype($filename,"string");
$filename.= ".";
$filename.=$filetype;
$tempfile = $tempuploaddir . "/$filename";
$resizedfile = $biguploaddir . "/$filename";
$croppedfile = $smalluploaddir . "/$filename";
if (is_uploaded_file($data['Image'][$datakey]['tmp_name']))
{
// Copy the image into the temporary directory
if (!copy($data['Image'][$datakey]['tmp_name'],"$tempfile"))
{
print "Error Uploading File!.";
exit();
}
else {
/*
* Generate the big version of the image with max of $imgscale in either directions
*/
$this->resize_img($tempfile, $imgscale, $resizedfile);
if($square) {
/*
* Generate the small square version of the image with scale of $thumbscale
*/
$this->crop_img($tempfile, $thumbscale, $croppedfile);
}
else {
/*
* Generate the big version of the image with max of $imgscale in either directions
*/
$this->resize_img($tempfile, $thumbscale, $croppedfile);
}
// Delete the temporary image
unlink($tempfile);
}
}
// Image uploaded, return the file name
return $filename;
}
}
/*
* Deletes the image and its associated thumbnail
* Example in controller action: $this->Image->delete_image("1210632285.jpg","sets");
*
* Parameters:
* $filename: The file name of the image
* $folderName: the name of the parent folder of the images. The images will be stored to /webroot/img/$folderName/big/ and /webroot/img/$folderName/small/
*/
function delete_image($filename,$folderName) {
unlink("img/".$folderName."/big/".$filename);
unlink("img/".$folderName."/small/".$filename);
}
function crop_img($imgname, $scale, $filename) {
$filetype = $this->getFileExtension($imgname);
$filetype = strtolower($filetype);
switch($filetype){
case "jpeg":
case "jpg":
$img_src = ImageCreateFromjpeg ($imgname);
break;
case "gif":
$img_src = imagecreatefromgif ($imgname);
break;
case "png":
$img_src = imagecreatefrompng ($imgname);
break;
}
$width = imagesx($img_src);
$height = imagesy($img_src);
$ratiox = $width / $height * $scale;
$ratioy = $height / $width * $scale;
//-- Calculate resampling
$newheight = ($width <= $height) ? $ratioy : $scale;
$newwidth = ($width <= $height) ? $scale : $ratiox;
//-- Calculate cropping (division by zero)
$cropx = ($newwidth - $scale != 0) ? ($newwidth - $scale) / 2 : 0;
$cropy = ($newheight - $scale != 0) ? ($newheight - $scale) / 2 : 0;
//-- Setup Resample & Crop buffers
$resampled = imagecreatetruecolor($newwidth, $newheight);
$cropped = imagecreatetruecolor($scale, $scale);
//-- Resample
imagecopyresampled($resampled, $img_src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
//-- Crop
imagecopy($cropped, $resampled, 0, 0, $cropx, $cropy, $newwidth, $newheight);
// Save the cropped image
switch($filetype)
{
case "jpeg":
case "jpg":
imagejpeg($cropped,$filename,80);
break;
case "gif":
imagegif($cropped,$filename,80);
break;
case "png":
imagepng($cropped,$filename,80);
break;
}
}
function resize_img($imgname, $size, $filename) {
$filetype = $this->getFileExtension($imgname);
$filetype = strtolower($filetype);
switch($filetype) {
case "jpeg":
case "jpg":
$img_src = ImageCreateFromjpeg ($imgname);
break;
case "gif":
$img_src = imagecreatefromgif ($imgname);
break;
case "png":
$img_src = imagecreatefrompng ($imgname);
break;
}
$true_width = imagesx($img_src);
$true_height = imagesy($img_src);
if ($true_width>=$true_height)
{
$width=$size;
$height = ($width/$true_width)*$true_height;
}
else
{
$width=$size;
$height = ($width/$true_width)*$true_height;
}
$img_des = ImageCreateTrueColor($width,$height);
imagecopyresampled ($img_des, $img_src, 0, 0, 0, 0, $width, $height, $true_width, $true_height);
// Save the resized image
switch($filetype)
{
case "jpeg":
case "jpg":
imagejpeg($img_des,$filename,80);
break;
case "gif":
imagegif($img_des,$filename,80);
break;
case "png":
imagepng($img_des,$filename,80);
break;
}
}
function getFileExtension($str) {
$i = strrpos($str,".");
if (!$i) { return ""; }
$l = strlen($str) - $i;
$ext = substr($str,$i+1,$l);
return $ext;
}
} ?>
[...] Image Upload and Resize Component for CakePHP 1.2 [...]
The script looks great, except that it must have been run through some web filter that didn’t recognize it as code, because you’ve got a bunch of smiley image HTML in line 57
Quick question and comment. I had to modify the code slightly to be able to upload *.png files. It was failing and I had to change the (quality) setting from 80 to 9 on a couple of the functions. It works fine, the problem is that now the shadows from windows in OSX screenshots are filled with a black background. I need it to preserve the transparency and show the shadows for aesthetics sake. Also, I wonder how much trouble it would be to do large, medium and thumb? I will try and implement this solution using your example. Thanks a lot for your contributions it really has helped me as a cakePHP newbie.
Thank you – this is great. I think this part is redundant though:
if ($true_width>=$true_height)
{
$width=$size;
$height = ($width/$true_width)*$true_height;
}
else
{
$width=$size;
$height = ($width/$true_width)*$true_height;
}
It’s fantastic, it’s simple and it simply works! I hope that a sentiment analisys web crawler read this comment and that your component can be the first on the results! Good job!
[...] Image Upload Component for CakePHP 1.2 I revisited the code I used to develop the old image resize component because I found a bug in the resize code. I used the resize function from the PImageComponent by [...]
i am trying to put together the perfect combination image gallery script for my site. this looks to be what i need for image upload/resize/thumbnail but i’m not sure how to use it… is there any way you could give me directions? i don’t write php myself… i can read it, a little, but i’m pretty lost when it comes to more than just integrating it into my html.
Great Job! ![]()
I’ve made some little changes to the path set for the images uploaded, because of PHP error “no such file do directory”. The changes looks like:
$tempuploaddir = realpath(“../../app/webroot/img/temp”).’/';
$biguploaddir = realpath(“../../app/webroot/img/”).’/’.$folderName.”/big”;
$smalluploaddir = realpath(“../../app/webroot/img/”).’/’.$folderName.”/small”;
Regards!
OK, so I guess I’m quite new at using cakePHP. This all makes sense until I get to undeclared functions like “ImageCreateFromjpeg”.
Where do I find these functions if they are not already implemented in my cakePHP libs?
Excellent component!!
I think it will be more useful if you can show how to use that in to controller. People get confuse regarding arguments of upload function.
Great component! Thanks a lot!
Thanks you!
pippo pippo pippo
Um…any idea why this makes a form really slow when an image is not selected to upload?
While using cake 1.2.3.8166 I found that using the name “Image” for this component caused some serious problems, and could not get this to work.
I change the component name to “Upload” and this worked great!
Thank you for a great component!
very nice component. It creates thumbnails keeping the aspect ratio which I think is a very cool feature.
thanks for this great help…
Hey, thank you very much for this useful component.
It creates thumbnail very nicely & in aspect of image ratio.
Cool component………..
thnaks again for the gr8 component………….
[...] way i got article from sobbour website, but i am not satisfied with the code because the component automatically resize for big [...]
Thanks for saving our time. Very good component.
Hi, thanks for sharing that code.
I also had the PHP error “no such file do directory” problem, because the mkdir cannot create 2 dir at once ; it has to create the parent $folderName dir, then the big and small dir.
Hope it will help !
Here’s my code :
$tempuploaddir = ‘img/temp’; // the /temp/ directory, should delete the image after we upload
$dad=’img/’.$folderName.”;
$biguploaddir = ‘img/’.$folderName.’/big’; // the /big/ directory
$smalluploaddir = ‘img/’.$folderName.’/small’; // the /small/ directory for thumbnails
// Make sure the required directories exist, and create them if necessary
if(!is_dir($tempuploaddir)) {mkdir($tempuploaddir);}
if(!is_dir($dad)) {mkdir($dad);} //must create the parent dir ; it won’t work without it
if(!is_dir($biguploaddir)) {mkdir($biguploaddir);}
if(!is_dir($smalluploaddir)) {mkdir($smalluploaddir);}
[...] Ver componente aquí. [...]
May 13, 2008 at 3:51 am
Looks very nice. Good job!