2010-07-21 24 views
5

J'ai été intrigué par this discussion de mise à l'échelle de l'image et j'ai ensuite découvert que le code PHP que j'utilise pour créer des vignettes à partir d'images téléchargées souffre du même problème. J'ai décidé d'essayer le correctif PHP posté vers le bas (conversion de gamma de 2.2 à 1.0, redimensionnement de l'image, conversion de gamma de 1.0 à 2.2). Cela fonctionne pour résoudre le problème noté dans l'article, mais cette modification du code a l'effet secondaire regrettable d'éliminer la transparence du canal alpha PNG.PHP GD2: comment maintenir la transparence du canal alpha et corriger le gamma

Voici le code que j'ai avec la correction gamma en place.

<?php 
$image = imagecreatefrompng($source_file); 
$resized_image = imagecreatetruecolor($new_width, $new_height); 
imagealphablending($resized_image, false); 
imagesavealpha($resized_image, true); 
imagegammacorrect($image, 2.2, 1.0); 
imagecopyresampled($resized_image, $image, 0, 0, 0, 0, $new_width, $new_height, $image_width, $image_height); 
imagegammacorrect($resized_image, 1.0, 2.2); 
imagepng($resized_image, $dest_file); 
?> 

Quelqu'un sait comment redimensionner l'image, en utilisant l'astuce de correction gamma, tout en maintenant la transparence du canal alpha de l'image originale?

Modifier

exemples d'images:

  1. fichier original - PNG avec transparence du canal alpha
  2. fichier redimensionné avec les appels de la fonction imagegammacorrect() en commentaire
  3. fichier redimensionné à la fois imagegammacorrect() appels de fonction en place

Vous pouvez voir que La transparence est bonne jusqu'à ce que vous essayez de corriger le gamma. (Meilleure façon de voir la transparence travaille ci-dessous est d'inspecter l'étiquette de paragraphe enroulé autour des images et ajouter un arrière-plan:. Noir, son attribut de style via Firebug ou similaire)

original image http://ender.hosting.emarketsouth.com/images/test-image.png no gamma correction http://ender.hosting.emarketsouth.com/images/test-image-resized-no-gamma.png gamma corrected - no transparency http://ender.hosting.emarketsouth.com/images/test-image-resized.png

Répondre

2

Voici du code qui fonctionne. Fondamentalement, il sépare le canal alpha, redimensionne l'image en utilisant gamma correct, redimensionne le canal alpha sans gamma correct, puis copie sur le canal alpha à l'image redimensionnée qui a été faite avec gamma correct. Je pense que la fonction imagegammacorrect() a un bug. Peut-être que gamma ne s'applique qu'à RGB et que GD essaie de faire le même calcul sur le canal alpha? La théorie des couleurs n'est pas mon fort.

Quoi qu'il en soit, voici le code. Malheureusement, je ne pouvais pas trouver un meilleur moyen de séparer les canaux que de faire une boucle sur les pixels un par un. Eh bien ...

<?php 
// Load image 
$image = imagecreatefrompng('test-image.png'); 

// Create destination 
$resized_image = imagecreatetruecolor(100, 100); 
imagealphablending($resized_image, false); // Overwrite alpha 
imagesavealpha($resized_image, true); 

// Create a separate alpha channel 
$alpha_image = imagecreatetruecolor(200, 200); 
imagealphablending($alpha_image, false); // Overwrite alpha 
imagesavealpha($alpha_image, true); 

for ($x = 0; $x < 200; $x++) { 
    for ($y = 0; $y < 200; $y++) { 
     $alpha = (imagecolorat($image, $x, $y) >> 24) & 0xFF; 
     $color = imagecolorallocatealpha($alpha_image, 0, 0, 0, $alpha); 
     imagesetpixel($alpha_image, $x, $y, $color); 
    } 
} 

// Resize image to destination, using gamma correction 
imagegammacorrect($image, 2.2, 1.0); 
imagecopyresampled($resized_image, $image, 0, 0, 0, 0, 100, 100, 200, 200); 
imagegammacorrect($resized_image, 1.0, 2.2); 

// Resize alpha channel 
$alpha_resized_image = imagecreatetruecolor(200, 200); 
imagealphablending($alpha_resized_image, false); 
imagesavealpha($alpha_resized_image, true); 

imagecopyresampled($alpha_resized_image, $alpha_image, 0, 0, 0, 0, 100, 100, 200, 200); 

// Copy alpha channel back to resized image 
for ($x = 0; $x < 100; $x++) { 
    for ($y = 0; $y < 100; $y++) { 
     $alpha = (imagecolorat($alpha_resized_image, $x, $y) >> 24) & 0xFF; 
     $rgb = imagecolorat($resized_image, $x, $y); 
     $r = ($rgb >> 16) & 0xFF; 
     $g = ($rgb >> 8) & 0xFF; 
     $b = $rgb & 0xFF; 
     $color = imagecolorallocatealpha($resized_image, $r, $g, $b, $alpha); 
     imagesetpixel($resized_image, $x, $y, $color); 
    } 
} 

imagepng($resized_image, 'test-image-scaled.png'); 
?> 

Remplacer les valeurs codées en dur avec des variables bien sûr ... Et voici le résultat que je me utiliser votre image et mon code:

Resized image http://www.jejik.com/sander/test-image-scaled.png

+0

intéressant, je vais devoir passer du temps avec ça demain quand je serai de retour au bureau :) –

+0

eu un petit refactoring à faire pour pouvoir le combiner avec mon code existant, mais à la fin cela fonctionne très bien. Très appréciée! –

-1

Il y a un problème avec imagecopyresampled() et la transparence. Jetez un oeil à this comment on php.net pour une solution possible.

+0

non, la transparence est préservé sans aucun problème lorsque je supprime les appels de la fonction imagegammacorrect(). http://stackoverflow.com/questions/313070/png-transparency-with-php/313103#313103 a aidé avec cela. –

+0

Ah, un défi alors! :-D Voir ma nouvelle réponse. –