PHP image on the fly resizing with caching, and croping

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Kevin p

kevin p

24/10/2012 14:47:46
Quote Anchor link
Beste forumleden.

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);
}
 
PHP hulp

PHP hulp

14/05/2024 00:51:05
 
Kris Peeters

Kris Peeters

24/10/2012 15:14:41
Quote Anchor link
Het is misschien wat dubbel werk, maar qua logica lijkt me het gemakkelijkste:

Je behoudt de berekening, die een image maakt van max 250px.
En dan merge je die afbeelding met een witte image van 250*250
 
Kevin p

kevin p

24/10/2012 15:17:35
Quote Anchor link
Beste Kris,

Bedankt voor je snelle reactie.

Hoe gaat dat in zijn werk?

(in het voorbeeld staat overigens een max. van 216x216px)
 
Kris Peeters

Kris Peeters

24/10/2012 15:27:15
Quote Anchor link
Ik kan het nu even niet volledig uitwerken.
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
 
Kevin p

kevin p

24/10/2012 15:39:05
Quote Anchor link
Ben wel een ander script tegengekomen.

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);

}
 
Kris Peeters

Kris Peeters

25/10/2012 12:26:13
Quote Anchor link
Als dit soort dingen te lastig wordt, is er nog class.upload.php (te downloaden: http://www.verot.net/php_class_upload.htm )

Test dit al eens uit.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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;
  }
}

?>


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.
 
Kevin p

kevin p

26/10/2012 14:11:17
Quote Anchor link
Beste Kris,

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. :)
 
Kevin p

kevin p

29/10/2012 11:23:40
Quote Anchor link
Beste Kris,

Zou je mij nog kunnen helpen bij het script aan te passen?

Alvast bedankt.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.