2008-08-28 24 views
90

El siguiente fragmento de código PHP GD utiliza para cambiar el tamaño de un archivo PNG navegador subido a 128x128. Funciona de maravilla, excepto que las áreas transparentes en la imagen original están siendo reemplazadas por un color sólido, negro en mi caso.¿Se puede preservar la transparencia de la imagen PNG cuando se utiliza la imagencopia GDlib de PHP que se muestra?

Aunque imagesavealpha se fija, algo no está del todo bien.

Cuál es la mejor manera de preservar la transparencia en la imagen muestreada de nuevo?

$uploadTempFile = $myField[ 'tmp_name' ] 
list($uploadWidth, $uploadHeight, $uploadType) 
    = getimagesize($uploadTempFile); 

$srcImage = imagecreatefrompng($uploadTempFile);  
imagesavealpha($targetImage, true); 

$targetImage = imagecreatetruecolor(128, 128); 
imagecopyresampled($targetImage, $srcImage, 
        0, 0, 
        0, 0, 
        128, 128, 
        $uploadWidth, $uploadHeight); 

imagepng( $targetImage, 'out.png', 9); 

Respuesta

178
imagealphablending($targetImage, false); 
imagesavealpha($targetImage, true); 

lo hizo por mí. Gracias ceejayoz.

nota, la imagen de destino no necesita la imagen de origen, la configuración alfa.

Editar: código de reemplazo completo. Ver también las respuestas a continuación y sus comentarios. No se garantiza que sea perfecto de ninguna manera, pero cumplió con mis necesidades en ese momento.

$uploadTempFile = $myField[ 'tmp_name' ] 
list($uploadWidth, $uploadHeight, $uploadType) 
    = getimagesize($uploadTempFile); 

$srcImage = imagecreatefrompng($uploadTempFile); 

$targetImage = imagecreatetruecolor(128, 128); 
imagealphablending($targetImage, false); 
imagesavealpha($targetImage, true); 

imagecopyresampled($targetImage, $srcImage, 
        0, 0, 
        0, 0, 
        128, 128, 
        $uploadWidth, $uploadHeight); 

imagepng( $targetImage, 'out.png', 9); 
+2

no funcionó para mí :( – sandeepKumar

+8

He votado 3 veces esto si hubiera podido –

+2

wow, funcionó como un amistoso gracias :-) –

9

Creo que esto debe hacer el truco:

$srcImage = imagecreatefrompng($uploadTempFile); 
imagealphablending($srcImage, false); 
imagesavealpha($srcImage, true); 

edición: Alguien en la documentación de PHP afirma imagealphablending debería ser cierto, no es falso. YMMV.

+2

Utilizando 'imagealphablending' con verdadero o falso siempre obtengo un fondo negro. – aesede

+0

PHP7 - Funcionando para mí – Yehonatan

+0

Jugado con él (PHP 7.x): PNG: imagealphablending ($ targetImage, false); // si es verdadero en PNG: fondo negro GIF: imagealphablending ($ targetImage, true); // si es falso en GIF: fondo negro – Jonny

2

Recalificación la transparencia preservar, al igual que entonces sí se dice en otras imagesavealpha mensajes() tiene que tener el valor true, para utilizar el imagealphablending bandera alfa() se debe establecer en falso de lo contrario no funciona.

También vi a dos cosas de menor importancia en su código:

  1. No es necesario llamar getimagesize() para obtener el ancho/altura de imagecopyresmapled()
  2. El $uploadWidth y $uploadHeight debe ser -1 el valor, ya las cordinates comienza a 0 y no 1, por lo que sería copiarlos en un píxel vacío. Sustituyéndolo por: imagesx($targetImage) - 1 y imagesy($targetImage) - 1, relativily debe hacer :)
21

¿Por qué hace las cosas tan complicadas? Lo siguiente es lo que uso y hasta ahora me ha hecho el trabajo.

$im = ImageCreateFromPNG($source); 
$new_im = imagecreatetruecolor($new_size[0],$new_size[1]); 
imagecolortransparent($new_im, imagecolorallocate($new_im, 0, 0, 0)); 
imagecopyresampled($new_im,$im,0,0,0,0,$new_size[0],$new_size[1],$size[0],$size[1]); 
+0

Funcionó maravillosamente para mí ... Small n funciona perfectamente ... – user1589754

+0

No funcionó, todavía tengo fondo negro con esta imagen: http://www.seomofo.com/downloads/new-google-logo-knockoff. png – aesede

+1

gracias ha funcionado después de tanto googlear –

4

supongo que esto podría hacer el truco:

$uploadTempFile = $myField[ 'tmp_name' ] 
list($uploadWidth, $uploadHeight, $uploadType) 
    = getimagesize($uploadTempFile); 

$srcImage = imagecreatefrompng($uploadTempFile); 

$targetImage = imagecreatetruecolor(128, 128); 

$transparent = imagecolorallocate($targetImage,0,255,0); 
imagecolortransparent($targetImage,$transparent); 
imagefilledrectangle($targetImage,0,0,127,127,$transparent); 

imagecopyresampled($targetImage, $srcImage, 
        0, 0, 
        0, 0, 
        128, 128, 
        $uploadWidth, $uploadHeight); 

imagepng( $targetImage, 'out.png', 9); 

La desventaja es que la imagen va a ser despojado de cada 100% de píxeles verdes. De todos modos, espero que ayude :)

+0

Si establece un color extremadamente feo que casi no usaría ninguna imagen, puede ser muy útil. – Cory

+1

@cory color extremadamente feo? –

+1

La respuesta aceptada no funcionó para mí. El uso de esta respuesta con 'imagecreate (...)' funcionó bien. Usted crea una imagen, que se llena con el primer color que asigna. Luego, configura ese color como transparente. Si alphablending se establece en verdadero para la imagen de destino, ambas imágenes se fusionarán y la transparencia funcionará correctamente. – Sumurai8

9

Una adición que podrían ayudar a algunas personas:

Es posible alternar imagealphablending mientras que la construcción de la imagen. En el caso específico que necesitaba esto, quería combinar PNG semitransparentes sobre un fondo transparente.

Primero establece imagealphablending en falso y completa la imagen de color verdadero recién creada con un color transparente. Si imagealphablending fuera cierto, no pasaría nada porque el relleno transparente se fusionaría con el fondo negro predeterminado y el resultado sería negro.

Luego, alternar imagealphablending con verdadero y agregar algunas imágenes PNG al lienzo, dejando visible parte del fondo (es decir, sin llenar toda la imagen).

El resultado es una imagen con un fondo transparente y varias imágenes PNG combinadas.

+0

Gracias por agregar esta información adicional. Esto me estaba volviendo loco. – zaf

6

me han hecho una función para cambiar el tamaño de la imagen como JPEG/GIF/PNG con copyimageresample y PNG aún así mantener allí la transparencia:

$myfile=$_FILES["youimage"]; 

function ismyimage($myfile) { 
    if((($myfile["type"] == "image/gif") || ($myfile["type"] == "image/jpg") || ($myfile["type"] == "image/jpeg") || ($myfile["type"] == "image/png")) && ($myfile["size"] <= 2097152 /*2mb*/)) return true; 
    else return false; 
} 

function upload_file($myfile) {   
    if(ismyimage($myfile)) { 
     $information=getimagesize($myfile["tmp_name"]); 
     $mywidth=$information[0]; 
     $myheight=$information[1]; 

     $newwidth=$mywidth; 
     $newheight=$myheight; 
     while(($newwidth > 600) || ($newheight > 400)) { 
      $newwidth = $newwidth-ceil($newwidth/100); 
      $newheight = $newheight-ceil($newheight/100); 
     } 

     $files=$myfile["name"]; 

     if($myfile["type"] == "image/gif") { 
      $tmp=imagecreatetruecolor($newwidth,$newheight); 
      $src=imagecreatefromgif($myfile["tmp_name"]); 
      imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight); 
      $con=imagegif($tmp, $files); 
      imagedestroy($tmp); 
      imagedestroy($src); 
      if($con){ 
       return true; 
      } else { 
       return false; 
      } 
     } else if(($myfile["type"] == "image/jpg") || ($myfile["type"] == "image/jpeg")) { 
      $tmp=imagecreatetruecolor($newwidth,$newheight); 
      $src=imagecreatefromjpeg($myfile["tmp_name"]); 
      imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight); 
      $con=imagejpeg($tmp, $files); 
      imagedestroy($tmp); 
      imagedestroy($src); 
      if($con) { 
       return true; 
      } else { 
       return false; 
      } 
     } else if($myfile["type"] == "image/png") { 
      $tmp=imagecreatetruecolor($newwidth,$newheight); 
      $src=imagecreatefrompng($myfile["tmp_name"]); 
      imagealphablending($tmp, false); 
      imagesavealpha($tmp,true); 
      $transparent = imagecolorallocatealpha($tmp, 255, 255, 255, 127); 
      imagefilledrectangle($tmp, 0, 0, $newwidth, $newheight, $transparent); 
      imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight); 
      $con=imagepng($tmp, $files); 
      imagedestroy($tmp); 
      imagedestroy($src); 
      if($con) { 
       return true; 
      } else { 
       return false; 
      } 
     } 
    } else 
      return false; 
} 
+1

Es bastante oneroso leer todo el código para descubrir por qué se preserva la transparencia en este código sobre el código en la pregunta. – eh9

+0

Me salté estas dos líneas y funcionó: '$ transparent = imagecolorallocatealpha ($ tmp, 255, 255, 255, 127);' 'imagefilledrectangle ($ tmp, 0, 0, $ newwidth, $ newheight, $ transparente); ' –

0

Aquí está mi código total de la prueba. Funciona para mí

$imageFileType = pathinfo($_FILES["image"]["name"], PATHINFO_EXTENSION); 
$filename = 'test.' . $imageFileType; 
move_uploaded_file($_FILES["image"]["tmp_name"], $filename); 

$source_image = imagecreatefromjpeg($filename); 

$source_imagex = imagesx($source_image); 
$source_imagey = imagesy($source_image); 

$dest_imagex = 400; 
$dest_imagey = 600; 
$dest_image = imagecreatetruecolor($dest_imagex, $dest_imagey); 

imagecopyresampled($dest_image, $source_image, 0, 0, 0, 0, $dest_imagex, $dest_imagey, $source_imagex, $source_imagey); 

imagesavealpha($dest_image, true); 
$trans_colour = imagecolorallocatealpha($dest_image, 0, 0, 0, 127); 
imagefill($dest_image, 0, 0, $trans_colour); 

imagepng($dest_image,"test1.png",1); 
0

Tener en cuenta las width y height los valores de la imagen de origen que se pasan a la función imagecopyresampled. Si son más grandes que el tamaño real de la imagen fuente, el resto del área de la imagen se rellenará con un color negro.

Cuestiones relacionadas