1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
<?
#dl("php_gd2.dll");
// requiered argument
$pic = $_REQUEST["pic"];
// optional
$width = $_REQUEST["width"];
$height = $_REQUEST["height"];
if (($width == "") || ($height == "")) {
$maxwidth = "160";
$maxheight = "120";
}
else {
$maxwidth = $width;
$maxheight = $height;
}
$getimg = getimagesize($pic);
// 0. width
// 1. height
// 2. Typ: 1=GIF, 2=JPEG, 3=PNG
// 3. size html tags (e.g. 'width="111" height="24"')
// preventing from accessing non gfx files.
if ((($getimg[2] < 1) && ($getimg[2] > 3)) || ($getimg[2] == "")) {
die("No valid gfx-source.");
}
$oldwidth = $getimg[0];
$oldheight = $getimg[1];
// If original is smaller then new image
if (($oldwidth <= $maxwidth) && ($oldheight <= $maxheight)) {
// JPEG
if($getimg[2]==2){
$img = ImageCreateFromJPEG($pic);
header("Content-Type: image/jpeg");
imagejpeg($img);
}
// Gif
if($getimg[2]==1){
$img = ImageCreateFromGIF($pic);
header("Content-Type: image/gif");
imagegif($img);
}
// PNG
if($getimg[2]==3){
$img = ImageCreateFromPNG($pic);
header("Content-Type: image/png");
imagepng($img);
}
}
else {
if ($oldwidth >= $oldheight) {
$relation = $oldwidth / $oldheight;
$newwidth = $maxwidth;
$newheight = round($newwidth / $relation);
while (($newwidth > $maxwidth) || ($newheight > $maxheight)) {
$newwidth--;
$newheight = round($newwidth / $relation);
}
}
else {
$relation = $oldheight / $oldwidth;
$newheight = $maxheight;
$newwidth = round($newheight / $relation);
while (($newheight > $maxheight) || ($newwidth > $maxwidth)) {
$newheight--;
$newwidth = round($newheight / $relation);
}
}
$imgA = imagecreatetruecolor($newwidth,$newheight); //alte gdlib --> imagecreate()
// JPEG
if($getimg[2]==2){
$imgB = ImageCreateFromJPEG($pic);
imagecopyresized($imgA, $imgB, 0,0, 0,0, $newwidth, $newheight, $oldwidth, $oldheight);
header("Content-Type: image/jpeg");
imagejpeg($imgA);
}
// Gif
if($getimg[2]==1){
$imgB = ImageCreateFromGIF($pic);
imagecopyresized($imgA, $imgB, 0,0, 0,0, $newwidth, $newheight, $oldwidth, $oldheight);
header("Content-Type: image/gif");
imagegif($imgA);
}
// PNG
if($getimg[2]==3){
$imgB = ImageCreateFromPNG($pic);
imagecopyresized($imgA, $imgB, 0,0, 0,0, $newwidth, $newheight, $oldwidth, $oldheight);
header("Content-Type: image/png");
imagepng($imgA);
}
}
?>
Refactorings
No refactoring yet !
typefreak
November 1, 2007, November 01, 2007 12:17, permalink
Personally, I would rather use $_POST or $_GET then $_REQUEST
Either way, you're not even trying to prevent notices. Bad idea. Especially if you're trying to send headers after that.
The statement ($getimg[2] < 1 && $getimg[2] > 3) alway returns false, as a number can't be smaller then 1, and bigger then 3 at the same time.
The use of the while-loop doensn't make any sense to me.
Function names are supposed to be case-sensitive, better use lowercase where appropriate.
$imgA and $imgB aren't really describing names. Rather use $smallimg and $bigimg instead.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
<? // requiered argument if ( empty($_REQUEST["pic"]) ) { die('You haven\'t specified a picture'); } $pic = $_REQUEST["pic"]; // optional parameters $maxwidth = (isset($_REQUEST['width']) ? $_REQUEST['width'] : 160); $maxheight = (isset($_REQUEST['height']) ? $_REQUEST['height'] : 120); $getimg = getimagesize($pic); // 0. width // 1. height // 2. Type: 1=GIF, 2=JPEG, 3=PNG // 3. size html tags (e.g. 'width="111" height="24"') // preventing from accessing non gfx files. if ( $getimg[2] < 1 || $getimg[2] > 3 || $getimg[2] == "" ) { die("No valid gfx-source."); } $oldwidth = $getimg[0]; $oldheight = $getimg[1]; // If original is smaller then or equal to new image if ( $oldwidth <= $maxwidth && $oldheight <= $maxheight ) { switch ($getimg[2]) { case 1: // Gif image $img = imagecreatefromgif($pic); header("Content-Type: image/gif"); imagegif($img); break; case 2: // Jpeg image $img = imagecreatefromjpeg($pic); header("Content-Type: image/jpeg"); imagejpeg($img); break; case 3: // Png image $img = imagecreatefrompng($pic); header("Content-Type: image/png"); imagepng($img); break; } } else { // Image should be rezised $widthdif = $oldwidth / $maxwidth; $heightdif = $oldheight / $maxheight; $maxdif = max($widthdif, $heightdif); $newwidth = floor($oldwidth / $maxdif); $newheight = floor($oldheight / $maxdif); $smallimg = imagecreatetruecolor($newwidth,$newheight); //alte gdlib --> imagecreate() switch ($getimg[2]) { case 1: // Gif image $bigimg = imagecreatefromgif($pic); imagecopyresized($smallimg, $bigimg, 0,0, 0,0, $newwidth, $newheight, $oldwidth, $oldheight); header("Content-Type: image/gif"); imagegif($smallimg); break; case 2: // Jpeg image $bigimg = imagecreatefromjpeg($pic); imagecopyresized($smallimg, $bigimg, 0,0, 0,0, $newwidth, $newheight, $oldwidth, $oldheight); header("Content-Type: image/jpeg"); imagejpeg($smallimg); break; case 3: // Png image $imgB = imagecreatefrompng($pic); imagecopyresized($smallimg, $bigimg, 0,0, 0,0, $newwidth, $newheight, $oldwidth, $oldheight); header("Content-Type: image/png"); imagepng($smallimg); break; } } ?>
tempouser.myopenid.com
November 2, 2007, November 02, 2007 09:04, permalink
Hello,
thanks for the refactoring. I still got the performance issues, but that must not implicitly topic to the php code.
Great code improvment! Especialy the resize part. Dont know what i was doing in complex stuff, the "while-thing etc" ;)
What is this kind of php syntax postet below? Is there an manual entry?
1
$maxwidth = (isset($_REQUEST['width']) ? $_REQUEST['width'] : 160);
typefreak
November 2, 2007, November 02, 2007 09:47, permalink
It is called a ternary operator: (scroll down to the 'ternary operator' heading.)
http://nl2.php.net/operators.comparison
In short:
if the part before the ? is true, then the part between ? and : is executed. otherwise, the part after : is executed.
The line you copied is functional equivilant to:
1 2 3 4 5 6
if ( isset($_REQUEST['width']) ) {
$maxwidth = $_REQUEST['width'];
}
else {
$maxwidth = 160;
}
zaadjis
November 2, 2007, November 02, 2007 13:53, permalink
using Imagick http://valokuva.org/?p=33
tempouser.myopenid.com
November 5, 2007, November 05, 2007 08:32, permalink
I noticed, that the imagecreatetruecolor() function can be very slow for images larger than 2000x2000.
So I added a cache-mode. Maybe there is something to refactor ;)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
<?
// cache mode settings
$cache = true; // true/false --> enable/disable cache mode
$cache_dir = "./cache"; // server directory -> must be writeable
$cache_web_dir = "/fotos/cache"; // web directory
// requiered argument
$pic = $_REQUEST["pic"];
// optional parameters
$maxwidth = (isset($_REQUEST['width']) ? floor($_REQUEST['width']) : 160); // default width 160
$maxheight = (isset($_REQUEST['height']) ? floor($_REQUEST['height']) : 120); // default height 120
$getimg = getimagesize($pic);
// 0. width
// 1. height
// 2. typ: 1=GIF, 2=JPEG, 3=PNG
// 3. html tag (e.g. 'width="111" height="24"')
// preventing from accessing non gfx files.
if ((($getimg[2] < 1) || ($getimg[2] > 3)) || ($getimg[2] == "")) {
die("No valid gfx-source.");
}
$oldwidth = $getimg[0];
$oldheight = $getimg[1];
// if original is smaller then or equal to new image
if ( $oldwidth <= $maxwidth && $oldheight <= $maxheight ) {
header("HTTP/1.1 302 Found");
header("Location: " . $pic);
}
else {
// image should be resized
$widthdif = $oldwidth / $maxwidth;
$heightdif = $oldheight / $maxheight;
$maxdif = max($widthdif, $heightdif);
$newwidth = floor($oldwidth / $maxdif);
$newheight = floor($oldheight / $maxdif);
// caching enabled
if ($cache) {
$char_replace = array(".", "/");
$cache_dir = $cache_dir . "/" . str_replace($char_replace, "", dirname($pic)) . "w" . $newwidth . "h" . $newheight . basename($pic);
$cache_web_dir = $cache_web_dir . "/" . str_replace($char_replace, "", dirname($pic)) . "w" . $newwidth . "h" . $newheight . basename($pic);
if (file_exists($cache_dir)) {
header("HTTP/1.1 302 Found");
header("Location: " . $cache_web_dir);
die;
}
}
$smallimg = imagecreatetruecolor($newwidth,$newheight);
switch ($getimg[2]) {
case 1:
// gif image
$bigimg = imagecreatefromgif($pic);
imagecopyresized($smallimg, $bigimg, 0, 0, 0, 0, $newwidth, $newheight, $oldwidth, $oldheight);
if ($cache) {
imagegif($smallimg, $cache_dir);
header("HTTP/1.1 302 Found");
header("Location: " . $cache_web_dir);
}
else {
header("Content-Type: image/gif");
imagegif($smallimg);
}
break;
case 2:
// jpg image
$bigimg = imagecreatefromjpeg($pic);
imagecopyresized($smallimg, $bigimg, 0, 0, 0, 0, $newwidth, $newheight, $oldwidth, $oldheight);
if ($cache) {
imagejpeg($smallimg, $cache_dir);
header("HTTP/1.1 302 Found");
header("Location: " . $cache_web_dir);
}
else {
header("Content-Type: image/jpeg");
imagejpeg($smallimg);
}
break;
case 3:
// png image
$bigimg = imagecreatefrompng($pic);
imagecopyresized($smallimg, $bigimg, 0, 0, 0, 0, $newwidth, $newheight, $oldwidth, $oldheight);
if ($cache) {
imagepng($smallimg, $cache_dir);
header("HTTP/1.1 302 Found");
header("Location: " . $cache_web_dir);
}
else {
header("Content-Type: image/png");
imagepng($smallimg);
}
break;
}
}
?>
Hubert Roksor
November 6, 2007, November 06, 2007 17:16, permalink
You should bump the cache-hit thing way up. The beginning of the script should look like the snippet below.
Also, is that code run often? I mean, is it used to display thumbnails on a live page? Because as I understand it, if $_REQUEST["pic"] is a URL, you get a round trip to the external server everytime someone displays the image if that image is not cached (if it's, ironically, not deemed worth caching because of its small size). Checking external resources is very costly and you'd actually be better off hosting a replica of the image on your own server.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// cache mode settings
$cache = true; // true/false --> enable/disable cache mode
$cache_dir = "./cache"; // server directory -> must be writeable
$cache_web_dir = "/fotos/cache"; // web directory
// requiered argument
$pic = $_REQUEST["pic"];
// caching enabled
if ($cache) {
$char_replace = array(".", "/");
$cache_dir = $cache_dir . "/" . str_replace($char_replace, "", dirname($pic)) . "w" . $newwidth . "h" . $newheight . basename($pic);
$cache_web_dir = $cache_web_dir . "/" . str_replace($char_replace, "", dirname($pic)) . "w" . $newwidth . "h" . $newheight . basename($pic);
if (file_exists($cache_dir)) {
header("HTTP/1.1 302 Found");
header("Location: " . $cache_web_dir);
die;
}
}
Hubert Roksor
November 6, 2007, November 06, 2007 17:18, permalink
Oh, also, you should take a look at imagecopyresampled(). It's the same as imagecopyresized() except that it gives better results, but it is also a little less performant than imagecopyresized(). But since you're caching the results, it wouldn't really matter.
JWvdV
November 6, 2007, November 06, 2007 17:43, permalink
Perhaps you can use this...
Good luck.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
<?php function image_createfromany($file){ if(is_file($file) && is_array($image_info = getimagesize($file))){ switch(strtolower($image_info['mime'])){ case 'image/jpeg': if(function_exists('imagecreatefromjpeg')) $src = @imagecreatefromjpeg($file); break; case 'image/gif': if(function_exists('imagecreatefromgif')) $src = @imagecreatefromgif($file); break; case 'image/png': if(function_exists('imagecreatefrompng')) $src = @imagecreatefrompng($file); break; case 'image/xbm': case 'image/x-xbitmap': if(function_exists('imagecreatefromxbm')) $src = @imagecreatefromxbm($file); break; case 'image/vnd.wap.wbmp': if(function_exists('imagecreatefromwbmp')) $src = @imagecreatefromwbmp($file); break; case 'image/x-xpixmap': if(function_exists('imagecreatefromxpm')) $src = @imagecreatefromxpm($file); break; default: return false; } if(isset($src) && !empty($src)) return($src); } return false; } function image_thumb($img, $maxwidth, $maxheight, $scale=true){ if(include_functions('validate') && is_int($maxwidth) && is_int($maxheight)){ if(is_file($img)) $img = image_createfromany($img); if($img && function_exists('imagesx') && function_exists('imagesy') && is_numeric($width = @imagesx($img)) && is_numeric($height = @imagesy($img))){ if($scale && (($maxwidth < $width) || ($maxheight < $height))){ $ratio = ((($width / $maxwidth) > ($height / $maxheight))? ($maxwidth / $width) : ($maxheight / $height)); $width = round($ratio * $width); $height = round($ratio * $height); } if(function_exists('imagecreate')){ $src = (function_exists('imagecreatetruecolor')? imagecreatetruecolor($width, $height) : imagecreate($width, $height)); if(function_exists('imagecopyresampled')) imagecopyresampled($src, $img, 0, 0, 0, 0, $width, $height, imagesx($img), imagesy($img)); else if(function_exists('imagecopyresized')) imagecopyresized($src, $img, 0, 0, 0, 0, $width, $height, imagesx($img), imagesy($img)); else return(false); return $src; } } } return false; } ?>
tempouser.myopenid.com
November 7, 2007, November 07, 2007 09:33, permalink
@ Huber Roksor: its all local stuff, no remote ressources.
ive tested the imagecopyresampled() function. i will use imagecopyresized, because in my tests, the quality results are not better than expected. in my opinion the images are looking a bit washy.
i got this code running on my old webserver. on the new one (better hardware), this script is pretty slow. dont know why. maybe also an apache problem. but maybe someone can altough improve this code. thanks.