para - ¿Se puede preservar la transparencia de la imagen PNG cuando se usa la imagencopia GDlib de PHP que se muestra?
mejor formato de imagen (9)
El siguiente fragmento de código PHP usa GD para cambiar el tamaño de un PNG cargado por el navegador 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.
Aunque se establece imagesavealpha
, algo no está del todo bien.
¿Cuál es la mejor manera de preservar la transparencia en la imagen muestreada?
$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 );
¿Por qué haces 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]);
Aquí está mi código de prueba total. Esto funciona para mi
$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);
Creo que esto debería hacer el truco:
$srcImage = imagecreatefrompng($uploadTempFile);
imagealphablending($srcImage, false);
imagesavealpha($srcImage, true);
editar: alguien en los documentos de PHP afirma que imagealphablending
debe ser verdadero, no falso. YMMV.
He hecho una función para cambiar el tamaño de la imagen como JPEG / GIF / PNG con copyimageresample
y las imágenes PNG todavía mantienen su 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;
}
Preste atención a los valores de width
y height
la imagen fuente 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.
Reanudar la transparencia de conservación, entonces sí como se indica en otras publicaciones imagesavealpha () tiene que establecerse en verdadero, para usar la bandera alfa imagealphablending () debe establecerse en falso, de lo contrario no funciona.
También descubrí dos cosas menores en tu código:
- No necesita llamar a
getimagesize()
para obtener el ancho / alto deimagecopyresmapled()
- El
$uploadWidth
y$uploadHeight
deben ser-1
el valor, ya que los cordinates comienzan en0
y no en1
, por lo que los copiarían en un píxel vacío. Sustituyéndolo por:imagesx($targetImage) - 1
eimagesy($targetImage) - 1
, relativily debería hacerlo :)
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 );
El inconveniente es que la imagen se despojará de cada 100% de píxeles verdes. De todos modos, espero que ayude :)
Una adición que podría ayudar a algunas personas:
Es posible alternar imagealphablending mientras se construye 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 llena 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.
A continuación, alternar imagealphablending a verdadero y agregar algunas imágenes PNG al lienzo, dejando algo del fondo visible (es decir, sin llenar toda la imagen).
El resultado es una imagen con un fondo transparente y varias imágenes PNG combinadas.
imagealphablending( $targetImage, false );
imagesavealpha( $targetImage, true );
lo hizo por mí. Gracias ceejayoz.
tenga en cuenta que la imagen objetivo necesita la configuración alfa, no la imagen fuente.
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 );