Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

php crop after resize

Posted on 2010-09-22
10
549 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 109

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
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
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 109

Expert Comment

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

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 109

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 109

Expert Comment

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

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Generating table dynamically is the most common issue faced by php developers.... So it seems there is a need of an article that explains the basic concept of generating tables dynamically. It just requires a basic knowledge of html and little maths…
These days socially coordinated efforts have turned into a critical requirement for enterprises.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
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 …

856 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