2010-07-21 15 views
5

Estaba intrigado por this discussion de escalado de imagen y posteriormente descubrí que el código PHP que estoy usando para crear miniaturas de imágenes cargadas sufre del mismo problema. Decidí probar la corrección PHP publicada cerca de la parte inferior (convertir gamma de 2.2 a 1.0, cambiar el tamaño de la imagen, convertir gamma de 1.0 a 2.2). Esto funciona para resolver el problema mencionado en el artículo, sin embargo, esta modificación del código tiene el desafortunado efecto secundario de noquear la transparencia del canal alfa PNG.PHP GD2: cómo mantener la transparencia del canal alfa y corregir gamma

Aquí está el código que tengo con la corrección de gamma en su lugar.

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

Alguien sabe cómo cambiar el tamaño de la imagen, empleando el truco corrección de gamma, mientras se mantiene la transparencia del canal alfa de la imagen original?

Editar

imágenes de muestra:

  1. archivo original - PNG con transparencia de canal alfa
  2. archivo cambia de tamaño con ambas imagegammacorrect llamadas de función() comentadas
  3. archivo cambia de tamaño con tanto imagegammacorrect() función llama en su lugar

Puede ver que th La transparencia está bien hasta que intentes corregir la gamma. (Forma más fácil de ver la transparencia está trabajando a continuación es para inspeccionar la etiqueta de párrafo envuelto alrededor de las imágenes y añadir un fondo:. Negro; a su atributo de estilo a través de FireBug o similares)

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

Respuesta

2

Aquí hay un código que funciona. Básicamente, separa el canal alfa, cambia el tamaño de la imagen usando gamma correcto, cambia el tamaño del canal alfa sin gamma correcto, luego copia sobre el canal alfa a la imagen redimensionada que se hizo con gamma correcto.

Supongo que la función imagegammacorrect() tiene un error. ¿Quizás la gamma solo se aplica a RGB y GD intenta hacer el mismo cálculo al canal alfa también? La teoría del color no es mi fuerte.

De todos modos, aquí está el código. Lamentablemente, no pude encontrar una mejor manera de separar los canales que recorrer los píxeles uno a uno. Oh, bueno ...

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

Reemplazar los valores codificados de forma rígida con variables, por supuesto ... Y aquí está el resultado que obtiene con su imagen y mi código:

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

+0

interesante, tendré que pasar algo de tiempo con esto mañana cuando regrese a la oficina :) –

+0

tuve que hacer una pequeña refactorización para combinar esto con mi código existente, pero al final funciona muy bien. ¡Muy apreciado! –

-1

Hay un problema con imagecopyresampled() y transparencia. Eche un vistazo a this comment on php.net para una posible solución.

+0

no, la transparencia es se conserva sin ningún problema cuando elimino las llamadas a la función imagegammacorrect(). http://stackoverflow.com/questions/313070/png-transparency-with-php/313103#313103 ayudó con eso. –

+0

¡Ah, un desafío! :-D Ver mi nueva respuesta. –

Cuestiones relacionadas