Deutsch English
Programmierung Read this post in English

PNG-Transparenzen erhalten mit GD Lib

Halbtransparentes PNG

Neulich mußte ich eine PHP-Funktion schreiben, die mittels GD Lib aus einem Bild verschieden große Vorschaubilder generiert. Dabei ärgerte ich mich ziemlich lange mit semi-transparenten PNG-Grafiken herum. Im Internet fand ich zwar viele Tips, die schon in die richtige Richtung wiesen, aber eine wirklich vollständige und saubere Lösung konnte ich nicht auftreiben. Oft wurde auch die ach so große Wichtigkeit der Funktionen imagealphablending() und imagesavealpha() betont, die – wie sich herausstellte – für meine Zwecke vollkommen bedeutungslos waren.
Nun ja, wie immer halte ich die Lösung hier fest, falls jemand anders irgendwann einmal ebenso verzweifelt danach sucht wie ich – oder falls ich sie mal vergesse. ;) Der hübsche rote Punkt hier rechts soll zur Veranschaulichung dienen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$filename = "rotverlauf.png";
 
$oldimg = imagecreatefrompng($filename);
 
$oldwidth = imagesx($oldimg);
$oldheight = imagesy($oldimg);
$newwidth = $oldwidth/2;
$newheight = $oldheight/2;
 
$newimage = imagecreate($newwidth, $newheight);
$color = imagecolorallocatealpha($newimage, 0, 0, 0, 127);
imagefill($newimage, 0, 0, $color);
 
imagecopyresampled($newimage, $oldimg, 0, 0, 0, 0, $newwidth, $newheight, $oldwidth, $oldheight);

Der Trick besteht darin, zuerst ein neues Bild ($newimage) zu erstellen und dieses mit einer transparenten Hintergrundfarbe ($color) zu füllen. Wenn man dort nun das Originalbild mithilfe von imagecopyresampled() hineinkopiert, bleibt die Transparenz erhalten.
Das Beispielscript reduziert den roten Punkt auf die Hälfte seiner Größe. Das Ergebnis ist links zu sehen.

Nun hatte ich allerdings noch ein weiteres Problem: Ich wollte die Thumbnails von PNG-Grafiken auch im JPEG-Format speichern, sie also z. B. über einen weißen oder schwarzen Hintergrund legen, wobei aber der Farbverlauf natürlich wieder erhalten bleiben sollte. Nach einigen Fehlversuchen stellte sich die Lösung eigentlich als sehr einfach heraus. ;) Man muß nur die Funktion imagecreate() durch imagecreatetruecolor() und imagecolorallocatealpha() durch imagecolorallocate() ersetzen. Also:

10
11
$newimage = imagecreatetruecolor($newwidth, $newheight);
$color = imagecolorallocate($newimage, 255, 255, 255);

Wie man sieht, habe ich als Hintergrundfarbe diesmal weiß (255, 255, 255) gewählt, weil es in den meisten Fällen einfach besser aussieht als schwarz.
Eigentlich hätte man imagecreatetruecolor() auch schon im ersten Beispiel bei der Erzeugung des PNGs verwenden können. Manche Server scheinen damit aber Probleme zu haben (so auch meiner), daher sollte man beim PNG zur Sicherheit lieber bei imagecreate() bleiben.
Rechts sieht man nun den fantastischen roten Kreis als JPEG.

Jetzt wo das neue Bild fertig ist, kann man es entweder als Datei speichern:

imagepng($nm, "neuer-dateiname.png"); //bzw. imagejpeg();

oder direkt ausgeben lassen:

header("Content-type: image/png"); //bzw. image/jpg
imagepng($nm); //bzw. imagejpeg();

Update (12. Oktober 2009)

Ich wurde darauf hingewiesen, daß meine Variante anscheinend auch nicht auf jedem Server richtig funktioniert. Wenn das der Fall ist, kann man noch versuchen, die Zeilen 11 und 12 durch folgendes zu ersetzen:

11
12
13
$color = imagecolorallocate($nm, 255, 255, 255);
imagefill($nm, 0, 0, $color);
imagecolortransparent($nm, $color);


Kommentare

  1. 18. August 2016
    0:47 Uhr

    Detlev flag

    Danke für diesen Post und das Update vom 12.10.2009 … es hat mein Problem gelöst !

  2. 21. Oktober 2015
    19:40 Uhr

    Joe flag

    This solution is still valid today, 2015. The only other solution is to change the image library itself to Imagmagick.

  3. 17. Oktober 2012
    13:42 Uhr

    Sergey flag

    Thanks a lot for this post!

  4. 30. Oktober 2010
    22:45 Uhr

    Fred flag

    Merci beaucoup pour ce bout de code, ca faisait des heures que je cherchais… Tu as sauvé ma nuit de sommeil !

    Thanks you very much for this piece of source code, i’ve searched for a solution about hours and hours… You saved my sleeping night !

  5. 21. Mai 2010
    11:01 Uhr

    Piotr flag

    thank you a lot for your discovery, I have searched for it for a long time,
    the key is to use imagecreate() instead of imagecreatetruecolor() for transparent png files

Kommentieren

Erlaubtes HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <p> <pre lang="" line="" escaped=""> <q cite=""> <strike> <strong> <img src="" alt="" class="" width="" height=""> | Codeschnipsel können in `backticks` gepostet werden. Beispiel: `<?php echo "Hi!"; ?>`