Può PNG trasparenza dell'immagine di essere conservato quando si utilizza PHP GDlib imagecopyresampled?

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

Domanda

Il seguente snippet di codice PHP utilizza GD per ridimensionare un browser caricato da PNG a 128x128.Funziona alla grande, tranne che le aree trasparenti dell'immagine originale sono stati sostituiti con un colore a tinta unita - nero nel mio caso.

Anche se imagesavealpha è impostato, qualcosa non è abbastanza di destra.

Qual è il modo migliore per preservare la trasparenza nel ricampiona immagine?

$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 );
È stato utile?

Soluzione

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

lo ha fatto per me.Grazie ceejayoz.

nota, l'immagine di destinazione esigenze alfa impostazioni, non l'immagine di origine.

Edit:sostituzione completa di codice.Vedere anche risposte di sotto e i loro commenti.Questo non è garantito per essere perfetta in qualsiasi modo, ma ha fatto realizzare le mie esigenze al 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 );

Altri suggerimenti

Perché non si fanno le cose così complicate?il seguente è quello che io uso e fino ad ora ha fatto il lavoro per me.

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

Credo che questo dovrebbe fare il trucco:

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

edit: Qualcuno in PHP docs crediti imagealphablending dovrebbe essere vero, non falso.YMMV.

Un'aggiunta che potrebbe aiutare alcune persone:

È possibile alternare imagealphablending durante la creazione dell'immagine.Ho il caso specifico che ho bisogno di questo, ho voluto unire alcuni semi-PNG trasparenti su uno sfondo trasparente.

Prima si imposta imagealphablending false e riempire appena creato la vera immagine a colori, con un colore trasparente.Se imagealphablending fosse vero, non sarebbe successo nulla, perché il riempimento trasparente si sarebbe fusa con il nero di sfondo predefinito e risultato in nero.

Poi si passa imagealphablending vero e aggiungere alcune immagini in formato PNG tela, lasciando alcuni di sfondo visibile (ie.non riempire l'intera immagine).

Il risultato è un'immagine con uno sfondo trasparente e diversi combinato le immagini PNG.

Ho fatto una funzione per il ridimensionamento dell'immagine, come JPEG/GIF/PNG con copyimageresample e le immagini PNG di mantenere ancora c'trasparenza:

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

Suppongo che questo potrebbe fare il trucco:

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

Il rovescio della medaglia è che l'immagine sarà essere spogliato di tutti il 100% dei pixel verdi.Comunque, spero che aiuta :)

Per quanto riguarda il mantenere la trasparenza, allora sì come detto in altri post imagesavealpha() deve essere impostato a true, per usare l'alpha bandiera imagealphablending() deve essere impostato a false, altrimenti non funziona.

Inoltre ho notato due cose minori nel codice:

  1. Non c'è bisogno di chiamare getimagesize() per ottenere la larghezza/altezza imagecopyresmapled()
  2. Il $uploadWidth e $uploadHeight dovrebbe essere -1 il valore, in quanto le cordinate inizia a 0 e non 1, e , quindi, anche la copia in un vuoto di pixel.Sostituire con: imagesx($targetImage) - 1 e imagesy($targetImage) - 1, relativily dovrebbe fare :)

Ecco la mia totale di codice di test.A me funziona

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

Prestare attenzione alla fonte dell'immagine width e height valori che sono passati imagecopyresampled funzione.Se sono più grandi di sorgente effettiva dimensione dell'immagine, il resto dell'area dell'immagine sarà riempito con il colore nero.

Ho unito le risposte da ceejayoz e Cheekysoft, che ha dato il risultato migliore per me.Senza imagealphablending() e imagesavealpha() l'immagine non è chiara:

$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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top