Kann die Transparenz von PNG-Bildern erhalten bleiben, wenn PHPs GDlib imagecopyresampled verwendet wird?

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

Frage

Das folgende PHP-Code-Snippet verwendet GD, um die Größe eines vom Browser hochgeladenen PNG auf 128 x 128 zu ändern.Es funktioniert großartig, außer dass die transparenten Bereiche im Originalbild durch eine Volltonfarbe ersetzt werden – in meinem Fall Schwarz.

Wenngleich imagesavealpha eingestellt ist, stimmt etwas nicht.

Was ist der beste Weg, um die Transparenz im neu abgetasteten Bild beizubehalten?

$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 );
War es hilfreich?

Lösung

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

habe es für mich getan.Danke ceejayoz.

Beachten Sie, dass das Zielbild die Alpha-Einstellungen benötigt, nicht das Quellbild.

Bearbeiten:Vollständiger Ersatzcode.Siehe auch die Antworten unten und ihre Kommentare.Es kann nicht garantiert werden, dass es in irgendeiner Weise perfekt ist, aber es erfüllte meine damaligen Anforderungen.

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

Andere Tipps

Warum machen Sie die Dinge so kompliziert?Das Folgende ist, was ich verwende, und bis jetzt hat es die Arbeit für mich erledigt.

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

Ich glaube, das sollte den Zweck erfüllen:

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

bearbeiten: Jemand in den PHP-Dokumenten behauptet imagealphablending sollte wahr sein, nicht falsch.YMMV.

Eine Ergänzung, die einigen Leuten helfen könnte:

Es ist möglich, das Bild-Alphablending beim Erstellen des Bildes umzuschalten.In dem konkreten Fall, dass ich das brauchte, wollte ich einige halbtransparente PNGs auf einem transparenten Hintergrund kombinieren.

Zuerst setzen Sie imagealphablending auf false und füllen das neu erstellte Echtfarbenbild mit einer transparenten Farbe.Wenn Imagealphablending wahr wäre, würde nichts passieren, da die transparente Füllung mit dem schwarzen Standardhintergrund verschmelzen würde und zu Schwarz führen würde.

Dann schalten Sie imagealphablending auf „true“ um und fügen der Leinwand einige PNG-Bilder hinzu, wobei ein Teil des Hintergrunds sichtbar bleibt (d. h.füllt nicht das gesamte Bild aus).

Das Ergebnis ist ein Bild mit transparentem Hintergrund und mehreren kombinierten PNG-Bildern.

Ich habe eine Funktion zum Ändern der Bildgröße wie JPEG/GIF/PNG mit erstellt copyimageresample und PNG-Bilder behalten weiterhin ihre Transparenz:

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

Ich nehme an, dass dies den Zweck erfüllen könnte:

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

Der Nachteil besteht darin, dass alle 100 % grünen Pixel aus dem Bild entfernt werden.Ich hoffe jedenfalls, dass es hilft :)

Wenn ich die Transparenz beibehalte, dann ja, wie in anderen Beiträgen angegeben, muss imagesavealpha() auf true gesetzt werden, um das Alpha-Flag zu verwenden, muss imagealphablending() auf false gesetzt werden, sonst funktioniert es nicht.

Außerdem sind mir in Ihrem Code zwei Kleinigkeiten aufgefallen:

  1. Sie müssen nicht anrufen getimagesize() um die Breite/Höhe zu erhalten imagecopyresmapled()
  2. Der $uploadWidth Und $uploadHeight sollte sein -1 der Wert, da die Koordinaten bei beginnen 0 und nicht 1, also würde es sie in ein leeres Pixel kopieren.Ersetzen durch: imagesx($targetImage) - 1 Und imagesy($targetImage) - 1, sollte relativerweise reichen :)

Hier ist mein gesamter Testcode.Für mich geht das

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

Achten Sie auf das Quellbild width Und height Werte, an die übergeben werden imagecopyresampled Funktion.Wenn sie größer als die tatsächliche Quellbildgröße sind, wird der Rest des Bildbereichs mit schwarzer Farbe gefüllt.

Ich habe die Antworten von ceejayoz und Cheekysoft kombiniert, was für mich das beste Ergebnis lieferte.Ohne imagealphablending() und imagesavealpha() ist das Bild nicht klar:

$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);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top