php: Bild verkleinern
Linuchs
- grafik
- php
0 Matthias Apsel1 TS
Moin,
Veranstaltungen in Listen zeigen das verkleinerte Logo des Veranstalters oder des Events.
Bisher konnten in meinem Projekt nur hochgeladene jpg Bilder verkleinert werden, also nichts mit transparentem Hintergrund, der für Logos notwendig wäre. Das habe ich dann einzeln mit Gimp gemacht.
Habe mich gestern einen halben Tag damit bechäftigt, auch gif und png zu schrumpfen.
Einmal drüber geschlafen, erscheint es mir unlogisch, ein neues Bild mit den gewünschten Maßen zu kreiren, den (immer?) schwarzen Hintergrund transparent zu machen und dann das vorhandene große Bild dort hineinzukopieren.
Wobei dann schwarz verstümmelt wird:
So habe ich es gemacht:
// 2019-11-15
switch ( $type ) {
case IMAGETYPE_PNG:
// erzeuge leeres schwarzes Bild in Zielgroesse 32 Bit/Pixel
$destin = imagecreatetruecolor( $new_width, $new_height );
// definiere Farbe schwarz
$black = imagecolorallocate( $destin, 0,0,0 );
// Mache den Hintergrund transparent
imagecolortransparent( $destin, $black );
// zu verkleinerndes Bild laden
$source = imagecreatefrompng( $source_pic );
// Skalieren
imagecopyresized ( $destin, $source, 0, 0, 0, 0, $new_width, $new_height, $width, $height );
// imagecopyresampled( $destin, $source, 0, 0, 0, 0, $new_width, $new_height, $width, $height ); // hat Raender um Buchstaben "berkach"
// Ausgabe qualitaet 0 (keine Kompression) .. 9
imagepng( $destin, $destination_pic, 6 );
break;
...
Geht das einfacher und qualitativ besser?
Gruß Linuchs
Hallo Linuchs,
Geht das einfacher und qualitativ besser?
Den Browser tun lassen? Bei sehr großen Logos wird es zu Lasten der Performance gehen.
Bis demnächst
Matthias
Hallo Matthias,
Den Browser tun lassen?
Keine gute Idee, dann werden bei jedem Seitenaufruf unnötig die großen Dateien übertragen anstatt die Verkleinerung.
Habe auch mit der Kompression gespielt, die Note Original hat 33,0 kB, die Verkleinerung dann 40,2 kB ohne qualitative Verbesserung:
// Ausgabe qualitaet 0 (keine Kompression) .. 9
// imagepng( $destin, $destination_pic, 6 );
imagepng( $destin, $destination_pic, 0 );
Linuchs
Lieber Linuchs,
Den Browser tun lassen?
Keine gute Idee, dann werden bei jedem Seitenaufruf unnötig die großen Dateien übertragen anstatt die Verkleinerung.
eine einmal übertragene Bilddatei kann im Browsercache vorgehalten werden. Deine live berechneten Bilder könnten das prinzipiell auch, wenn Dein PHP-Script die notwendigen Header sendet. Tut es das nicht, ist Dein Argument ganz schnell hinfällig!
Liebe Grüße
Felix Riesterer
Lieber Felix,
Deine live berechneten Bilder ...
Ich hatte vergessen zu erwähnen, dass Hochladen / Verkleinerung bei Eingabe eines Veranstaltungstermins geschieht und nur die verkleinerte Datei auf dem Server gespeichert wird.
Linuchs
Lieber Felix,
eine einmal übertragene Bilddatei kann im Browsercache vorgehalten werden. .. wenn Dein PHP-Script die notwendigen Header sendet.
Interessantes Thema. Wie könnte ich denn einer Bilddatei einen Header verpassen? Die wird doch vom Browser abgerufen ohne PHP-Beteiligung.
Edit: Ach so, die php Datei hat den Header. Wie sieht der aus?
Cache-Bilder sind insofern problematisch, weil der alte Stand angezeigt wird, auch wenn der Veranstalter ein neues hochlädt, das denselben Namen hat. Der beklagt sich dann, dass das Hochladen nicht funktioniert.
Ich weiss, ich könnte dem Dateinamen einen Zeitstempel anhängen ?t=1159
, vielleicht eine Stunde nach create-Datum der Bilddatei. Wie lange bedient sich denn ein Browser aus dem Cache?
Linuchs
Ich weiss, ich könnte dem Dateinamen einen Zeitstempel anhängen ?t=1159, vielleicht eine Stunde nach create-Datum der Bilddatei.
Noch einfacher: Ich hänge dem Bild-Dateinamen immer das Änderungsdatum an, dann kann der Cache jahrelang bestehen:
// 2019-11-16 Zeitstempel letzte Aenderung anhaengen, um alte / neue Bilder zu unterscheiden
$arr['name'] .= "?t=".date( "His", $arr['filemtime'] );
Linuchs
Hello,
eine einmal übertragene Bilddatei kann im Browsercache vorgehalten werden. .. wenn Dein PHP-Script die notwendigen Header sendet.
Guckst Du in meinen Artikel zum Thema Fileupload - Kapitel Daten wieder bereitstellen.
Du solltest beim Ausliefern per Script auch den Cache bedienen, damit die Bilder nicht jedes Mal neu ausgeliefert werden müssen.
Glück Auf
Tom vom Berg
Lieber TS,
Guckst Du in meinen Artikel zum Thema Fileupload - Kapitel Daten wieder bereitstellen.
nein, tut er nicht. @Linuchs hat doch schon erklärt, dass er die Bilddateien nicht via Script ausliefert, sondern nur beim Upload verkleinert und im Dateisystem ablegt, von wo sie vom Webserver regulär an den Browser gehen.
Liebe Grüße
Felix Riesterer
Hello Lieber Felix,
ich wünsche Dir einen langen und erholsamen Urlaub :-)
Glück Auf
Tom vom Berg
Lieber TS,
ich wünsche Dir einen langen und erholsamen Urlaub :-)
vielleicht wird's ja in den Weihnachtsferien etwas. Sommerferien und Herbstferien gingen komplett für die Schule drauf...
Liebe Grüße
Felix Riesterer
Hello K. H.,
nimm als Backgroundfarbe irgendeine abgefahrene Farbe, die garantiert nicht in der PNG-Palette enthalten ist.
Damit füllst Du das neue Bild.
Dann kopierst Du das verkleinerte und "antialiaste" neue Bild hinein.
Abschließend definierst Du die Transparenzfarbe.
So müsste es gehen.
Glück Auf
Tom vom Berg
Hallo Tom,
danke für deine klare Anleitung, die ich anderswo nirgends gefunden habe. Das Ergebnis überzeugt:
Bitte schau noch mal drüber, ob ich das optimal umgesetzt habe, wirkt doch recht umständlich:
case IMAGETYPE_PNG:
// 1. leeres Ziel-Bild (destination) anlegen in Zielgroesse und 32 Bit/Pixel
$destin = imagecreatetruecolor( $new_width, $new_height );
// 2. definiere Farbe, die kaum vorkommt und transparenter Hintergrund werden soll
$pink = imagecolorallocate( $destin, 241, 0, 255);
// 3. Ziel-Bild mit Farbe fuellen
imagefill( $destin, 0, 0, $pink);
// 4. zu verkleinerndes Quellen-Bild (source) laden
$source = imagecreatefrompng( $source_pic );
// 5. Quelle ins Ziel kopieren, dabei verkleinern
imagecopyresized ( $destin, $source, 0, 0, 0, 0, $new_width, $new_height, $width, $height );
// imagecopyresampled( $destin, $source, 0, 0, 0, 0, $new_width, $new_height, $width, $height ); // hat Raender um Buchstaben "berkach"
// 6. definierte Hintergrund-Farbe wird transparent
imagecolortransparent( $destin, $pink );
// 7. Ziel-Bild als Datei speichern. Ausgabe qualitaet 0 (keine Kompression) .. 9
imagepng( $destin, $destination_pic, 6 );
// imagepng( $destin, $destination_pic, 0 );
break;
Gruß, Linuchs
Edit: Wenn ich - auch größere- Bilder mit Gimp „aufbereite“, wähle ich zum Schluss [Bild] [Modus] [indiziert] und reduziere auf 255 Farben. Das langt sogar bei Gruppenfotos und reduziert die Dateigröße auf die Hälfte bis ein Drittel. Muss mal stöbern, ob php das auch kann.
Hallo,
danke für deine klare Anleitung, die ich anderswo nirgends gefunden habe. Das Ergebnis überzeugt:
da sehe ich noch ein paar kleine pinkfarbene Krümel. Die würden mich stören. Warum die übriggeblieben sind, ist mir aber nicht wirklich klar.
Hat das Originalbild vielleicht Alphatransparenz anstatt nur einer volltransparenten Farbe, wie du es erzeugst? Sind die paar Pixel am Rand des Notenkörpers vielleicht "fast, aber nicht ganz transparent" und bilden sich daher mit einer ganz leicht abweichenden Farbe ab?
Ciao,
Martin
Hallo Martin,
da sehe ich noch ein paar kleine pinkfarbene Krümel. Die würden mich stören.
Ja, wenn ich beim Original mit Gimp den Hintergrund weiße, krümelt da was. Ist also nicht „Schuld“ von php.
Ein vorhandenes Bild mit einem Grafik-Programm bearbeiten und freistellen ist immer wieder eine Herausforderung.
Ich habe immer wieder Rundungen, deren Hintergrund ich mit einem sichelartigen Werkzeug löschen müsste, habe aber nur eckige oder runde Werkzeuge zur Verfügung.
Linuchs
Hallo Linuchs,
Ich habe immer wieder Rundungen, deren Hintergrund ich mit einem sichelartigen Werkzeug löschen müsste, habe aber nur eckige oder runde Werkzeuge zur Verfügung.
Und manche Leute haben Zauberstäbe für die Rundungen.
Bis demnächst
Matthias
Hallo Matthias,
Ich habe immer wieder Rundungen, deren Hintergrund ich mit einem sichelartigen Werkzeug löschen müsste, habe aber nur eckige oder runde Werkzeuge zur Verfügung.
Und manche Leute haben Zauberstäbe für die Rundungen.
ähm, ja, das auch. ;-)
Aber zurück zur Grafikbearbeitung: Viele Programme bieten auch die Funktion, Konturen automatisch zu erkennen und freizustellen.
Ich kenne GIMP nicht aus eigener Anwendung[1], bin aber sehr zuversichtlich, dass der das auch bietet.
Ciao,
Martin
Das liegt daran, dass Attribute wie "sehr gewöhnungsbedürgtig", "schwierig zu erlernen" und ähnliche mich bisher davon abgehalten haben. ↩︎
Hallo Der Martin,
Aber zurück zur Grafikbearbeitung: Viele Programme bieten auch die Funktion, Konturen automatisch zu erkennen und freizustellen.
Und das Symbol dafür ist häufig der Zauberstab. https://docs.gimp.org/2.6/de/gimp-tools.html#gimp-toolbox-icons, https://docs.gimp.org/2.6/de/gimp-tool-fuzzy-select.html
Bis demnächst
Matthias
Hello,
Hallo Linuchs,
Ich habe immer wieder Rundungen, deren Hintergrund ich mit einem sichelartigen Werkzeug löschen müsste, habe aber nur eckige oder runde Werkzeuge zur Verfügung.
Und manche Leute haben Zauberstäbe für die Rundungen.
In den meisten Grafikprogrammen gibt es auch did Funktion Sprenkel entfernen
, die K.H. hier wohl gebrauchen könnte.
Die wollte ich immer schon mal mit der GD-Lib nachbauen. Das ist aber wohl die falsche Programmschicht. Dann kannst Du zwischendurch Kuchenbacken gehen.
Glück Auf
Tom vom Berg