2010-02-26 3 views
11

J'ai un script php qui enregistre l'image originale, puis la redimensionne - une vignette et une image plus grande pour la visualisation sur le web. Cela fonctionne bien sauf avec quelques images la qualité est terrible. Il semble être enregistré avec une palette de couleur très basse. Vous pouvez voir le résultat à http://kalpaitch.com/index.php?filter=white - cliquez sur la première vignette avec le titre « blanc blanc blanc »php imagecopyresampled mauvaise qualité

Ci-dessous est le code utilisé pour le rééchantillonnage d'image:

function resizeImg($name, $extension, $size1, $size2) { 
if (preg_match('/jpg|jpeg|JPG|JPEG/',$extension)){ 
    $image = imagecreatefromjpeg($name); 
} 
if (preg_match('/gif|GIF/',$extension)){ 
    $image = imagecreatefromgif($name); 
} 

$old_width = imageSX($image); 
$old_height = imageSY($image); 
$old_aspect_ratio = $old_width/$old_height; 

if($size2 == 0){ 
    $new_aspect_ratio = $old_aspect_ratio; 
    if($old_width > $old_height){ 
     $new_width = $size1; 
     $new_height = $new_width/$old_aspect_ratio; 
    } else { 
     $new_height = $size1; 
     $new_width = $new_height * $old_aspect_ratio; 
    } 
} elseif($size2 > 0){ 
    $new_aspect_ratio = $size1/$size2; 
    //for landscape potographs 
    if($old_aspect_ratio >= $new_aspect_ratio) { 
     $x1 = round(($old_width - ($old_width * ($new_aspect_ratio/$old_aspect_ratio)))/2); 
     $old_width = round($old_width * ($new_aspect_ratio/$old_aspect_ratio)); 
     $y1 = 0; 
     $new_width = $size1; 
     $new_height = $size2; 
     //for portrait photographs 
    } else{ 
     $x1 = 0; 
     $y1 = 0; 
     $old_height = round($old_width/$new_aspect_ratio); 
     $new_width = $size1; 
     $new_height = $size2; 
    } 
} 

$new_image = imagecreatetruecolor($new_width, $new_height); 
imagecopyresampled($new_image, $image, 0, 0, $x1, $y1, $new_width, $new_height, $old_width, $old_height); 

return $new_image; 

Merci beaucoup

post-scriptum [photos ont été supprimées du serveur]

Et voici le reste du code de téléchargement:

// Move the original to the right place 
     $result = @move_uploaded_file($image['tmp_name'], $origlocation); 

     // Resize the image and save the thumbnail 
     $new_image = resizeImg($origlocation, $extension, 500, 0); 

     if (preg_match("/gif/",$extension)){ 
      imagegif($new_image, $normallocation); 
     } else { 
      imagejpeg($new_image, $normallocation); 
     } 

     // Resize the image and save the thumbnail 
     $new_image = resizeImg($origlocation, $extension, 190, 120); 

     if (preg_match("/gif/",$extension)){ 
      imagegif($new_image, $thumblocation); 
     } else { 
      imagejpeg($new_image, $thumblocation); 
     } 
+2

Pouvez-vous montrer un exemple avant-après? –

+0

Je ne suis pas 100% clair, mais il semble que certaines des images que vous obtenez sont d'une certaine taille et que votre script le redimensionne plus GRAND qu'il ne l'était à l'origine? La qualité sera terrible si vous faites cela. – Jage

+0

Non, le script redimensionnera l'image proportionnellement si une seule taille est donnée. Si deux tailles sont données, elles seront redimensionnées et le reste sera coupé sans changer le rapport d'aspect. Les images rééchantillonnées ont toujours une résolution beaucoup plus faible que l'image originale. La photo ci-dessus n'est pas l'original, ils sont à la fois la même résolution mais l'avant est sauvegardé avec photoshop et l'après est sauvegardé avec mon script. – kalpaitch

Répondre

24

La perte de qualité est en baisse non pas à imagecopyresampled(), mais à la compression JPEG. Malheureusement, les algorithmes de compression de GD ne correspondent pas à ceux de Photoshop - en fait, très peu le sont. Mais vous pouvez améliorer le résultat: le niveau de compression par défaut GD JPG est 75 de 100.

Vous pouvez augmenter la qualité en utilisant le troisième paramètre à imagejpeg() (que je suppose que vous utilisez pour la sortie finale):

imagejpeg ($new_image, null, 99); 

Jouez dans la gamme 90-100. L'image deviendra plus grande dans la taille du fichier que l'original - cela va être le prix que vous payez. Mais il devrait être possible d'atteindre une qualité comparable.

Alternativement, comme John Himmelman le dit déjà dans les commentaires, essayez d'utiliser imagepng() pour une meilleure qualité - également au prix d'une taille de fichier sensiblement plus grande, bien sûr.

+4

Comme un dernier petit point pour quiconque est curieux. J'ai changé la qualité de imagejpeg() en 99 et je repars avec une bien meilleure image. Bien que - la différence entre cela et la valeur par défaut est une augmentation de 1000% de la taille du fichier (12kb par défaut, compression de haute qualité à 110kb) – kalpaitch

+1

Juste une suggestion que je suis arrivé après avoir lu ceci. Avec mon système de miniatures, il n'est pas nécessaire que l'image miniature ait le même format que l'image originale en taille réelle, on demande à ma fonction d'utilité "quel est le fichier miniature pour cette image, et existe-t-il déjà?" Donc, si on vous demande à propos de file.jpg, il reviendra avec thumbnail_cache/file.jpg. J'ai modifié cette approche pour toujours répondre avec les vignettes au format .png, donc si on me demande à propos de fichier.jpg il revient avec thumbnail_cache/file.png et génère une vignette png. Cela évite tout souci de compression GD jpg. – Neek

1

bien, la documentation php.net dit que vous devriez avoir une image imagecreatetruecolor() pour votre dest_image si vous voulez Évitez d'utiliser seulement une palette de 255 couleurs, mais vous le faites déjà.

Je suppose qu'une alternative serait d'utiliser un outils externes tels que imagemagick avec un appel system().

+0

Oui, pas sûr que PHP est très utile. Comme vous pouvez le voir, j'ai fait une troisième image de test en utilisant imagecopyresized, ce qui est un peu mieux mais pas assez. – kalpaitch

0
function img_resize($tmpname, $size, $save_dir, $save_name, $maxisheight = 0) 
{ 
    $save_dir .= (substr($save_dir,-1) != "/") ? "/" : ""; 
    $gis = getimagesize($tmpname); 
    $type = $gis[2]; 

    switch($type) 
    { 
     case "1": $imorig = imagecreatefromgif($tmpname); break; 
     case "2": $imorig = imagecreatefromjpeg($tmpname);break; 
     case "3": $imorig = imagecreatefrompng($tmpname); break; 
     default: $imorig = imagecreatefromjpeg($tmpname); 
    } 

    $x = imagesx($imorig); 
    $y = imagesy($imorig); 

    $woh = (!$maxisheight)? $gis[0] : $gis[1] ; 
    if($woh <= $size) 
    { 
     $aw = $x; 
     $ah = $y; 
    } 
    else 
    { 
     if(!$maxisheight) 
     { 
      $aw = $size; 
      $ah = $size * $y/$x; 
     } 
     else 
     { 
      $aw = $size * $x/$y; 
      $ah = $size; 
     } 
    } 
    $im = imagecreatetruecolor($aw,$ah); 

    if (imagecopyresampled($im,$imorig , 0,0,0,0,$aw,$ah,$x,$y)) 

    if (imagejpeg($im, $save_dir.$save_name)) 

     return true; 

    else 

     return false; 

} 
2

Le rapide un sale tour est de les vignettes 1000 x 1000 pixels (ou plus) sur imagecopyresized() puis définissez la qualité JPEG à 20 ou moins imagejpeg($img, $savePath, 20);. La sortie sera généralement inférieure à 100 kb. Laissez le CSS du client effectuer le redimensionnement et les images seront rapides à charger et auront un aspect irréprochable dans les navigateurs modernes lorsqu'elles seront mises à l'échelle en taille de vignette.

Questions connexes