Linuchs: php: Bild verkleinern

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:

png-Vorlage: Note

png-Verkleinerung: Note

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

  1. 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

    --
    Pantoffeltierchen haben keine Hobbys.
    ¯\_(ツ)_/¯
    1. 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

      1. 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

        1. 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

        2. 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

          1. 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

          2. 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

            --
            Es gibt nichts Gutes, außer man tut es!
            Das Leben selbst ist der Sinn.
            1. 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

              1. Hello Lieber Felix,

                ich wünsche Dir einen langen und erholsamen Urlaub :-)

                Glück Auf
                Tom vom Berg

                --
                Es gibt nichts Gutes, außer man tut es!
                Das Leben selbst ist der Sinn.
                1. 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

  2. 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

    --
    Es gibt nichts Gutes, außer man tut es!
    Das Leben selbst ist der Sinn.
    1. Hallo Tom,

      danke für deine klare Anleitung, die ich anderswo nirgends gefunden habe. Das Ergebnis überzeugt:

      Original 33,0 kB: lachende Note groß

      Verkleinerung 9,6 kB: lachende Note klein

      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.

      1. Hallo,

        danke für deine klare Anleitung, die ich anderswo nirgends gefunden habe. Das Ergebnis überzeugt:

        Verkleinerung 9,6 kB: lachende Note klein

        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

        --
        Kunst beginnt da, wo bei den meisten das Können aufhört.
        1. 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

          1. 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

            --
            Pantoffeltierchen haben keine Hobbys.
            ¯\_(ツ)_/¯
            1. 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

              --
              Kunst beginnt da, wo bei den meisten das Können aufhört.

              1. Das liegt daran, dass Attribute wie "sehr gewöhnungsbedürgtig", "schwierig zu erlernen" und ähnliche mich bisher davon abgehalten haben. ↩︎

              1. 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

                --
                Pantoffeltierchen haben keine Hobbys.
                ¯\_(ツ)_/¯
            2. 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

              --
              Es gibt nichts Gutes, außer man tut es!
              Das Leben selbst ist der Sinn.