Link to home
Start Free TrialLog in
Avatar of hrolsons
hrolsonsFlag for United States of America

asked on

Use php to get a photo in the right proportions

I have a folder full of .jpg files of all kinds of random dimensions and sizes.  I have used php for manipulating images but it has been a while.

I wish to print them all to 8"x12" paper and have nothing cropped or stretched from the original.

What I am currently doing is manually adding black bars to meet the correct dimensions.

Since I'm printing to 8"x12" the ratio is 1/1.5 or 0.667

So a photo coming in at 3000x4000 will finalize at 3000x4500 with black on top & bottom of 3000x250

A picture coming in at 2500x10000 will finalize at 6666x10000 with black bars on right & left of 2083x10000

Hopefully I'm being clear.  The incoming photo will be of varying sizes, both landscape & portrait.  They will all print to 8"x12" or 12"x8" with no stretching or cropping.
Avatar of Francisco Igor
Francisco Igor
Flag of Canada image

Thy this function . It needs the PHP/gd2 functions enabled.

function imageResize($filename,$newfile){

	$imgsrc=@imagecreatefromjpeg ($filename);
	if (!$imgsrc) return false;
	list($width, $height, $type, $atr) = getimagesize($filename);
	// ratio selection
	if ($width<$height){
		$ratio=8/12;
	}else{
		$ratio=12/8;
	}
	// best size selection
	if ($height<=round($width/$ratio)){
		$width_n=($width);
		$height_n=round($width/$ratio);
	}else{
		$height_n=($height);
		$width_n=round($height*$ratio);
	}
	
	/* New image */
	$imgdst  = imagecreatetruecolor ($width_n, $height_n); 
	// White BGColor  (255,255,255)
	$bgc = imagecolorallocate ($imgdst, 255, 255, 255);
	imagefilledrectangle ($imgdst, 0, 0, $width_n, $height_n, $bgc);		

	// add simetric borders
	$xx=($width_n-$width)/2;
	$yy=($height_n-$height)/2;

	//best function to resize
	if (function_exists("imagecopyresampled"))
		imagecopyresampled($imgdst,$imgsrc,$xx,$yy,0,0,$width_n,$height_n,$width,$height);
	//alternative function

		else
		imagecopyresized($imgdst,$imgsrc,$xx,$yy,0,0,$width_n,$height_n,$width,$height);
	//create the new (jpeg) image in the $newfile path
	imagejpeg($imgdst,$newfile);
	return true;
}

Open in new window

I think we need a little clarification here, and it would be really useful if you could post your test images and show us the code you have tried to use to complete this task.

The term will finalize is not clear to me, and it is not a term of art in imaging.  Please clarify.

When you write, "no stretching or cropping" I understand that to mean that you would want to preserve the aspect ratio of the images.  Is that what you mean?
http://en.wikipedia.org/wiki/Aspect_ratio_%28image%29

What image density (DPI) do you intend to use for printing?  On my fine art photo-quality Epson printers I usually use at least 150DPI and never find any value in using more than 300DPI.  Parenthetically, I rarely find 8x12" paper, but that is probably not really relevant to your objectives.

The image dimensions in pixels for a 12x8 landscape image would be 1,800 x 1,200 at 150DPI and 3,600 x 2,400 at 300DPI.  Image dimensions are always written with the width (x-axis) first.  

Do you care about the size and position of the "black bars?"  Do you want the image centered in a black field?  Or do you want the image resized  to occupy the largest possible area of the paper, understanding that resizing images to enlarge them may produce visually unacceptable results.  And resizing images to reduce them may result in irrevocable loss of detail as image information is discarded in the process

Do you want to render the images to the browser output stream or save them into a library?  

Do you care about compression and image quality?  If so, please tell us what your objectives are - better images or smaller file sizes?

The general design I would use goes something like this: 1. create an image resource of appropriate dimensions with black.  2. use ImageCopyResampled() to put the raw image into the final image.  There is not really much more to it, just a few ratios, etc.

Have you thought about doing this with Photoshop "actions?"
Avatar of hrolsons

ASKER

I'm getting this error:

"Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 3204 bytes) in..."

On this line:

$imgdst  = imagecreatetruecolor ($width_n, $height_n);

Where $width_n=3204 and $height_n=4806
Here are the original image, and how I'd like it to end up:

 User generated image
 User generated image
ASKER CERTIFIED SOLUTION
Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ray,

When I run your code, the correct image pops up, but none of your "echo" statements show up on-screen for some reason.  And, the mail function didn't work.  I just installed phpED on my local machine and I believe php.ini is not configured correctly.

I'm going to try something, based on your code...
OK, I tried your code with the "real" image and:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 12388 bytes) in C:\Photo Resell\Photo Editor\noname2.php on line 13

And Ray, I know it drives you crazy when people don't include the "real" image in their question, but I thought it was too large to post.  But in this case, here goes:

 User generated image
For an image of 3204 x 4806 you need at least
3204*4806*24 = 369562176 bytes (360M)
so you need to set the memory-limit from 512M or more for larger images.

<?php

ini_set('memory_limit', '512M');


?>

Open in new window

What is the maximum I can set it to?
You can set it up up to all available memory on the server.

If you want no limit set it to -1
(0 will work, i guess)


See the documentation for "memory_limit" php configuration.
http://php.net/manual/en/ini.core.php

...none of your "echo" statements show up on-screen for some reason.  
The reason is on line 28: ob_start(); and you can read about that function here.
See http://us2.php.net/manual/en/function.ob-start.php

The reason for using output buffering and the mail() command is that the script writes a JPG image header, so the browser output has to be a JPG image.  Text does not fit into that model, so I capture the text and use email to get it to myself.  This lets me see what is going on in the script.  The browser output of the image lets me see that the script worked correctly.

And, the mail function didn't work.
Yes it did.  I just removed it from the script on my server so I wouldn't get junk mail if someone is testing the script at http://www.laprbass.com/RAY_temp_hrolsons.php

More importantly, the test data you provided to us was nothing like the actual data you're working with.  A file that is 91KB is materially different from a file that is 3,100KB.  Notwithstanding that, you have the solution to your question as well as a script that shows the implementation using the test data you gave us.  And now all you need to do is get your server settings right.  So I'll sign off on this one.  If you have other questions, please consider posting a "follow-on" question.  Best of luck with your project, ~Ray
Thank you guys so much.  I have indeed posted a "follow-on" question here:

https://www.experts-exchange.com/questions/27301642/Make-a-solid-black-image.html
Darn it, I shouldn't have created the new question because I can see the answer now in "fraigor" post above.

And now when I change the memory limit, fraigor's code is almost working, but the black bar(after I changed to 0,0,0) is only to the side.

What a mess, and now how do I do points, you have all been so helpful, as usual.