php png gd resize

¿Cómo cambio el tamaño de pngs con transparencia en PHP?



gd resize (9)

Aquí está el código completo que funciona para los archivos png con la preservación de la transparencia de sus imágenes.

list($width, $height) = getimagesize($filepath); $new_width = "300"; $new_height = "100"; if($width>$new_width && $height>$new_height) { $image_p = imagecreatetruecolor($new_width, $new_height); imagealphablending($image_p, false); imagesavealpha($image_p, true); $image = imagecreatefrompng($filepath); imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); imagepng($image_p,$filepath,5); }

Estoy intentando redimensionar pngs con fondos transparentes en PHP y las muestras de código que he encontrado en línea no funcionan para mí. ¡Aquí está el código que estoy usando, los consejos serán muy apreciados!

$this->image = imagecreatefrompng($filename); imagesavealpha($this->image, true); $newImage = imagecreatetruecolor($width, $height); // Make a new transparent image and turn off alpha blending to keep the alpha channel $background = imagecolorallocatealpha($newImage, 255, 255, 255, 127); imagecolortransparent($newImage, $background); imagealphablending($newImage, false); imagesavealpha($newImage, true); imagecopyresampled($newImage, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight()); $this->image = $newImage; imagepng($this->image,$filename);


Actualización Por "no funciona" Quise decir que el color de fondo cambia a negro cuando cambio el tamaño de pngs.


Aquí hay una solución final que funciona bien para mí.

function resizePng($im, $dst_width, $dst_height) { $width = imagesx($im); $height = imagesy($im); $newImg = imagecreatetruecolor($dst_width, $dst_height); imagealphablending($newImg, false); imagesavealpha($newImg, true); $transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127); imagefilledrectangle($newImg, 0, 0, $width, $height, $transparent); imagecopyresampled($newImg, $im, 0, 0, 0, 0, $dst_width, $dst_height, $width, $height); return $newImg; }


Ejemplo completo Tenga en cuenta que para algunas imágenes png que se encuentran en Internet funciona incorrectamente, pero para mi creado con photoshop funciona bien.

header(''Content-Type: image/png''); $filename = "url to some image"; $newWidth = 300; $newHeight = 300; $imageInfo = getimagesize($filename); $image = imagecreatefrompng($filename); //create source image resource imagesavealpha($image, true); //saving transparency $newImg = imagecreatetruecolor($newWidth, $newHeight); //creating conteiner for new image imagealphablending($newImg, false); imagesavealpha($newImg,true); $transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127); //seting transparent background imagefilledrectangle($newImg, 0, 0, $newWidth, $newHeight, $transparent); imagecopyresampled($newImg, $image, 0, 0, 0, 0, $newWidth, $newHeight, $imageInfo[0], $imageInfo[1]); imagepng($newImg); //printout image string


El relleno de la nueva imagen con un color transparente también se requiere (como Dycey codificó pero supongo que olvidé mencionar :)), no solo el ahorro "estratégico" por sí mismo.

IIRC, también debe asegurarse de que los PNG sean de 24 bits, es decir, color verdadero, y no de 8 bits para evitar el comportamiento defectuoso.


Ni la solución anterior funcionó para mí. Esta es la forma en que me enteré para resolver el problema.

// upload directory $upload_dir = "../uploads/"; // valid image formats $valid_formats = array("jpg", "jpeg", "png"); // maximum image size 1 mb $max_size = 1048576; // crop image width, height $nw = $nh = 800; $nw1 = $nh1 = 400; $nw3 = $nh3 = 200; $nw2 = $nh2 = 100; // checks that if upload_dir a directory/not if (is_dir($upload_dir) && is_writeable($upload_dir)) { // not empty file if (!empty($_FILES[''image''])) { // assign file name $name = $_FILES[''image''][''name'']; // $_FILES to execute all files within a loop if ($_FILES[''image''][''error''] == 4) { $message = "Empty FIle"; } if ($_FILES[''image''][''error''] == 0) { if ($_FILES[''image''][''size''] > $max_size) { echo "E-Image is too large!<br>"; $_SESSION[''alert''] = "Image is too large!!"; } else if (!in_array(pathinfo($name, PATHINFO_EXTENSION), $valid_formats)) { $_SESSION[''alert''] = "This image is not a valid image format!!"; echo "E-This image is not a valid image format<br>"; } else if (file_exists($upload_dir . $name)) { $_SESSION[''alert''] = "Image already exists!!"; echo "E-Image already exists<br>"; } else { // No error found! Move uploaded files $size = getimagesize($_FILES[''image''][''tmp_name'']); $x = (int) $_POST[''x'']; $y = (int) $_POST[''y'']; $w = (int) $_POST[''w''] ? $_POST[''w''] : $size[0]; $h = (int) $_POST[''h''] ? $_POST[''h''] : $size[1]; // path for big image $big_image_path = $upload_dir . "big/" . $name; // medium image path $medium_image_path = $upload_dir . "medium/" . $name; // small image path $small_image_path = $upload_dir . "small/" . $name; // check permission if (!is_dir($upload_dir . "big/") && !is_writeable($upload_dir . "big/")) { mkdir($upload_dir . "big/", 0777, false); } if (!is_dir($upload_dir . "medium/") && !is_writeable($upload_dir . "medium/")) { mkdir($upload_dir . "medium/", 0777, false); } if (!is_dir($upload_dir . "small/") && !is_writeable($upload_dir . "small/")) { mkdir($upload_dir . "small/", 0777, false); } // image raw data from form $data = file_get_contents($_FILES["image"]["tmp_name"]); // create image $vImg = imagecreatefromstring($data); //create big image $dstImg = imagecreatetruecolor($nw, $nh); imagealphablending($dstImg, false); $trans_colour = imagecolorallocatealpha($dstImg, 0, 0, 0, 127); imagefilledrectangle($dstImg, 0, 0, $w, $h, $trans_colour); imagesavealpha($dstImg, true); imagecopyresampled($dstImg, $vImg, 0, 0, $x, $y, $nw, $nh, $w, $h); imagepng($dstImg, $big_image_path); //create medium thumb $dstImg1 = imagecreatetruecolor($nw1, $nh1); imagealphablending($dstImg1, false); $trans_colour1 = imagecolorallocatealpha($dstImg1, 0, 0, 0, 127); imagefilledrectangle($dstImg1, 0, 0, $w, $h, $trans_colour1); imagesavealpha($dstImg1, true); imagecopyresampled($dstImg1, $vImg, 0, 0, $x, $y, $nw1, $nh1, $w, $h); imagepng($dstImg1, $medium_image_path); // create smallest thumb $dstImg2 = imagecreatetruecolor($nw2, $nh2); imagealphablending($dstImg2, false); $trans_colour2 = imagecolorallocatealpha($dstImg2, 0, 0, 0, 127); imagefilledrectangle($dstImg2, 0, 0, $w, $h, $trans_colour2); imagesavealpha($dstImg2, true); imagecopyresampled($dstImg2, $vImg, 0, 0, $x, $y, $nw2, $nh2, $w, $h); imagepng($dstImg2, $small_image_path); /* * Database insertion */ $sql = "INSERT INTO tbl_inksand_product_gallery (" . "Product_Id,Gallery_Image_Big,Gallery_Image_Medium,Gallery_Image_Thumb," . "Gallery_Status,Created_By,Created_Datetime" . ") VALUES (" . "''{$Product_Id}'',''{$big_image_path}'',''{$medium_image_path}'',''{$small_image_path}''," . "''A'',''$Created_By'',''{$time}''" . ")"; db_query($sql); if (db_affected_rows() == 1) { if (imagedestroy($dstImg)) { $_SESSION[''success''] = "Image uploaded successfully."; echo "S-Image uploaded successfully<br>"; } else { $_SESSION[''alert''] = "Image not uploaded!!"; echo "S-Image not uploaded"; } } else { $_SESSION[''alert''] = "Error in uploading image!!"; echo "E-Error in uploading image!!"; } } } } } else { mkdir($upload_dir, 0777); }


Por lo que puedo decir, necesitas establecer el modo de fusión en false , y guardar el indicador de canal alfa en true antes de hacer la imagencolorallocatealpha ()

<?php $newImg = imagecreatetruecolor($nWidth, $nHeight); imagealphablending($newImg, false); imagesavealpha($newImg,true); $transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127); imagefilledrectangle($newImg, 0, 0, $nWidth, $nHeight, $transparent); imagecopyresampled($newImg, $im, 0, 0, 0, 0, $nWidth, $nHeight, $imgInfo[0], $imgInfo[1]); ?>

ACTUALIZACIÓN : Este código solo funciona en fondo transparente con opacidad = 0. Si su imagen tiene 0 <opacidad <100, será fondo negro.


Probablemente esté relacionado con las versiones más nuevas de PHP (probé con PHP 5.6), pero ahora funciona sin necesidad de llenar la imagen con un fondo transparente:

$image_p = imagecreatetruecolor(480, 270); imageAlphaBlending($image_p, false); imageSaveAlpha($image_p, true); $image = imagecreatefrompng(''image_with_some_transaprency.png''); imagecopyresampled($image_p, $image, 0, 0, 0, 0, 480, 270, 1920, 1080); imagepng($image_p, ''resized.png'', 0);


esto tampoco funciona para mí :( esta es mi solución ... pero también tengo un fondo negro y la imagen no es transparente

<?php $img_id = 153; $source = "images/".$img_id.".png"; $source = imagecreatefrompng($source); $o_w = imagesx($source); $o_h = imagesy($source); $w = 200; $h = 200; $newImg = imagecreatetruecolor($w, $h); imagealphablending($newImg, false); imagesavealpha($newImg,true); $transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127); imagefilledrectangle($newImg, 0, 0, $w, $h, $transparent); imagecopyresampled($newImg, $source, 0, 0, 0, 0, $w, $h, $o_w, $o_h); imagepng($newImg, $img_id.".png"); ?> <img src="<?php echo $img_id.".png" ?>" />


viejo hilo, pero por las dudas, el ejemplo de Dycey debería funcionar, si nombras las cosas correctamente. Aquí hay una versión modificada utilizada en mi clase de cambio de tamaño de imagen. Observe la comprobación para asegurarse de que se defina imagecolorallocatealpha (), que no será si está usando GD <2.0.8.

/** * usually when people use PNGs, it''s because they need alpha channel * support (that means transparency kids). So here we jump through some * hoops to create a big transparent rectangle which the resampled image * will be copied on top of. This will prevent GD from using its default * background, which is black, and almost never correct. Why GD doesn''t do * this automatically, is a good question. * * @param $w int width of target image * @param $h int height of target image * @return void * @private */ function _preallocate_transparency($w, $h) { if (!empty($this->filetype) && !empty($this->new_img) && $this->filetype == ''image/png'')) { if (function_exists(''imagecolorallocatealpha'')) { imagealphablending($this->new_img, false); imagesavealpha($this->new_img, true); $transparent = imagecolorallocatealpha($this->new_img, 255, 255, 255, 127); imagefilledrectangle($this->new_img, 0, 0, $tw, $th, $transparent); } } }