Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

php crop after resize

Posted on 2010-09-22
10
Medium Priority
?
558 Views
Last Modified: 2012-05-10
Hi fellow experts. Im in some sort of twilight zone for more then a day and I need Your help.
I need to upload image with some width and height and crop a part with new width and new height. For example:

original img (600x374)

I need two thumbs, one with 100x100 and one with 200x100.
What I did so far is to resize original image to 160x100 and 200x124 so I can keep aspect ratio, but now I want to crop 100x100 and 200x100 respectively. Is that even possible with one imagecopyresampled command or I need two of them (first one to resize, second one to crop it).

Look at my code below to see what I achieved so far. Folder structure looks like this:

storage
|-images
  |-!100x100!
  |-!200x100!

Original img goes to images folder and thumbnails needs to go to !100x100! and !200x200! folders. So Im getting original coppied where it needs to, at 100x100 folder I get image with 160x100 and in 200x100 folder I get image with 200x124.

Thanks in advance.


//This stops SQL Injection in POST vars
	foreach ($_POST as $key => $value) {
		$$key = mysql_real_escape_string(stripslashes(htmlspecialchars(strip_tags($value))));
	}
	
	//This stops SQL Injection in GET vars
	foreach ($_GET as $key => $value) {
		$$key = mysql_real_escape_string(stripslashes(htmlspecialchars(strip_tags($value))));
	}
	
	$storage = "storage/" . $path;
	$contents = scandir($storage);
	$bad = array(".", "..");
    $items = array_diff($contents, $bad);
	
	foreach ($items as &$item)
	{
		if ((filetype($storage."/".$item) == "dir") && (utf8_substr($item,0,1) == "!") && (utf8_substr($item,-1) == "!"))
			//$sizes[] = array_filter(explode("x",utf8_substr($item,1,-1)));
			$item = array_filter(explode("x",utf8_substr($item,1,-1)));
	}
	
//	print_r($items);

	if (!empty($_FILES)) {
		$tempFile = $_FILES['Filedata']['tmp_name'];

		$targetPath = $storage . '/';

		$targetFile =  str_replace('//','/',$targetPath) . $_FILES['Filedata']['name'];

		move_uploaded_file($tempFile,$targetFile);
		echo "1";
		list($width, $height) = getimagesize($targetFile);
		
		$ratio = $width/$height;
		
		foreach ($items as &$item)
		{
			$newwidth = $item[0]; // This can be a set value or a percentage of original size ($width)
			$newheight = $item[1]; // This can be a set value or a percentage of original size ($height)
			
			if ($item[0] == $item[1])
			{
				if ($width > $height)
				{
					$newwidth = $item[1] * $ratio;
				}
				elseif ($width < $height)
				{
					$newheight = $item[0] / $ratio;
				}
			}
			elseif ($item[0] > $item[1])
			{
				$newheight = $item[0] / $ratio;
			}
			else
			{
				$newwidth = $item[1] * $ratio;
			}
				
			

			
			$thumb = imagecreatetruecolor($newwidth, $newheight);
			$source = imagecreatefromjpeg($targetFile);
			
			imagecopyresampled($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
			
			$itemFile = $storage . "/" . "!" . $item[0] . "x" . $item[1] . "!/" . $_FILES['Filedata']['name'];

			
			imagejpeg($thumb1, $itemFile, 100);

				echo "1";
		}

	}

Open in new window

0
Comment
Question by:R-Byter
  • 5
  • 4
10 Comments
 
LVL 31

Expert Comment

by:Marco Gasi
ID: 33736025
Sorry, but if you say towish to crop the two images, I understand you want to create a smaller image which captures only a portion of the original image. If this is right, you should use imagecopy() function, not imagecopyresampled(). In fact, if you wish to capture only a portion of original image you don't need to resample image because you don't reduce its size nor its quality.

But if you wish to give a smaller size to the entire image without regarding to the aspect ratio, then you have to use imagecopyresampled() function.

In both cases, you have to use two separate commands, because you give different parameters regarding width and height: 160 x 100 vs 100 x 100 and 200 x 124 vs 200 x 100.
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 33739136
Near line 66, et seq...

$thumb = imagecreatetruecolor($newwidth, $newheight);
...
imagejpeg($thumb1, $itemFile, 100);

It appears that $thumb1 is undefined in this script.
0
 
LVL 14

Author Comment

by:R-Byter
ID: 33739182
Well, I think imagecopy and imagecopyresampled works pretty much the same way, though imagecopyresampled  gives "smoother" images.
What I want is to capture a portion of original image reduced size.
So if I have a picture of some face 1000x500px, and I need a thumbnail of 100x100, it would look silly to take crop directly from image with original size because i would get one eye, part of hair... :)
The idea was to reduce the image in its size, keep aspect ratio, and then take a crop of reduced image. Most of the examples I found on the net create square thumbnails, it is pretty much easy to do it. Didnt found example which would take original image and create thumbnails with predefined width and height.
Thanks
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 14

Author Comment

by:R-Byter
ID: 33739187
Thanks Ray I noticed that, my mistake. It should be:

imagejpeg($thumb, $itemFile, 100);



0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 33739753
This seems to work for me.
RAY-temp-600x374.jpg
0
 
LVL 111

Accepted Solution

by:
Ray Paseur earned 2000 total points
ID: 33739759
Here is the script that I used to process the test image.

There are a lot of ways to deal with the peripheral parts of this question.  Should the function return the image resource?  Or send the image into the browser output stream?  You can probably make those choices better for your application than I can.  The function as written stores the image on the file server.

HTH, ~Ray
<?php // RAY_resize_and_crop.php
error_reporting(E_ALL);

// RESIZE AN IMAGE PROPORTIONALLY AND CROP CENTERED

function resize_and_crop($original_image_url, $thumb_image_url, $thumb_w, $thumb_h, $quality=75)
{
    // ACQUIRE THE ORIGINAL IMAGE: http://us3.php.net/manual/en/function.imagecreatefromjpeg.php
    $original = imagecreatefromjpeg($original_image_url);
    if (!$original) return FALSE;

    // GET ORIGINAL IMAGE DIMENSIONS
    list($original_w, $original_h) = getimagesize($original_image_url);

    // RESIZE IMAGE AND PRESERVE PROPORTIONS KEEPING AS MUCH OF THE IMAGE AS POSSIBLE
    $thumb_w_resize = $thumb_w;
    $thumb_h_resize = $thumb_h;
    if ($original_w > $original_h)
    {
        $thumb_h_ratio  = $thumb_h / $original_h;
        $thumb_w_resize = (int)round($original_w * $thumb_h_ratio);
    }
    else
    {
        $thumb_w_ratio  = $thumb_w / $original_w;
        $thumb_h_resize = (int)round($original_h * $thumb_w_ratio);
    }
    if ($thumb_w_resize < $thumb_w)
    {
        $thumb_h_ratio  = $thumb_w / $thumb_w_resize;
        $thumb_h_resize = (int)round($thumb_h * $thumb_h_ratio);
        $thumb_w_resize = $thumb_w;
    }

    // CREATE THE PROPORTIONAL IMAGE RESOURCE
    $thumb = imagecreatetruecolor($thumb_w_resize, $thumb_h_resize);
    if (!imagecopyresampled($thumb, $original, 0,0,0,0, $thumb_w_resize, $thumb_h_resize, $original_w, $original_h)) return FALSE;

    // ACTIVATE THIS TO STORE THE INTERMEDIATE IMAGE
    // imagejpeg($thumb, 'RAY_temp_' . $thumb_w_resize . 'x' . $thumb_h_resize . '.jpg', 100);

    // CREATE THE CENTERED CROPPED IMAGE TO THE SPECIFIED DIMENSIONS
    $final = imagecreatetruecolor($thumb_w, $thumb_h);

    $thumb_w_offset = 0;
    $thumb_h_offset = 0;
    if ($thumb_w < $thumb_w_resize)
    {
        $thumb_w_offset = (int)round(($thumb_w_resize - $thumb_w) / 2);
    }
    else
    {
        $thumb_h_offset = (int)round(($thumb_h_resize - $thumb_h) / 2);
    }

    if (!imagecopy($final, $thumb, 0,0, $thumb_w_offset, $thumb_h_offset, $thumb_w_resize, $thumb_h_resize)) return FALSE;

    // STORE THE FINAL IMAGE - WILL OVERWRITE $thumb_image_url
    if (!imagejpeg($final, $thumb_image_url, $quality)) return FALSE;
    return TRUE;
}

// USE CASE
resize_and_crop('RAY_temp_600x374.jpg', 'RAY_temp_100x100.jpg', 100, 100);
resize_and_crop('RAY_temp_600x374.jpg', 'RAY_temp_200x100.jpg', 200, 100);
resize_and_crop('RAY_temp_600x374.jpg', 'RAY_temp_200x300.jpg', 200, 300);

Open in new window

0
 
LVL 14

Author Comment

by:R-Byter
ID: 33739912
Thanks for Your help Ray and Im awarding You the points. With the help of Your detailed solution I managed to find out the way to correct my code.
So I changed this line:

$thumb = imagecreatetruecolor($newwidth, $newheight);

to:

$thumb = imagecreatetruecolor($item[0], $item[1]);

just as You did before using imagecopy. Then I tried to use only one imagecopyresampled command and it worked so Im asking You to tell me is it a good practice or do you see any flaw in this (I have great confidence in You and Your solutions here at EE):

imagecopyresampled($thumb, $source, 0 - ($newwidth - $item[0]) / 2, 0 - ($newheight - $item[1]) / 2, 0, 0, $newwidth, $newheight, $width, $height);
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 33740020
Thanks for the points.  As to "is it a good practice" -- I have no idea.  

As a general rule I do not like compound statements.  They hide information from the standard debugging tools like "var_dump()."  So if you needed to know the value of "0 - ($newheight - $item[1]) / 2" but it was being computed as part of the function call, you're hosed.

Best of luck with the project, ~Ray
0
 
LVL 14

Author Comment

by:R-Byter
ID: 33740308
Thanks again Ray. Its always good to hear practical advices from You.
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 33740529
Glad to help.  Over and out until next time...
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article discusses four methods for overlaying images in a container on a web page
Originally, this post was published on Monitis Blog, you can check it here . In business circles, we sometimes hear that today is the “age of the customer.” And so it is. Thanks to the enormous advances over the past few years in consumer techno…
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to count occurrences of each item in an array.
Suggested Courses

963 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question