Solved

php crop after resize

Posted on 2010-09-22
10
545 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 30

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 108

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
 
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 108

Expert Comment

by:Ray Paseur
ID: 33739753
This seems to work for me.
RAY-temp-600x374.jpg
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 108

Accepted Solution

by:
Ray Paseur earned 500 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 108

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 108

Expert Comment

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

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Introduction HTML checkboxes provide the perfect way for a web developer to receive client input when the client's options might be none, one or many.  But the PHP code for processing the checkboxes can be confusing at first.  What if a checkbox is…
Deprecated and Headed for the Dustbin By now, you have probably heard that some PHP features, while convenient, can also cause PHP security problems.  This article discusses one of those, called register_globals.  It is a thing you do not want.  …
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

706 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

Need Help in Real-Time?

Connect with top rated Experts

22 Experts available now in Live!

Get 1:1 Help Now