Solved

Use php to get a photo in the right proportions

Posted on 2011-09-04
14
310 Views
Last Modified: 2012-05-12
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.
0
Comment
Question by:hrolsons
  • 7
  • 4
  • 3
14 Comments
 
LVL 13

Expert Comment

by:F Igor
Comment Utility
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

0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
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?"
0
 

Author Comment

by:hrolsons
Comment Utility
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
0
 

Author Comment

by:hrolsons
Comment Utility
Here are the original image, and how I'd like it to end up:

 Original
 Edited
0
 
LVL 108

Accepted Solution

by:
Ray Paseur earned 250 total points
Comment Utility
The start image you posted here is 465x721 pixels at 300 DPI.  This is an image 1.550" wide and 2.403" high.  I have saved it on my server here:
http://www.laprbass.com/RAY_temp_hrolsons.jpg

I saved a black image of 481x721 pixels (same dimensions as the finish image you posted here) on my server.  See it here:
http://www.laprbass.com/RAY_temp_hrolsons_black.png

The finish image is 481x721 pixels at 300DPI.  Same height as the start image, and 1.603" wide.  It has two strips of black on each side, 8 pixels wide.

The email message with the memory utilization said something like this:
WITH IMAGES int(4,190,992)
POST IMAGES    int(680,544)
<?php // RAY_temp_hrolsons.php
error_reporting(E_ALL);

// LOCATION OF THE IMAGES (COULD COME IN FROM $_GET URL STRING)
$original = 'http://www.LAPRBass.com/RAY_temp_hrolsons.jpg';
$border   = 'http://www.LAPRBass.com/RAY_temp_hrolsons_black.png';

// READ THE BLACK IMAGE BACKGROUND
$bg = ImageCreateFromPNG($border);

// READ THE IMAGE
$im = ImageCreateFromJPEG($original);

// COMPUTE THE OFFSET FOR THE SIDE BORDERS
$bg_x = imagesx($bg);
$im_x = imagesx($im);
$im_y = imagesy($im);
$offs = (int)($bg_x - $im_x) / 2;

// COPY THE IMAGE TO THE BACKGROUND
ImageCopy
( $bg    // DESTINATION IMAGE
, $im    // SOURCE IMAGE
, $offs  // DESTINATION X-AXIS IN PIXELS
, 0      // DESINTATION Y-AXIS IN PIXELS
, 0      // SOURCE X-AXIS IN PIXELS
, 0      // SOURCE Y-AXIS IN PIXELS
, $im_x  // SOURCE WIDTH
, $im_y  // SOURCE HEIGHT
)
;

// SHOW THE IMAGE
header('Content-type: image/jpg');
ImageJPEG($bg, NULL, 100);

// SHOW THE MEMORY USE
ob_start();
echo "WITH IMAGES ";
var_dump(memory_get_usage());

// REMOVE THE IMAGE RESOURCES
ImageDestroy($im);
ImageDestroy($bg);

// SHOW THE MEMORY USE
ECHO "POST IMAGES ";
var_dump(memory_get_usage());

// SEND THE MESSAGE
$msg = ob_get_clean();
mail('Ray.Paseur@Gmail.com', 'hrolsons memory stats', $msg);

Open in new window

0
 
LVL 13

Assisted Solution

by:F Igor
F Igor earned 250 total points
Comment Utility
For larger images you need a lot of memory configured in your PHP configuration to get it working:

If you have access to the php configuration and modify it,
edit php.ini the line with the folowing text:

memory_limit = 128M (or whatever is set up before)


to

memory limit = 256M  (or a higher value like 512M)


If you can´t access this configuration to modify it,
you can add the following line at the start of your PHP code
(It must be done in every page that you need more memory,
if you can't modify the php configuration for a global value)



<?php

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

...
..
..

Open in new window


And try different values to meet your needs.

0
 

Author Comment

by:hrolsons
Comment Utility
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...
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:hrolsons
Comment Utility
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:

 Actual "real" image
0
 
LVL 13

Expert Comment

by:F Igor
Comment Utility
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

0
 

Author Comment

by:hrolsons
Comment Utility
What is the maximum I can set it to?
0
 
LVL 13

Expert Comment

by:F Igor
Comment Utility
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

0
 
LVL 108

Expert Comment

by:Ray Paseur
Comment Utility
...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
0
 

Author Comment

by:hrolsons
Comment Utility
Thank you guys so much.  I have indeed posted a "follow-on" question here:

http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_27301642.html
0
 

Author Comment

by:hrolsons
Comment Utility
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.
0

Featured Post

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!

Join & Write a Comment

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 article discusses four methods for overlaying images in a container on a web page
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
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.

772 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

10 Experts available now in Live!

Get 1:1 Help Now