
|
View Full Version : PHP Thumbnail Help Please!
ballingtonma 08-16-2004, 04:39 PM Hi, I am trying to create an automatic thumbnail generator in php. So far I have the following code:
error_reporting (E_ALL);
$abc = imagecreatefromjpeg("1.jpg");
$def = imagecreate(120, 90);
imagecopyresized($def, $abc, 0, 0, 0, 0, 120, 90, 400, 400);
imagejpeg($def, '1_thumb.jpg', 100);
ImageDestroy($abc);
ImageDestroy($def);
This doesnt work well and the thumbnail is low quality and streches or deforms it. I will be using it by uploading all kinds of size images (Note: All will be larger than the thumbnail size) so they all need to be resized to the same size, with no streching, deformation or no black areas. Click the link bellow to see how I mean, and how the system should be working:
http://www.theextremenetwork.com/thumb/index.php
Thanks in Advance,
Matt
EXOWorks 08-16-2004, 08:15 PM I use something like this:
$max_width = 200;
$max_height = 200;
$_GET['file'] = 'your file here';
if( !file_exists( 'thumbs/'.$ext . $_GET['file'] ))
{
if ( strstr ( $_GET['file'], '.gif' ) )
{
$im = imagecreatefromgif( $path . $_GET['file']);
}
elseif ( preg_match( '/(\.jpg|\.jpeg)/i', $_GET['file'] ))
{
$im = imagecreatefromjpeg( $path . $_GET['file']);
}
elseif ( preg_match( '/\.png/i', $_GET['file'] ))
{
$im = imagecreatefrompng( $path . $_GET['file']);
}
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0,0,0);
$y = 50 * imagesy($im) / 100;
$widths = imagesx($im);
$heights = imagesy($im);
if ( $widths > $max_width )
{
$img_width = $max_width;
$img_height = ceil( ( $heights * ( ( $max_width * 100 ) / $widths ) ) / 100 );
$heights = $img_height;
$widths = $img_width;
}
else
{
$img_height = $heights;
}
if ( $heights > $max_height )
{
$img_height = $max_height;
$img_width = ceil( ( $widths * ( ( $max_height * 100 ) / $heights ) ) / 100 );
}
else
{
$img_width = $widths;
}
$newwidth = $img_width;
$newheight = $img_height;
$sourcedata = getimagesize ( $path . $_GET['file'] );
$image = imagecreatetruecolor($newwidth, $newheight);
imagecopyresampled($image,$im,0,0,0,0,$newwidth,$newheight,$sourcedata[0],$sourcedata[1]);
imagejpeg($image, 'thumbs/'.$ext.$_GET['file']);
}
You might get some idea from it ..
Burhan 08-17-2004, 03:30 AM You might also want to consider Image_Transform (http://pear.php.net/package/Image_Transform/), a class that is part of PEAR (http://pear.php.net).
If you have the means to, get ImageMagick. ;) It does quite a good job with thumbnailing and so on.
Also, I would use mime/types in general, instead of matching the extensions. Users in general are stupid and screw things up. ;) Which is why I wouldn't rely on anyone else.
Till
ballingtonma 08-17-2004, 08:06 AM Thanks for the replys, It needs to be done using GD. Mike_R's script works ok, only all the thumbnails wont be exactly the same size if the images are different sizes. Is there any way to make the changes so all the thumbnails will be exactly the same size?
thartdyke 08-17-2004, 09:41 AM Mike_R's script sets the maximum height or width to 200, but maintains the aspect ratio. If you have images of differing aspect ratios, yes, you will get images of all sorts of sizes, but the largest dimensio will be no more than 200 pixels.
What are you looking for precisely? What do you want to have happen for images of various aspect ratios? Do you want all the thumbnails to be square? of rectangles of a fixed size? If so, do you just want the edges cropped?
ballingtonma 08-17-2004, 12:00 PM I want the edges to be cropped to the specific size of 120px wide and 90px high.
thartdyke 08-17-2004, 01:29 PM What you need to do is resize to the 'correct' uncropped size with imagecopyresampled. Then crop the edges by copying an image of 120px by 90px from the relevant part of the intermediate image using imagecopy.
Say you have an image that's 480 wide by 180 high. You can resize to 240 wide by 90 high easily (that's similar to what Mike_R's code does, though his would go to 120 wide by 45 high).
You then work out where to take your 120x90 image from to use with imagecopy into a new 120x90 image.
ballingtonma 08-17-2004, 02:32 PM Ok, have you got any form of code on how to go about doing that?
thartdyke 08-17-2004, 06:13 PM No code I'm afraid, and I'm just getting ready to go away for 3 weeks, or I'd hack something out (thoigh I am taking my laptop with me...)
Have a bash yourself - just remember that instead of ensuring all dimensions are at least as small as the target size, you have a step where you resize so that one dimension is the target size, and the other is larger.
Once you've done that, it's just fooling around a bit with imagecopy.
ballingtonma 08-18-2004, 02:57 PM Does anyone know how this can be done, I have tried and tried so many times my head is spinning!
EXOWorks 08-18-2004, 09:16 PM This will copy the image to a new image of 120 x 90 .. Just change it in the above code and try. But the image might be distorted.
$image = imagecreatetruecolor(120, 90);
imagecopyresampled($image,$im,0,0,0,0,120,90,$sourcedata[0],$sourcedata[1]);
xelav 08-19-2004, 09:33 AM just an idea - written it in notepad with no testing
$image = imagecreatetruecolor(120, 90);
$ar=$sourcedata[0]/$sourcedata[1];
if ($ar < 4/3) {
imagecopyresampled($image,$im,0,0,0,0,120,90*($sourcedata[1]/$sourcedata[0]),$sourcedata[0],$sourcedata[1]);
}
else {
imagecopyresampled($image,$im,0,0,0,0,120*($sourcedata[1]/$sourcedata[0]),90,$sourcedata[0], $sourcedata[1]);
}
$w=imagesx($image);
$h=imagesy($image);
if ($w>120)
imagecopy($image,$image,0,0,0+($w-120)/2,0,120,90);
if ($h>90)
imagecopy($image,$image,0,0,0,0+($h-90)/2,120,90);
ballingtonma 08-26-2004, 03:16 PM Thanks for the reply, sorry its took me so long to respond, I have been on haliday. That script doesnt seem to be working, it just returns a blank black image. Any thoughts on how to get it working?
Radchenko 08-26-2004, 05:03 PM Why do something thats been done so many times?
I use jpgtn (freshmeat.net/projects/jpgtn/) which saves a lot of time and processing power (I do something like create a thumbnail directory, save the thumbnail to that dir, then in the script instead of generating a thumbnail every time the page is loaded, i check if the file exists and if not generate it: ie
<?
$image = "1.jpg";
$thumbnail_dir = "./thumbnail";
if (!file_exists("$thumbnail_dir/$image")) {
exec("/usr/local/bin/jpgtn [some arguements here] $image");
}
?>
<img src="<? "$thumbnail_dir/$image" ?>">
or something to that extent.
ballingtonma 08-27-2004, 10:54 AM Thanks, but this needs to be done without using any extra software other than GD.
thartdyke 09-25-2004, 04:51 PM The following is taken from working code:
<?php
$width = 120;
$height = 90;
$path = 'c:\temp\'; //Make sure this exists - and add trailing backslash
$outputdir = 'c:\temp\thumbs\'; //Add trailing backslash
$filename = 'image.jpg';
$file = $path . $filename;
//get image attributes
list($src_width, $src_height, $type, $attr) = getimagesize("$file");
if (($src_width/$src_height) > ($width/$height)) { //Too wide - cut vertical strips from edges
//Resize to get the intermediate image (right height, but too wide)
$int_width = round($height * ($src_width/$src_height));
//Create an image $int_width wide, and $height tall
$int_image = imagecreatetruecolor($int_width, $height);
$src_image = imagecreatefromjpeg($file);
imagecopyresampled($int_image, $src_image, 0, 0, 0, 0, $int_width, $height, $src_width, $src_height);
//Uncomment the next line if you want to save the intermediate file
//imagejpeg($int_image, $outputdir . "tmp.jpg");
//...now crop the top and bottom
$stripwidth = round(($int_width - $width)/2);
$dest_image = imagecreatetruecolor($width, $height);
//imagecopy($dest_image, $int_image, 0, 0, floor($stripwidth), 0, $width, $height);
imagecopy($dest_image, $int_image, 0, 0, $stripwidth, 0, $width, $height);
imagejpeg($dest_image, $outputdir . $filename);
} elseif (($src_width/$src_height) < ($width/$height)) { //Too tall - cut top & bottom strips
//Resize to get the intermediate image (right width, but too tall)
$int_height = round($width * ($src_height/$src_width));
//Create an image $int_width wide, and $height tall
$int_image = imagecreatetruecolor($width, $int_height);
$src_image = imagecreatefromjpeg($file);
imagecopyresampled($int_image, $src_image, 0, 0, 0, 0, $width, $int_height, $src_width, $src_height);
//...now crop the sides
$stripheight = round(($int_height - $height)/2);
$dest_image = imagecreatetruecolor($width, $height);
imagecopy($dest_image, $int_image, 0, 0, 0, $stripheight, $width, $height);
imagejpeg($dest_image, $outputdir . $filename);
} else { //Just right - resize only
$src_image = imagecreatefromjpeg($file);
$dest_image = imagecreatetruecolor($width, $height);
imagecopyresized($dest_image, $src_image, 0, 0, 0, 0, $width, $height, $src_width, $src_height);
imagejpeg($dest_image, $outputdir . $filename);
}
?>
I've made it fairly verbose, so it should be clear what's happening. It basically grabs the image size, then processes the image in one of three ways, depending on whether the source image is:
- Wider than it needs to be
- Taller than it needs to be
- The correct aspect ratio
No guarantees on what happens if the source is smaller than the thumbnail size. Note that the image gets resized, even if it's the correct size. I haven't worried too much about what to do if the strips to be removed are of uneven size (where I have an odd number of pixels to remove). I don't suppose it makes much difference.
Careful with path strings - you may need to escape the backslashes. I did on Windows, but pasting the code into here, the PHP wasn't parsed right until I removed the extra backslashes - can't be bothered to work it out now! It still omits the trailing backslash, so make sure you add them.
ballingtonma 09-25-2004, 06:51 PM Thanks mate, thats absolutely brilliant!
I owe you one!
thartdyke 09-26-2004, 10:01 AM Just noticed I forgot to edit some of the comments in the middle section, but the code is right!
ballingtonma 09-26-2004, 05:37 PM Thats ok, was it anything importaint?
thartdyke 09-26-2004, 06:19 PM No, just things lkike the second time I say:
//Create an image $int_width wide, and $height tall
I meant:
//Create an image $width wide, and $int_height tall
As I said, the code is correct though.
|