Peut de la transparence des images PNG être préservé lors de l'utilisation de PHP GDlib imagecopyresampled?

StackOverflow https://stackoverflow.com/questions/32243

Question

Le code PHP suivant extrait de code utilise GD pour redimensionner un navigateur téléchargé PNG de 128x128 pixels.Il fonctionne très bien, sauf que les zones transparentes de l'image d'origine sont remplacés par un solide de couleur noire dans mon cas.

Même si imagesavealpha est ensemble, quelque chose n'est pas tout à fait droit.

Quelle est la meilleure façon de préserver la transparence dans l'échantillonnage de l'image?

$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 );
Était-ce utile?

La solution

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

il l'a fait pour moi.Grâce ceejayoz.

remarque, l'image de la cible a besoin de l'alpha paramètres, et non la source de l'image.

Edit:le remplacement complet de code.Voir aussi les réponses ci-dessous et leurs commentaires.Ce n'est pas garanti d'être parfait, mais n'a atteindre mes besoins du moment.

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

Autres conseils

Pourquoi avez-vous rendre les choses si compliquées?ce qui suit est ce que j'utilise et pour l'instant il a fait le travail pour moi.

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

Je crois que cela devrait faire l'affaire:

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

edit: Quelqu'un dans le PHP docs revendications imagealphablending devrait-il être vrai, de faux pas.YMMV.

Un ajout qui pourrait aider certaines personnes:

Il est possible de changer imagealphablending alors que la construction de l'image.J'ai le cas particulier que j'avais besoin de cela, je voulais combiner certaines de ces semi-transparent PNG sur fond transparent.

D'abord, vous définissez imagealphablending de faux et de remplir le nouvellement créé de véritable couleur de l'image avec une couleur transparente.Si imagealphablending était vrai, il ne se passe rien parce que le fond transparent de fusionner avec le noir en arrière-plan par défaut et le résultat dans le noir.

Puis vous mettez de imagealphablending de vrai et ajouter quelques images PNG à la toile, laissant un peu de l'arrière-plan visible (c'est à dire.ne pas remplir la totalité de l'image).

Le résultat est une image avec un fond transparent et plusieurs combinés des images PNG.

J'ai fait une fonction de redimensionnement d'image comme JPEG/GIF/PNG copyimageresample et PNG images toujours garder la transparence:

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

Je suppose que cela pourrait faire l'affaire:

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

L'inconvénient est que l'image sera dépouillé de tous 100% de pixels verts.En tout cas, espérons que cela aide :)

Reclassement de la préserver la transparence, alors oui, comme dit dans d'autres posts imagesavealpha() doivent être mis à true, pour utiliser l'alpha drapeau imagealphablending() doit être définie sur false sinon cela ne fonctionne pas.

Aussi, j'ai repéré deux petites choses dans votre code:

  1. Vous n'avez pas besoin d'appeler getimagesize() pour obtenir la largeur/hauteur de imagecopyresmapled()
  2. L' $uploadWidth et $uploadHeight devrait être -1 la valeur, depuis la cordinates commence à 0 et pas 1, serait donc de les copier dans un vide pixel.Le remplaçant par: imagesx($targetImage) - 1 et imagesy($targetImage) - 1, relativily devrait le faire :)

Voici mon code de test.Il fonctionne pour moi

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

Attention à la source de l'image width et height les valeurs qui sont passés à imagecopyresampled fonction.Si ils ne le sont plus que par la taille de l'image source, le reste de la zone de l'image sera rempli avec la couleur noire.

J'ai combiné les réponses de ceejayoz et Cheekysoft, qui a donné le meilleur résultat pour moi.Sans imagealphablending() et imagesavealpha() l'image n'est pas claire:

$img3 = imagecreatetruecolor(128, 128);
imagecolortransparent($img3, imagecolorallocate($img3, 0, 0, 0));
imagealphablending( $img3, false );
imagesavealpha( $img3, true );
imagecopyresampled($img3, $srcImage, 0, 0, 0, 0, 128, 128, $uploadWidth, $uploadHeight);
imagepng($img3, 'filename.png', 9);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top