45 votes

Comment redimensionner des pngs avec transparence en PHP ?

J'essaie de redimensionner des pngs avec des fonds transparents en PHP et les exemples de code que j'ai trouvés en ligne ne fonctionnent pas pour moi. Voici le code que j'utilise, les conseils seront très appréciés !

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

Mise à jour Par "ne fonctionne pas", je voulais dire que la couleur de fond devient noire lorsque je redimensionne les pngs.

0 votes

Que voulez-vous dire par les exemples qui ne fonctionnent pas pour vous ?

83voto

Dycey Points 1366

D'après ce que je peux dire, vous devez régler le mode de mélange sur false et le drapeau du canal alpha à true avant vous faites l'imagecolorallocatealpha()

<?php
/**
 * https://stackoverflow.com/a/279310/470749
 * 
 * @param resource $image
 * @param int $newWidth
 * @param int $newHeight
 * @return resource
 */
public function getImageResized($image, int $newWidth, int $newHeight) {
    $newImg = imagecreatetruecolor($newWidth, $newHeight);
    imagealphablending($newImg, false);
    imagesavealpha($newImg, true);
    $transparent = imagecolorallocatealpha($newImg, 255, 255, 255, 127);
    imagefilledrectangle($newImg, 0, 0, $newWidth, $newHeight, $transparent);
    $src_w = imagesx($image);
    $src_h = imagesy($image);
    imagecopyresampled($newImg, $image, 0, 0, 0, 0, $newWidth, $newHeight, $src_w, $src_h);
    return $newImg;
}
?>

UPDATE : Ce code ne fonctionne que sur un fond transparent avec opacité = 0. Si votre image a 0 < opacité < 100, elle sera sur fond noir.

0 votes

La réponse n'avait rien à voir, mais c'est la façon correcte de redimensionner avec la transparence.

0 votes

C'est définitivement le BON moyen de créer/copier des images PNG transparentes.

1 votes

@RyanDoherty si cela n'était pas la réponse alors pouvez-vous fournir votre solution ?

14voto

Michael Points 21

Voici une solution finale qui fonctionne bien pour moi.

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;
}

4voto

jTresidder Points 477

Le remplissage de la nouvelle image avec une couleur transparente est également nécessaire (comme Dycey l'a codé mais j'imagine qu'il a oublié de le mentionner :)), pas seulement la sauvegarde 'stratégique' en elle-même.

IIRC, vous devez également vous assurer que les PNG sont à 24 bits, c'est-à-dire truecolor, et non à 8 bits pour éviter un comportement bogué.

4voto

sbeam Points 1196

L'exemple de Dycey devrait fonctionner, si vous nommez les choses correctement. Voici une version modifiée utilisée dans ma classe de redimensionnement d'images. Remarquez la vérification pour s'assurer que imagecolorallocatealpha() est défini, ce qui ne sera pas le cas si vous utilisez 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);
            }
        }
    }

0 votes

Tw - Largeur cible th - Hauteur cible

0 votes

Je pense que ce qu'il a sous-entendu est : tw et th sont indéfinis. Les paramètres de la fonction sont appelés $w et $h, mais imagefilledrectangle() est appelée avec $tw et $th. C'est un bug.

2voto

Alexandr Points 38

Cela ne fonctionne pas non plus pour moi :( Voici ma solution mais j'ai aussi un fond noir et l'image n'est pas 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" ?>" />

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X