PHP image on the fly resizing with caching, and croping
Ik maak gebruik van image 404 caching.
Hiervoor maak ik gebruik van een php script.
Dit script werkt alsvolgt:
ik laadt vanuit een datafeed een afbeelding in.
Deze afbeelding is bijv. 1024 x 680px
het script haalt de afbeelding op, plaatst deze in een subdirectory met een id van het feed.
resized de afbeelding naar een formaat die ik wil gebruiken op mijn website (250x250px) met behoud van proportie.
vervolgens maakt hij de afbeelding 250x166px
Wat ik graag wil is dat hij de afbeelding maakt naar 250x250px en het restant vult met wit.
Dit wil ik namelijk toepassen om een vast formaat in mijn script in te stellen wat weer goed werkt voor Google.
Wie kan mij helpen mijn huidige script aan te passen:
Quote:
mysql_select_db( $db_database, $_resource );
# adjust if you use
#your definition in xhelpers.php should look like:
#define ('DF_IMAGE','concat("http://img.example.com/cache/",`feed_id`,"/",`items_id`,".jpg")');
if ( preg_match("#.*imgcache/([0-9]+)/([0-9]+).jpg#",$_SERVER['REQUEST_URI'],$m) ) {
$dir='img/'.$m[1];
if ( ! is_dir($dir) ) { mkdir ($dir,0755,true); }
$img=$dir.'/'.$m[2].'.jpg';
$id=(int)$m[2];
$feed_q="select image from $db_table where items_id = $id limit 1";
$_feeds=mysql_query($feed_q,$_resource);
$p=mysql_result($_feeds,0);
if ( $p ) {
createthumb($p,"$img",216,216);
exit;
}
}
function createthumb($name,$filename,$new_w,$new_h)
{
$src_img=false;
$name=str_replace(array('[',']',' ','&'),array('%5B','%5D','%20','&'),$name);
$src_img=imagecreatefromstring(file_get_contents($name));
if ( ! $src_img ) {
if (preg_match("/(jpg|jpeg)$/i",$name)){
$src_img=imagecreatefromjpeg($name);
}
if (preg_match("/gif$/i",$name)){
$src_img=imagecreatefromgif($name);
}
if (preg_match("/png$/i",$name)){
$src_img=imagecreatefrompng($name);
}
}
if ( ! $src_img ) {
return;
#or use local image as base
}
$old_x=imageSX($src_img);
$old_y=imageSY($src_img);
if ($old_x > $old_y)
{
$thumb_w=$new_w;
$thumb_h=$old_y*($new_h/$old_x);
}
if ($old_x < $old_y)
{
$thumb_w=$old_x*($new_w/$old_y);
$thumb_h=$new_h;
}
if ($old_x == $old_y)
{
$thumb_w=$new_w;
$thumb_h=$new_h;
}
$d_h=$thumb_h > 216?216:$thumb_h;
$dst_img=ImageCreateTrueColor($thumb_w,$d_h);
imagecopyresampled($dst_img,$src_img,0,0,0,0,$thumb_w,$thumb_h,$old_x,$old_y);
imagejpeg($dst_img,$filename);
header("Content-type: image/jpg");
imagejpeg($dst_img);
imagedestroy($dst_img);
imagedestroy($src_img);
}
# adjust if you use
#your definition in xhelpers.php should look like:
#define ('DF_IMAGE','concat("http://img.example.com/cache/",`feed_id`,"/",`items_id`,".jpg")');
if ( preg_match("#.*imgcache/([0-9]+)/([0-9]+).jpg#",$_SERVER['REQUEST_URI'],$m) ) {
$dir='img/'.$m[1];
if ( ! is_dir($dir) ) { mkdir ($dir,0755,true); }
$img=$dir.'/'.$m[2].'.jpg';
$id=(int)$m[2];
$feed_q="select image from $db_table where items_id = $id limit 1";
$_feeds=mysql_query($feed_q,$_resource);
$p=mysql_result($_feeds,0);
if ( $p ) {
createthumb($p,"$img",216,216);
exit;
}
}
function createthumb($name,$filename,$new_w,$new_h)
{
$src_img=false;
$name=str_replace(array('[',']',' ','&'),array('%5B','%5D','%20','&'),$name);
$src_img=imagecreatefromstring(file_get_contents($name));
if ( ! $src_img ) {
if (preg_match("/(jpg|jpeg)$/i",$name)){
$src_img=imagecreatefromjpeg($name);
}
if (preg_match("/gif$/i",$name)){
$src_img=imagecreatefromgif($name);
}
if (preg_match("/png$/i",$name)){
$src_img=imagecreatefrompng($name);
}
}
if ( ! $src_img ) {
return;
#or use local image as base
}
$old_x=imageSX($src_img);
$old_y=imageSY($src_img);
if ($old_x > $old_y)
{
$thumb_w=$new_w;
$thumb_h=$old_y*($new_h/$old_x);
}
if ($old_x < $old_y)
{
$thumb_w=$old_x*($new_w/$old_y);
$thumb_h=$new_h;
}
if ($old_x == $old_y)
{
$thumb_w=$new_w;
$thumb_h=$new_h;
}
$d_h=$thumb_h > 216?216:$thumb_h;
$dst_img=ImageCreateTrueColor($thumb_w,$d_h);
imagecopyresampled($dst_img,$src_img,0,0,0,0,$thumb_w,$thumb_h,$old_x,$old_y);
imagejpeg($dst_img,$filename);
header("Content-type: image/jpg");
imagejpeg($dst_img);
imagedestroy($dst_img);
imagedestroy($src_img);
}
Je behoudt de berekening, die een image maakt van max 250px.
En dan merge je die afbeelding met een witte image van 250*250
Bedankt voor je snelle reactie.
Hoe gaat dat in zijn werk?
(in het voorbeeld staat overigens een max. van 216x216px)
Maar kijk hier eens:
http://php.net/manual/en/image.examples-watermark.php
Qua principe lijkt het wat op een watermerk.
Dus de basis-image is een wit vlak; het watermerk is de image die jouw code aanmaakt: $dst_img
Je moet dan nog berekenen op welke pixel de hoek van de image moet komen
(canvas_width - image_width) / 2
of zo.
Gewijzigd op 24/10/2012 15:34:35 door Kris Peeters
Helaas heb ik zelf weinig kennis van PHP (ben een designer, en frontend ontwerper)
Wellicht dat iemand hier wat aan heeft?
Dit moet hetzelfde doen:
function resize($imagePath,$opts=null){
$imagePath = urldecode($imagePath);
# start configuration
$cacheFolder = './cache/'; # path to your cache folder, must be writeable by web server
$remoteFolder = $cacheFolder.'remote/'; # path to the folder you wish to download remote images into
$defaults = array('crop' => false, 'scale' => 'false', 'thumbnail' => false, 'maxOnly' => false,
'canvas-color' => 'transparent', 'output-filename' => false,
'cacheFolder' => $cacheFolder, 'remoteFolder' => $remoteFolder, 'quality' => 90, 'cache_http_minutes' => 20);
$opts = array_merge($defaults, $opts);
$cacheFolder = $opts['cacheFolder'];
$remoteFolder = $opts['remoteFolder'];
$path_to_convert = 'convert'; # this could be something like /usr/bin/convert or /opt/local/share/bin/convert
## you shouldn't need to configure anything else beyond this point
$purl = parse_url($imagePath);
$finfo = pathinfo($imagePath);
$ext = $finfo['extension'];
# check for remote image..
if(isset($purl['scheme']) && ($purl['scheme'] == 'http' || $purl['scheme'] == 'https')):
# grab the image, and cache it so we have something to work with..
list($filename) = explode('?',$finfo['basename']);
$local_filepath = $remoteFolder.$filename;
$download_image = true;
if(file_exists($local_filepath)):
if(filemtime($local_filepath) < strtotime('+'.$opts['cache_http_minutes'].' minutes')):
$download_image = false;
endif;
endif;
if($download_image == true):
$img = file_get_contents($imagePath);
file_put_contents($local_filepath,$img);
endif;
$imagePath = $local_filepath;
endif;
if(file_exists($imagePath) == false):
$imagePath = $_SERVER['DOCUMENT_ROOT'].$imagePath;
if(file_exists($imagePath) == false):
return 'image not found';
endif;
endif;
if(isset($opts['w'])): $w = $opts['w']; endif;
if(isset($opts['h'])): $h = $opts['h']; endif;
$filename = md5_file($imagePath);
// If the user has requested an explicit output-filename, do not use the cache directory.
if(false !== $opts['output-filename']) :
$newPath = $opts['output-filename'];
else:
if(!empty($w) and !empty($h)):
$newPath = $cacheFolder.$filename.'_w'.$w.'_h'.$h.(isset($opts['crop']) && $opts['crop'] == true ? "_cp" : "").(isset($opts['scale']) && $opts['scale'] == true ? "_sc" : "").'.'.$ext;
elseif(!empty($w)):
$newPath = $cacheFolder.$filename.'_w'.$w.'.'.$ext;
elseif(!empty($h)):
$newPath = $cacheFolder.$filename.'_h'.$h.'.'.$ext;
else:
return false;
endif;
endif;
$create = true;
if(file_exists($newPath) == true):
$create = false;
$origFileTime = date("YmdHis",filemtime($imagePath));
$newFileTime = date("YmdHis",filemtime($newPath));
if($newFileTime < $origFileTime): # Not using $opts['expire-time'] ??
$create = true;
endif;
endif;
if($create == true):
if(!empty($w) and !empty($h)):
list($width,$height) = getimagesize($imagePath);
$resize = $w;
if($width > $height):
$resize = $w;
if(true === $opts['crop']):
$resize = "x".$h;
endif;
else:
$resize = "x".$h;
if(true === $opts['crop']):
$resize = $w;
endif;
endif;
if(true === $opts['scale']):
$cmd = $path_to_convert ." ". escapeshellarg($imagePath) ." -resize ". escapeshellarg($resize) .
" -quality ". escapeshellarg($opts['quality']) . " " . escapeshellarg($newPath);
else:
$cmd = $path_to_convert." ". escapeshellarg($imagePath) ." -resize ". escapeshellarg($resize) .
" -size ". escapeshellarg($w ."x". $h) .
" xc:". escapeshellarg($opts['canvas-color']) .
" +swap -gravity center -composite -quality ". escapeshellarg($opts['quality'])." ".escapeshellarg($newPath);
endif;
else:
$cmd = $path_to_convert." " . escapeshellarg($imagePath) .
" -thumbnail ". (!empty($h) ? 'x':'') . $w ."".
(isset($opts['maxOnly']) && $opts['maxOnly'] == true ? "\>" : "") .
" -quality ". escapeshellarg($opts['quality']) ." ". escapeshellarg($newPath);
endif;
$c = exec($cmd, $output, $return_code);
if($return_code != 0) {
error_log("Tried to execute : $cmd, return code: $return_code, output: " . print_r($output, true));
return false;
}
endif;
# return cache file path
return str_replace($_SERVER['DOCUMENT_ROOT'],'',$newPath);
}
http://www.verot.net/php_class_upload.htm )
Test dit al eens uit.
Dus, als je niets aanpast, heb je nodig:
'mijn_foto.jpg' (zelfde map als index.php)
submap 'files' waarin de aangepaste foto komt.
Als je content bent met dit resultaat, kunnen we zien om dit in te bouwen bij jouw code.
Als dit soort dingen te lastig wordt, is er nog class.upload.php (te downloaden: Test dit al eens uit.
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
// error_reporting(E_ALL);
require_once 'class.upload.php'; // Te downloaden op: http://www.verot.net/php_class_upload_download.htm
$handle = new upload('mijn_foto.jpg'); // bij het uploaden kan je als parameter bv $_FILES['image_field'] invullen
if ($handle->uploaded) {
$handle->image_resize = true;
$handle->image_y = 250;
$handle->image_x = 250;
$handle->image_ratio_fill = true; // dit doet: de foto wordt zo goed mogelijk verkleind (best fit); de overtollige ruimte wordt gevuld met een kleur;
$handle->image_background_color = '#FFFFFF';
$handle->process('files/'); // parameter: de submap waar je de foto opslaat
if ($handle->processed) {
echo 'image resized';
// $handle->clean(); // Indien je dit laat uitvoeren, wordt het originele
} else {
echo 'error : ' . $handle->error;
}
}
?>
// error_reporting(E_ALL);
require_once 'class.upload.php'; // Te downloaden op: http://www.verot.net/php_class_upload_download.htm
$handle = new upload('mijn_foto.jpg'); // bij het uploaden kan je als parameter bv $_FILES['image_field'] invullen
if ($handle->uploaded) {
$handle->image_resize = true;
$handle->image_y = 250;
$handle->image_x = 250;
$handle->image_ratio_fill = true; // dit doet: de foto wordt zo goed mogelijk verkleind (best fit); de overtollige ruimte wordt gevuld met een kleur;
$handle->image_background_color = '#FFFFFF';
$handle->process('files/'); // parameter: de submap waar je de foto opslaat
if ($handle->processed) {
echo 'image resized';
// $handle->clean(); // Indien je dit laat uitvoeren, wordt het originele
} else {
echo 'error : ' . $handle->error;
}
}
?>
Dus, als je niets aanpast, heb je nodig:
'mijn_foto.jpg' (zelfde map als index.php)
submap 'files' waarin de aangepaste foto komt.
Als je content bent met dit resultaat, kunnen we zien om dit in te bouwen bij jouw code.
Bedankt voor het mee denken...
Het maakt mij eerlijk gezegt niet veel uit.
Het gaat erom dat ik een externe afbeelding uit een feed binnenhaal.
Deze afbeelding converteerd hij momenteel binnen de aangegeven marge van 250x250...
Alleen maakt hij de afbeelding in proportie ipv dat hij de overige pixels converteert naar witte pixels zodat elke afbeelding altijd 250x250 is.
De manier waarop maakt mij niet veel uit...
Maar het princiepe van bonvenstaande script is juist. :)
Zou je mij nog kunnen helpen bij het script aan te passen?
Alvast bedankt.