Enrico: Selbstgebasteltes Skript zum Verkleinern von Grafiken erzeugt keine Thumbnails

Hallo,

ich habe mich jetzt an der on-the-fly-Verkleinerung von Grafiken mittels PHP versucht, wohl aber noch einige Fehler fabriziert, weil mir keine verkleinerte Grafik angezeigt wird.

Ein fertiges Framework wollte ich nicht einbinden, weil ich ansonsten ja keinen Lerneffekt habe.

Hier die Testdatei, die eine vorhandene Grafik verkleinern soll:

   $Grafik = "../IMG/FotoEnricoGross.png";

   echo '<img src="INC/Verkleinern.php?G=' . $Grafik . '&B=100">';

Und hier die Datei "Verkleinern.php", die die Verkleinerung bewerkstelligen soll:

   if (empty ($_GET))
      return 'Die Servervariable "GET" ist leer';

   if (!isset ($_GET["A"]))
      return "Du hast keine Datei angegeben";

   $Ausgangsgrafik = $_GET["A"];

   if (!file_exists ($Ausgangsgrafik))
      return 'Die Datei "' . $Ausgangsgrafik . '" wurde nicht gefunden';

   if (strtolower (pathinfo ($Ausgangsgrafik, PATHINFO_EXTENSION)) != "png")
      return 'Die Grafik "' . $Ausgangsgrafik . '" ist keine png-Datei';

   if (!isset ($_GET["B"]) && !isset ($_GET["H"]))
      return 'Die Angabe für die neue Breite oder Höhe fehlt';

   if (isset ($_GET["B"]))
      $Maximale_Breite = $_GET["B"];

   if (!((int)$Maximale_Breite === $Maximale_Breite))
      return 'Die Angabe "' . $Maximale_Breite . '" für die neue Breite ist keine Zahl';

   if ($Maximale_Breite <= 0)
      return 'Die Angabe für die neue Breite muss größer "0" sein';

   if (isset ($_GET["H"]))
      $Maximale_Hoehe = $_GET["H"];

   if (!((int)$Maximale_Hoehe === $Maximale_Hoehe))
      return 'Die Angabe "' . $Maximale_Hoehe . '" für die neue Höhe ist keine Zahl';

   if ($Maximale_Hoehe <= 0)
      return 'Die Angabe für die neue Höhe muss größer "0" sein';

   if ($Maximale_Breite && $Maximale_Hoehe)
      return "Es wird nur eine Angabe für die neue Breite oder Höhe benötigt";

   $Kopie = imagecreatefromstring (Bytes_einlesen ($Ausgangsgrafik));

   $Urspruengliche_Breite = imagesx ($Kopie);
   $Urspruengliche_Hoehe  = imagesy ($Kopie);

   if ($Maximale_Breite)
      $Faktor = $Maximale_Hoehe / $Urspruengliche_Hoehe;
   else
      if ($Maximale_Hoehe)
         $Faktor = $Maximale_Breite / $Urspruengliche_Breite;

   $Neue_Breite = round ($Urspruengliche_Breite * $Faktor);
   $Neue_Hoehe  = round ($Urspruengliche_Hoehe  * $Faktor);

   $Kopie = imagecreatefrompng ($Ausgangsgrafik);
   $Verkleinerte_Kopie = imagecreatetruecolor ($Neue_Breite, $Neue_Hoehe);
   $Transparenz = imagecolortransparent ($Kopie);

   if ($Transparenz != -1)
   {
      $Transparente_Farbe = imagecolorsforindex ($Kopie, $Transparenz);
      $Transparenz = imagecolorallocate ($Verkleinerte_Kopie, $Transparente_Farbe["red"], $Transparente_Farbe["green"], $Transparente_Farbe["blue"]);
      imagefill ($Verkleinerte_Kopie, 0, 0, $Transparenz);
      imagecolortransparent ($Verkleinerte_Kopie, $Transparenz);
   }
   else
   {
      imagealphablending ($Verkleinerte_Kopie, false);
      $Alpha = imagecolorallocatealpha ($Verkleinerte_Kopie, 0, 0, 0, 127);
      imagefill ($Verkleinerte_Kopie, 0, 0, $Alpha);
      imagesavealpha ($Verkleinerte_Kopie, true);
   }

   imagecopyresampled ($Verkleinerte_Kopie, $Kopie, 0, 0, 0, 0, $Neue_Breite, $Neue_Hoehe, $Urspruengliche_Breite, $Urspruengliche_Hoehe);

   header ("Content-type: IMAGETYPE_PNG");
   imagepng ($Verkleinerte_Kopie, null);

   function Bytes_einlesen ($url)
   {
      $curl = curl_init ($url);

      curl_setopt($curl, CURLOPT_HTTPHEADER, array("Range: bytes=0-32768"));
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

      $data = curl_exec($curl);

      curl_close($curl);

      return $data;
   }

Die Funktion "Bytes_einlesen" soll lediglich die Rohdaten der Ausgangsgrafik einlesen, so dass die Grafik nicht zuerst vollständig geladen werden muss, um deren Höhe und Breite zu ermitteln.

Ich dachte zunächst an einen Fehler bzgl. der Pfadangabe der Ausgangsgrafik. Sie existiert, relativ zur aufrufenden Datei. Für den Fall, dass die verkleinernde PHP-Datei vom Ordner "INC" ausgehend auf die Grafik zugreifen sollte, habe ich einen weiteren Verzeichnungssprung zurück festgelegt ("../IMG/FotoEnricoGross.png"), aber mit dem selben Resultat, dass mir im Browser nur ein Symbol angezeigt wird, das wohl fehlerhaft geladene Grafiken symbolisieren soll.

Könnt ihr mir bitte helfen, dass ich mein Skript funktionstüchtig zum Laufen bringe?

Und übt bitte Nachsicht, sollten euch bei meinem Code die Haare zu Berge stehen.

Kann man Code jetzt gar nicht mehr farblich hervorheben lassen, so wie es im "alten" Forum war? Irgendwie war ich zu blöd, hier auch nur annähernd eine strukturierte Ausgabe hinzubekommen ^^ Sorry dafür...

Vielen lieben Dank und Gruß, Enrico

  1. Tach!

       $Grafik = "../IMG/FotoEnricoGross.png";
       echo '<img src="INC/Verkleinern.php?G=' . $Grafik . '&B=100">';
    

    Es ist sehr ungüstig, wenn du solche relativen Pfade zulässt und nicht seitens deines Scripts den Anwender nur in ein vorher festgelegtes Verzeichnis einsperrst.

    if (empty ($_GET))
    return 'Die Servervariable "GET" ist leer';

    Diese Meldung kann kein Anwender verstehen.

    if (!isset ($_GET["A"]))
    return "Du hast keine Datei angegeben";

    Diese schon eher.

    $Ausgangsgrafik = $_GET["A"];

    if (!file_exists ($Ausgangsgrafik))
    return 'Die Datei "' . $Ausgangsgrafik . '" wurde nicht gefunden';

    Bei dieser Meldung kann der Anwender nichts weiter tun. Oder doch? Sag ihm seine Alternativen.

    if (isset ($_GET["B"]))
    $Maximale_Breite = $_GET["B"];

    if (!((int)$Maximale_Breite === $Maximale_Breite))
    return 'Die Angabe "' . $Maximale_Breite . '" für die neue Breite ist keine Zahl';

    $_GET liefert immer Strings (hier nicht zutreffende Ausnahme: Arrays mit Strings). $Maximale_Breite ist also ein String. Ein Integer ist nie typgleich zu einem String. Diese Bedingung wird (aufgrund der Negation) immer true ergeben.

    Die Funktion "Bytes_einlesen" soll lediglich die Rohdaten der Ausgangsgrafik einlesen, so dass die Grafik nicht zuerst vollständig geladen werden muss, um deren Höhe und Breite zu ermitteln.

    Höhe und Breite liefert auch getimagesize().

    Ich dachte zunächst an einen Fehler bzgl. der Pfadangabe der Ausgangsgrafik. Sie existiert, relativ zur aufrufenden Datei. Für den Fall, dass die verkleinernde PHP-Datei vom Ordner "INC" ausgehend auf die Grafik zugreifen sollte, habe ich einen weiteren Verzeichnungssprung zurück festgelegt ("../IMG/FotoEnricoGross.png"), aber mit dem selben Resultat, dass mir im Browser nur ein Symbol angezeigt wird, das wohl fehlerhaft geladene Grafiken symbolisieren soll.

    Ich weiß ja nicht, was du mit den Return-Werten der Fehlermeldungen anstellst ... aber lass mal das header ("Content-type: IMAGETYPE_PNG"); weg und ruf das Script inklusive Parameter direkt auf. Schau auch in die Quelltextansicht des Browsers.

    Kann man Code jetzt gar nicht mehr farblich hervorheben lassen, so wie es im "alten" Forum war?

    Sieht doch alles gut aus, oder hat das ein Forumsgeist korrigiert?

    dedlfix.

    1. Hallo dedlfix,

      Danke für Deine rasche Antwort.

      Es ist sehr ungüstig, wenn du solche relativen Pfade zulässt und nicht seitens deines Scripts den Anwender nur in ein vorher festgelegtes Verzeichnis einsperrst.

      Das Skript soll nur für eigene Bildergalerien verwendet werden und wird daher nur auf einen festgelegten Ordner zugreifen, der letztendlich die einzelnen Unterordner für die verschiedenen Galerien enthalten wird.

      Diese Meldung kann kein Anwender verstehen.

      Ich habe nun alle return-Meldungen entfernt, da diese selber für Fehlermeldungen gesorgt haben.

      lass mal das header ("Content-type: IMAGETYPE_PNG"); weg und ruf das Script inklusive Parameter direkt auf. Schau auch in die Quelltextansicht des Browsers.

      Jetzt funktioniert die Verkleinerung wunderbar :-)

      Die ursprüngliche Grafik besteht aus einem schwarzen Dummy mit transparentem Hintergrund und wird nun auf weißem Hintergrund im Browser dargestellt. Bedeutet dies, dass auch die Transparenz erhalten wurdee?

      Gruß, Enrico

      1. Hallo dedlfix,

        Jetzt funktioniert die Verkleinerung wunderbar :-)

        Hmm, mit "kleiner" Einschränkung :-|

        Eine Verkleinerung auf eine neue Breite funktioniert, eine Verkleinerung auf eine neue Höhe hingegen fragt mich, womit ich die Datei "Verkleinern.php" öffnen will?!

        Gruß, Enrico

        1. Hallo dedlfix,

          und hier der neue Code, den ich nun direkt mit Parametern aufrufe:

             $Ausgangsgrafik = $_GET["A"];
          
             if (isset ($_GET["B"]))
                $Maximale_Breite = $_GET["B"];
          
             if (isset ($_GET["H"]))
                $Maximale_Hoehe = $_GET["H"];
          
             $Informationen         = getimagesize ($Ausgangsgrafik);
             $Urspruengliche_Breite = $Informationen[0];
             $Urspruengliche_Hoehe  = $Informationen[1];
          
             if ($Maximale_Breite)
                $Faktor = $Maximale_Breite / $Urspruengliche_Breite;
             else
                if ($Maximale_Hoehe)
                   $Faktor = $Maximale_Hoehe / $Urspruengliche_Hoehe;
          
             $Neue_Breite = round ($Urspruengliche_Breite * $Faktor);
             $Neue_Hoehe  = round ($Urspruengliche_Hoehe  * $Faktor);
          
             $Kopie = imagecreatefrompng ($Ausgangsgrafik);
             $Verkleinerte_Kopie = imagecreatetruecolor ($Neue_Breite, $Neue_Hoehe);
             $Transparenz = imagecolortransparent ($Kopie);
          
             if ($Transparenz != -1)
             {
                $Transparente_Farbe = imagecolorsforindex ($Kopie, $Transparenz);
                $Transparenz = imagecolorallocate ($Verkleinerte_Kopie, $Transparente_Farbe["red"], $Transparente_Farbe["green"], $Transparente_Farbe["blue"]);
                imagefill ($Verkleinerte_Kopie, 0, 0, $Transparenz);
                imagecolortransparent ($Verkleinerte_Kopie, $Transparenz);
             }
             else
             {
                imagealphablending ($Verkleinerte_Kopie, false);
                $Alpha = imagecolorallocatealpha ($Verkleinerte_Kopie, 0, 0, 0, 127);
                imagefill ($Verkleinerte_Kopie, 0, 0, $Alpha);
                imagesavealpha ($Verkleinerte_Kopie, true);
             }
          
             imagecopyresampled ($Verkleinerte_Kopie, $Kopie, 0, 0, 0, 0, $Neue_Breite, $Neue_Hoehe, $Urspruengliche_Breite, $Urspruengliche_Hoehe);
          
             header ("Content-type: IMAGETYPE_PNG");
             imagepng ($Verkleinerte_Kopie, null);
          

          Gruß, Enrico

          1. Hallo

            Du hast den Code ja ordentlich ausgemistet. Allerdings bist du dabei meiner Meinung nach etwas zu weit gegangen und zudem grundsätzlich falsch abgebogen.

            ##Fangen wir mit dem Abbiegen an.

            Du lässt bei jedem Aufruf einer Seite, in der das Skript eingebunden ist, ein oder mehrere Thumbnail(s) erstellen. Werden die Seiten oft aufgerufen, ist das ineffektiv. Sollten die Bilder aus Uploads stammen, sollte die Thumbnailerstellung einmalig gleich nach dem Upload erfolgen. Das kann dein Skript erledigen. Werden die Bilder von dir oder einem Beauftragten per FTP hochgeladen, sollte die Thumbnailerstellung zum vorbereitenden Arbeitsablauf der Bilderstellung gehören.

            ##Jetzt zum „zu weit“.

            Du hast sämtliche Prüfungen, die zu Fehlerausgaben führen könnten, entfernt. Das sind praktisch alle. Dabei hast du aber verdrängt, dass genau dies ebenso zu Fehlern führen kann.

            Beispiel 1 (alt):

               if (!isset ($_GET["A"]))
                  return "Du hast keine Datei angegeben";
            
               $Ausgangsgrafik = $_GET["A"];
            

            Beispiel 1 (neu):

               $Ausgangsgrafik = $_GET["A"];
            

            Falls $_GET["A"] nicht existiert, ist, je nach eingestelltem PHP-Meldungslevel, entweder $Ausgangsgrafik NULL oder du hast eine Fehlermeldung, die dir dein Skript kaputt gehen lässt.

            Beispiel 2 (alt):

               if (!isset ($_GET["B"]) && !isset ($_GET["H"]))
                  return 'Die Angabe für die neue Breite oder Höhe fehlt';
            
               if (isset ($_GET["B"]))
                  $Maximale_Breite = $_GET["B"];
            # dazwischen liegende Verarbeitungsschritte
               if (isset ($_GET["H"]))
                  $Maximale_Hoehe = $_GET["H"];
            

            Beispiel 2 (neu):

               if (isset ($_GET["B"]))
                  $Maximale_Breite = $_GET["B"];
            # dazwischen liegende Verarbeitungsschritte
               if (isset ($_GET["H"]))
                  $Maximale_Hoehe = $_GET["H"];
            

            Du verlässt dich in der neuen Version darauf, dass $_GET["H"] und $_GET["B"] gesetzt sind, denn die früher vorhandene Prüfung hast du entsorgt. Setze für die Fälle, dass eine oder beide GET-Felder fehlen, Standardwerte über einen Else-Zweig oder eine Vorbelegung ein. Zudem sollte darauf geprüft werden, ob die Eingangswerte numerisch ist und in einem sinnvollen Bereich liegen.

            Eventuell ist es auch sinnvoller, die Maximalgrößen der Thumbnails fest vorzugeben. Gibt es einen Grund, warum diese Größen jedesmal übermittelt werden und somit vom Benutzer beeinflussbar sind?

            Vorbelegung:

               $Maximale_Breite = 100; # Standardwert
               if (isset ($_GET["B"]) and is_numeric($_GET["B"]) and $_GET["B"] > 40 and $_GET["B"] < 160)
                  $Maximale_Breite = $_GET["B"]; # Standardwert wird nur bei vorhandenem $_GET["B"] überschrieben.
            

            Else-Zweig

               if (isset ($_GET["B"]) and is_numeric($_GET["B"]) and $_GET["B"] > 40 and $_GET["B"] < 160) {
                  $Maximale_Breite = $_GET["B"]; # Wert wird nur bei vorhandenem $_GET["B"] gesetzt.
               } else {
                  $Maximale_Breite = 100; # Standardwert bei nicht vorhandenem $_GET["B"].
               }
            # oder
               $Maximale_Breite = (isset ($_GET["B"])) ? $_GET["B"] : 100;
            

            Tschö, Auge

            --
            Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war. Terry Pratchett, “Wachen! Wachen!
            1. @@Auge

              Sollten die Bilder aus Uploads stammen, sollte die Thumbnailerstellung einmalig gleich nach dem Upload erfolgen.

              Oder einmalig beim ersten Aufruf.

              Das Script schaut nach, ob schon ein generiertes Bild in der angefragten Größe im Dateisystem existiert. Wenn ja, wird dieses ausgeliefert. Wenn nein, wird es erstellt, im Dateisystem abgelegt und ausgeliefert.

              Oder das Script schaut gar nicht selbst nach, sondern ist das 404er Script für das Bilderverzeichnis.

              Werden die Bilder von dir oder einem Beauftragten per FTP hochgeladen, sollte die Thumbnailerstellung zum vorbereitenden Arbeitsablauf der Bilderstellung gehören.

              Kann man sich dann sparen, da es dann egal ist, ob die Originalbilder per Upload-Formular oder FTP auf den Server gelangen.

              LLAP

              PS: Einfach nur skalierte Bilder ist oft nicht das, was man will; sondern art direction.

              --
              „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
              1. Liebe Mitdenker, liebe Wissende, liebe Neugierige,

                Sollten die Bilder aus Uploads stammen, sollte die Thumbnailerstellung einmalig gleich nach dem Upload erfolgen.

                Oder einmalig beim ersten Aufruf.

                Das Script schaut nach, ob schon ein generiertes Bild in der angefragten Größe im Dateisystem existiert. Wenn ja, wird dieses ausgeliefert. Wenn nein, wird es erstellt, im Dateisystem abgelegt und ausgeliefert.

                und wenn man schon mal dabei ist, kann das Skript auch einen last_modified-Header mitsenden und beim Request prüfen, ob der Browser einen "If-Modified-Since" mitgesendet hat und den auswerten. Warum nochmal umwandeln und übertragen, wenn der Client das Bild schon hat?

                Spirituelle Grüße
                Euer Robert
                robert.r@online.de

                --
                Möge der wahre Forumsgeist ewig leben!
              2. Hallo

                Werden die Bilder von dir oder einem Beauftragten per FTP hochgeladen, sollte die Thumbnailerstellung zum vorbereitenden Arbeitsablauf der Bilderstellung gehören.

                Kann man sich dann sparen, da es dann egal ist, ob die Originalbilder per Upload-Formular oder FTP auf den Server gelangen.

                Das ist grundsätzlich richtig. Allerdings ist die Qualität nach der Bearbeitung in einem qualifizierten Grafikprogramm typischerweise besser als nach der Skalierung durch PHP, auch wenn das evtl. mit höherem Aufwand und mit höherer nötiger Qualifikation des Programmbedieners einhergeht.

                Tschö, Auge

                --
                Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war. Terry Pratchett, “Wachen! Wachen!
                1. Liebe Mitdenker, liebe Wissende, liebe Neugierige,

                  Das ist grundsätzlich richtig. Allerdings ist die Qualität nach der Bearbeitung in einem qualifizierten Grafikprogramm typischerweise besser als nach der Skalierung durch PHP, auch wenn das evtl. mit höherem Aufwand und mit höherer nötiger Qualifikation des Programmbedieners einhergeht.

                  So groß ist der Unterschied wahrlich nicht mehr. Die GD-Lib arbeitet mit imagecopyresampled() schon ganz ordentlich.

                  Spirituelle Grüße
                  Euer Robert
                  robert.r@online.de

                  --
                  Möge der wahre Forumsgeist ewig leben!
                  1. Hallo

                    Das ist grundsätzlich richtig. Allerdings ist die Qualität nach der Bearbeitung in einem qualifizierten Grafikprogramm typischerweise besser als nach der Skalierung durch PHP, auch wenn das evtl. mit höherem Aufwand und mit höherer nötiger Qualifikation des Programmbedieners einhergeht.

                    So groß ist der Unterschied wahrlich nicht mehr. Die GD-Lib arbeitet mit imagecopyresampled() schon ganz ordentlich.

                    Das wollte ich auch nicht in Zweifel ziehen.Es ist aber ein Automatismus, den ein talentierter Mensch wohl immer ausstechen wird. Der kann halt auch ein Ergebnis verwerfen und anders ahn die Sache herangehen. Das kann der Automatismus nicht.

                    Aber da sind wir wohl in dem Bereich, den Gunnar mit „art direction“ bezeichnete.

                    Tschö, Auge

                    --
                    Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war. Terry Pratchett, “Wachen! Wachen!
                    1. @@Auge

                      Es ist aber ein Automatismus, den ein talentierter Mensch wohl immer ausstechen wird. Der kann halt auch ein Ergebnis verwerfen und anders ahn die Sache herangehen. Das kann der Automatismus nicht.

                      Aber da sind wir wohl in dem Bereich, den Gunnar mit „art direction“ bezeichnete.

                      Eher das, was mein geschätzter Kollege auf Folie 17 zeigt.

                      LLAP

                      --
                      „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
                      1. Aloha ;)

                        Eher das, was mein geschätzter Kollege auf Folie 17 zeigt.

                        Mir gefällt die Einbindung der Präsentation auf der Seite deines geschätzten Kollegen, vor allem die Touchscreensteuerung, extrem gut, zumindest meiner UX nach. Sehr intuitiv und noch dazu schön anzuschauen. Musste ich schnell loswerden.

                        Grüße,

                        RIDER

                        --
                        Camping_RIDER a.k.a. Riders Flame a.k.a. Janosch Zoller Erreichbar meist Mittwochs ab 21 Uhr im Self-TS (ts.selfhtml.org) oder sonst - wenn online - auf dem eigenen TeamSpeak-Server (fritz.campingrider.de). # Facebook # Twitter # Steam # YouTube # Self-Wiki # ch:? rl:| br:> n4:? ie:% mo:| va:) js:) de:> zu:) fl:( ss:| ls:[
                        1. Hallo

                          Eher das, was mein geschätzter Kollege auf Folie 17 zeigt.

                          Mir gefällt die Einbindung der Präsentation auf der Seite deines geschätzten Kollegen, vor allem die Touchscreensteuerung, extrem gut, zumindest meiner UX nach. Sehr intuitiv und noch dazu schön anzuschauen. Musste ich schnell loswerden.

                          Dann probiere es doch mal mit einer Maus. Viel Spaß!

                          Als ich weiter blättern wollte, war für mich nicht erkennbar wie, aber als ich es nicht wollte, hat es – für mich nicht reproduzierbar – aus Versehen funktioniert. Die Präsentation hat in Sachen Bedienung für mich vor lauter Schickimicki verkackt. Dass die Seite per se ohne JavaScript garnicht funktioniert, spielt dabei schon keine Rolle mehr.

                          Tschö, Auge

                          --
                          Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war. Terry Pratchett, “Wachen! Wachen!
                          1. @@Auge

                            Dann probiere es doch mal mit einer Maus. Viel Spaß!

                            Da, wo sich der Mauscursor ändert, kann man clicken: auf dem rechten Rand der aktuellen Folie und dem Zwischenraum zur nächsten bzw. auf dem linken Rand der aktuellen Folie und dem Zwischenraum zur vorigen.

                            Die Präsentation hat in Sachen Bedienung für mich vor lauter Schickimicki verkackt.

                            Die Präsentation ist primär dazu gedacht, vom Vortragenden präsentiert zu werden. Der schaltet eher nicht mit Maus, sondern mit Leertaste (vorwärts), Pfeiltasten oder am ehesten kabellos.

                            Dass die Seite per se ohne JavaScript garnicht funktioniert, spielt dabei schon keine Rolle mehr.

                            Stimmt.

                            LLAP

                            --
                            „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
                            1. Hallo

                              Dann probiere es doch mal mit einer Maus. Viel Spaß!

                              Da, wo sich der Mauscursor ändert, kann man clicken: auf dem rechten Rand der aktuellen Folie und dem Zwischenraum zur nächsten bzw. auf dem linken Rand der aktuellen Folie und dem Zwischenraum zur vorigen.

                              Hmm, genau das hat nicht geklappt. Klick an den Bildschrimrand: nüscht. Klick in den Zwischenraum der Folien: nüscht. Klick auf den Rand des Foliencontainers: nüscht.

                              Die Präsentation hat in Sachen Bedienung für mich vor lauter Schickimicki verkackt.

                              Die Präsentation ist primär dazu gedacht, vom Vortragenden präsentiert zu werden. Der schaltet eher nicht mit Maus, sondern mit Leertaste (vorwärts), Pfeiltasten oder am ehesten kabellos.

                              Klar, dass eine Präsentation primär anders als mit der Maus bedient wird. Wenn sie (die Präsentation) im Web präsentiert wird, sollte sie dort aber auch mit den typischen Eingabegeräten intuitiv bedienbar sein. Ja, für mich gehört die Maus definitiv dazu. Eine Markierung der Bedienflächen, eventuell mit Hovereffekt, hätte ja schon gereicht.

                              Tschö, Auge

                              --
                              Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war. Terry Pratchett, “Wachen! Wachen!
                              1. Aloha ;)

                                Naja. Ich hatte ja ausdrücklich und ausschließlich die Touchscreenbedienung gelobt. Ich hab mir schon überlegt, ob ichs überhaupt schreiben soll, weil mir irgendwie schon klar war, dass das mit Maus ganz anders aussieht und wahrscheinlich nur mit JavaScript läuft. Da das für mich zu diesem Zeitpunkt aber nicht nachprüfbar war (mangels Entwicklerwerkzeugen und Maus am Tablet) hab ichs halt bei dem Lob belassen.

                                Der Grund meines Lobes ist ja vor allem, dass mir die Bedienung am Touchscreen so gut gefallen hat. Daher: Wenn man das von Grund auf ordentlich umsetzt, d.h. mit ähnlich intuitiver Maussteuerung, und vor allen Dingen mit der JavaScript-basierten Steuerung als progressive enhancement, dann fände ich das ziemlich optimal.

                                Es gibt zuhauf Systeme, die sich mit Maus und Tastatur intuitiv steuern lassen, und es gibt auch zuhauf Systeme, die sich ohne JavaScript gut bedienen lassen. Aber kaum welche, die so intuitiv am Touchscreen bedienbar sind. Das ist quasi die kritische Zutat (sofern auch alle anderen Suppeneinlagen entsprechend hochwertig sind), die das Essen würzt, und so oft hab ich die noch nicht gefunden. Deshalb die Erwähnung.

                                Grüße,

                                RIDER

                                --
                                Camping_RIDER a.k.a. Riders Flame a.k.a. Janosch Zoller Erreichbar meist Mittwochs ab 21 Uhr im Self-TS (ts.selfhtml.org) oder sonst - wenn online - auf dem eigenen TeamSpeak-Server (fritz.campingrider.de). # Facebook # Twitter # Steam # YouTube # Self-Wiki # ch:? rl:| br:> n4:? ie:% mo:| va:) js:) de:> zu:) fl:( ss:| ls:[
                              2. @@Auge

                                Hmm, genau das hat nicht geklappt. Klick an den Bildschrimrand: nüscht. Klick in den Zwischenraum der Folien: nüscht. Klick auf den Rand des Foliencontainers: nüscht.

                                Klappt bei mir problemlos. Welcher Browser (welches OS) zickt da rum?

                                Klar, dass eine Präsentation primär anders als mit der Maus bedient wird. Wenn sie (die Präsentation) im Web präsentiert wird, sollte sie dort aber auch mit den typischen Eingabegeräten intuitiv bedienbar sein. Ja, für mich gehört die Maus definitiv dazu. Eine Markierung der Bedienflächen, eventuell mit Hovereffekt, hätte ja schon gereicht.

                                Ja, in der Nachbearbeitung könnte man Pfeilsymbole als Hintergrundbild auf die Folien tun, um das Vorwärts/Rückwärts zu visualisieren.

                                Aber erst dann; beim Vortrag wären die fehl am Platz.

                                LLAP

                                --
                                „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
                                1. Hallo

                                  Hmm, genau das hat nicht geklappt. Klick an den Bildschrimrand: nüscht. Klick in den Zwischenraum der Folien: nüscht. Klick auf den Rand des Foliencontainers: nüscht.

                                  Klappt bei mir problemlos. Welcher Browser (welches OS) zickt da rum?

                                  Firefox 37.0.1 unter Windows 7. Ob's daran liegt, sei dahingestellt. Vielleicht klickte ich ja auch nur auf die falschen Stellen. Als ich es nicht wollte, hat es ja zumindest einmal geklappt.

                                  Tschö, Auge

                                  --
                                  Verschiedene Glocken läuteten in der Stadt, und jede von ihnen vertrat eine ganz persönliche Meinung darüber, wann es Mitternacht war. Terry Pratchett, “Wachen! Wachen!
                2. @@Auge

                  Das ist grundsätzlich richtig. Allerdings ist die Qualität nach der Bearbeitung in einem qualifizierten Grafikprogramm typischerweise besser als nach der Skalierung durch PHP, auch wenn das evtl. mit höherem Aufwand und mit höherer nötiger Qualifikation des Programmbedieners einhergeht.

                  Der Ansatz, Bilder bei Bedarf zu generieren, geht auch wunderbar mit manueller Skalierung/art direction einher. Es wird ja nur generiert, was noch nicht da ist (z.B. manuell erstellt und hochgeladen wurde). Und automatisch generierte Dateien können nachträglich überschrieben werden.

                  LLAP

                  --
                  „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)
          2. Lieber Enrico, liebe Mitdenker, liebe Wissende, liebe Neugierige,

            und hier der neue Code, den ich nun direkt mit Parametern aufrufe:

            Und was ist damit? Läuft der nun so, wie Du wolltest?
            Mir sind einige Dinge aufgefallen. Ich weiß leider noch nicht, wie ich die Bemerkungen in deinen Code reinbringen kann, ohne dass die Formatierung nachher flöten geht, aber ich will es mal versuchen.

               $Ausgangsgrafik = $_GET["A"];  
            

            Umkopieren ist nicht notwendig, aber prüfen auf einen erlaubten Pfad ist wichtig, damit dein Script nicht zur Sicherheitslücke wird. Du übergibst übrigens (oben im Thread) "G=../IMG/bildname.png" und fragst hier nach $_GET['A'].

            Außerdem solltest Du auch danach fragen "if (isset($_GET['G']))"

            if (isset ($_GET["B"])) $Maximale_Breite = $_GET["B"];

            Hier erst umwandeln in Integer und dann Werte kleiner Minimalbreite ablehnen

            if (isset ($_GET["H"])) $Maximale_Hoehe = $_GET["H"];

            Hier auch umwandeln in Integer und dann Werte kleine Minimalhöhe ablehnen

            $Informationen = getimagesize ($Ausgangsgrafik);

            getimagesize() liefert auch einen Fehlerwert, wenn das Grafikfile nicht auswertbar ist

            $Urspruengliche_Breite = $Informationen[0]; $Urspruengliche_Hoehe = $Informationen[1];

            Die sind nur vorhanden, wenn getimagesize() vorher geklappt hat

            if ($Maximale_Breite) $Faktor = $Maximale_Breite / $Urspruengliche_Breite; else if ($Maximale_Hoehe) $Faktor = $Maximale_Hoehe / $Urspruengliche_Hoehe;

            $Neue_Breite = round ($Urspruengliche_Breite * $Faktor); $Neue_Hoehe = round ($Urspruengliche_Hoehe * $Faktor);

            $Kopie = imagecreatefrompng ($Ausgangsgrafik);

            Woher weißt Du, dass es eine PNG-Grafik war?

            Man kann auch imagecreatefromstring() benutzen, das erkennt selber, was für ein Bildtyp vorliegt. Außerdem kann man dann vorher die Datei einlesen mit fread() und prüfen, ob das klappt, dann muss man das TOCTOU-Anfällige file_exists() nicht benutzen. Dann kann man darauf auch getimagesizefromstring() anwenden, wenn die PHP-Version >= 5.4.0 ist. Dadurch muss dann nur ein einziger HDD-Zugriff erfolgen, während deine Methode ( file_exists(), getimagesize(), imagecreatefrom***() ) drei Zugriffe erfordert. (Ok, wenn PHP das file cached hat, ist es vermutlich egal, aber da steckt man nicht drin, ... )

            $Verkleinerte_Kopie = imagecreatetruecolor ($Neue_Breite, $Neue_Hoehe); $Transparenz = imagecolortransparent ($Kopie);

            if ($Transparenz != -1) { $Transparente_Farbe = imagecolorsforindex ($Kopie, $Transparenz); $Transparenz = imagecolorallocate ($Verkleinerte_Kopie, $Transparente_Farbe["red"], $Transparente_Farbe["green"], $Transparente_Farbe["blue"]); imagefill ($Verkleinerte_Kopie, 0, 0, $Transparenz); imagecolortransparent ($Verkleinerte_Kopie, $Transparenz); } else { imagealphablending ($Verkleinerte_Kopie, false); $Alpha = imagecolorallocatealpha ($Verkleinerte_Kopie, 0, 0, 0, 127); imagefill ($Verkleinerte_Kopie, 0, 0, $Alpha); imagesavealpha ($Verkleinerte_Kopie, true); }

            imagecopyresampled ($Verkleinerte_Kopie, $Kopie, 0, 0, 0, 0, $Neue_Breite, $Neue_Hoehe, $Urspruengliche_Breite, $Urspruengliche_Hoehe);

            header ("Content-type: IMAGETYPE_PNG"); imagepng ($Verkleinerte_Kopie, null);

            Da Du ein eigenes Skript daraus machst, kannst Du in diesem Skript auch eigene Funktionen erstellen. Das vereinfacht und verbessert die Steuerung des Programmablaufes - also aufteilen in einzelne Funktionen mit definierter Aufgabe.

            Die übrigen Dinge lasse ich erst einmal ohne Kommentar. Ich will dich ja nicht ärgern :-)

            Und noch eine Idee für Dich:

            Du kannst den Aufruf des Skriptes per .htaccess steuern:

            Die Umleitung auf das Skript kannst Du mit einer Rewrite-Rule in einer .htaccess-Datei vornehmen. Wenn Du schreibst <img src="/images/meinbild.jpg" ...>, dann wird das Originalbild ausgeliefert und wenn Du schreibst <img src="/thumbs/meinbild.jpg" ...>, dann wird auf dein Skript umgeleitet, weil "/thumbs/" im Pfad steht und das in der Rewrite-Rule so festgelegt wird. Und das Skript weiß dann selber, dass es das Image in /images/ zu suchen hat (weil das von Dir so festgelegt wurde) und liefert es verkleinert aus.

            Das hat den Vorteil, dass dein Skript "geheim" bleibt, also der Name nach außen hin gar nicht erst publik gemacht wird.

            Spirituelle Grüße
            Euer Robert
            robert.r@online.de

            --
            Möge der wahre Forumsgeist ewig leben!
            1. Hallo robertroth,

              Ich weiß leider noch nicht, wie ich die Bemerkungen in deinen Code reinbringen kann, ohne dass die Formatierung nachher flöten geht,

              Wenn du Codeblöcke auseinandernehmen möchtest, muss du (wie im alten Forum auch) darauf achten, dass jeder einen Anfang und ein Ende hat.

                 $Ausgangsgrafik = $_GET["A"];
              

              Umkopieren ist nicht notwendig, aber prüfen auf einen erlaubten Pfad ist wichtig, damit dein Script nicht zur Sicherheitslücke wird. Du übergibst übrigens (oben im Thread) "G=../IMG/bildname.png" und fragst hier nach $_GET['A'].

              Außerdem solltest Du auch danach fragen "if (isset($_GET['G']))"

                 if (isset ($_GET["B"]))
                    $Maximale_Breite = $_GET["B"];
              

              Hier erst umwandeln in Integer und dann Werte kleiner Minimalbreite ablehnen

                 if (isset ($_GET["H"]))
                    $Maximale_Hoehe = $_GET["H"];
              

              Hier auch umwandeln in Integer und dann Werte kleine Minimalhöhe ablehnen

              Bis demnächst
              Matthias

              --
              Signaturen sind bloed (Steel) und Markdown ist mächtig.
          3. Hallo,

            uffz, so viele Antworten, die ich jetzt erst mal durcharbeiten werde.

            Danke euch, ich melde mich dann wieder.

            Gruß, Enrico

            1. Hallo,

              so, jetzt habe ich - hoffentlich - alle Anregungen umgesetzt, um das Skript sowohl durch direkten Aufruf mit hart eingegebenen Parametern zum Laufen zu bringen, als auch als src-Angabe für das Einbinden der verkleinerten Grafik im image-Tag:

                 if (!isset ($_GET["G"]))
                    die ("Es wurde keine zu verkleinernde Grafik angegeben");
              
                 $Grafik = "../../IMG/" . $_GET["G"] . ".png"; // Vollständigen relativen Pfad erzeugen
              
                 if (!file_exists ($Grafik))
                    die ("Der Pfad zur zu verkleinernden Grafik ist fehlerhaft oder die zu verkleinernde Grafik existiert nicht");
              
                 if (exif_imagetype ($Grafik) != IMAGETYPE_PNG)
                    die ('Die zu verkleinernde Grafik ist keine "png"-Datei');
              
                 if (!($Informationen = @getimagesize ($Grafik)))
                    die ("Die Daten der zu verkleinernden Grafik konnten nicht ausgelesen werden");
              
                 if (isset ($_GET["B"])) // Auf Breite verkleinern
                    $Faktor = 80 / $Informationen[0];
                 else
                    if (isset ($_GET["H"])) // Auf Höhe verkleinern
                       $Faktor = 100 / $Informationen[1];
                    else
                       die ("Die Angabe zur Verkleinerung der Grafik in der Höhe oder Breite fehlt");
              
                 $Breite = round ($Informationen[0] * $Faktor);
                 $Hoehe  = round ($Informationen[1] * $Faktor);
              
                 $Kopie         = imagecreatefrompng ($Grafik);
                 $Verkleinerung = imagecreatetruecolor ($Breite, $Hoehe);
                 $Transparenz   = imagecolortransparent ($Kopie);
              
                 if ($Transparenz != -1)
                 {
                    $Transparente_Farbe = imagecolorsforindex ($Kopie, $Transparenz);
                    $Transparenz = imagecolorallocate ($Verkleinerung, $Transparente_Farbe["red"], $Transparente_Farbe["green"], $Transparente_Farbe["blue"]);
                    imagefill ($Verkleinerung, 0, 0, $Transparenz);
                    imagecolortransparent ($Verkleinerung, $Transparenz);
                 }
                 else
                 {
                    imagealphablending ($Verkleinerung, false);
                    $Alpha = imagecolorallocatealpha ($Verkleinerung, 0, 0, 0, 127);
                    imagefill ($Verkleinerung, 0, 0, $Alpha);
                    imagesavealpha ($Verkleinerung, true);
                 }
              
                 imagecopyresampled ($Verkleinerung, $Kopie, 0, 0, 0, 0, $Breite, $Hoehe, $Informationen[0], $Informationen[1]);
              
                 header ("Content-type: IMAGETYPE_PNG");
                 imagepng ($Verkleinerung, null);
              

              Der Aufruf im image-Tag erfolgt folgendermaßen:

              echo '<img src="INC/Verkleinern.php?G=FotoEnricoGross&B">';
              

              Ich übergebe nun nur noch ein Kennzeichen "B" oder "H", um die übergebene Grafik entweder in ihrer B(reite) oder H(öhe) zu verkleinern mit fest im Skript hinterlegten Werten.

              Das Skript soll letztendlich beim Aufrufen einer anzuzeigenden Galerie auf jede Grafik in obig genannter Form die jeweilige Grafik verkleinern. Interaktionen von Besuchern sind ausdrücklich nicht vorgesehen.

              Das Script schaut nach, ob schon ein generiertes Bild in der angefragten Größe im Dateisystem existiert. Wenn ja, wird dieses ausgeliefert. Wenn nein, wird es erstellt, im Dateisystem abgelegt und ausgeliefert.

              Gunnar, Dein Ansatz zieht wohl darauf ab, dass ich, zusätzlich zu den vorhandenen großen Originalgrafiken, die verkleinerten Thumbnails erzeuge und auf dem Server ablege, oder habe ich Dich hier falsch verstanden?

              und wenn man schon mal dabei ist, kann das Skript auch einen last_modified-Header mitsenden und beim Request prüfen, ob der Browser einen "If-Modified-Since" mitgesendet hat und den auswerten. Warum nochmal umwandeln und übertragen, wenn der Client das Bild schon hat?

              Robert, Du gehst in die gleiche Richtung wie Gunnar? Oder kann ich diesen Mechanismus generell auf mein Vorhaben anwenden? Wenn ja, wie muss ich vorgehen?

              Kann ich am Skript sonst noch etwas verbessern?

              Gruß, Enrico

              1. Hallo Enrico,

                header ("Content-type: IMAGETYPE_PNG");

                mit »IMAGETYPE_PNG« als Content-Typ werden Browser nicht viel anfangen können - auch wenn die Konstante aufgelöst würde würde mit »3« kein sinnvoller Typ rauskommen.

                Gunnar, Dein Ansatz zieht wohl darauf ab, dass ich, zusätzlich zu den vorhandenen großen Originalgrafiken, die verkleinerten Thumbnails erzeuge und auf dem Server ablege, oder habe ich Dich hier falsch verstanden?

                Willst du die Bilder etwa bei jedem Seitenaufruf neu erzeugen?

                Gruß,
                Tobias

                1. Hallo Tobias,

                  mit »IMAGETYPE_PNG« als Content-Typ werden Browser nicht viel anfangen können - auch wenn die Konstante aufgelöst würde würde mit »3« kein sinnvoller Typ rauskommen.

                  Was meinst Du damit genau? Ich habe gelesen, diese Angabe wäre notwendig, um über PHP erzeugte Bilder an den Browser auszuliefern.

                  Willst du die Bilder etwa bei jedem Seitenaufruf neu erzeugen?

                  Ich hatte eigentlich nur vor, die großen originalen Grafiken auf dem Server zu haben und die Verkleinerungen on-the-fly zu erzeugen. Sonst könnte ich die Verkleinerungen doch gleich hart über ein Grafikprogramm erzeugen und in einem Unterordner auf dem Server ablegen, oder bin ich hier jetzt in einer völlig falschen Richtung?

                  Gruß, Enrico

                  1. Hallo Enrico,

                    Was meinst Du damit genau? Ich habe gelesen, diese Angabe wäre notwendig, um über PHP erzeugte Bilder an den Browser auszuliefern.

                    ein Content-Type-Header ist auch nötig, stimmt - aber als Wert gehört da eben »image/png« rein und nicht »IMAGETYPE_PNG« (wobei ich vermute dass du eigentlich den Wert der Konstanten einfügen wolltest, aber in der steht auch nur eine 3 drin).

                    Ich hatte eigentlich nur vor, die großen originalen Grafiken auf dem Server zu haben und die Verkleinerungen on-the-fly zu erzeugen. Sonst könnte ich die Verkleinerungen doch gleich hart über ein Grafikprogramm erzeugen und in einem Unterordner auf dem Server ablegen, oder bin ich hier jetzt in einer völlig falschen Richtung?

                    Ob du die verkleinerten Bilder jetzt vom Server oder vom Grafikprogram berechnen und lässt ist egal - aber die Bilder bei jedem Seitenaufruf neu zu berechnen ist doch unnötige Arbeit für den Server.

                    Gruß,
                    Tobias

                  2. Liebe Mitdenker, liebe Wissende, liebe Neugierige,

                    mit »IMAGETYPE_PNG« als Content-Typ werden Browser nicht viel anfangen können - auch wenn die Konstante aufgelöst würde würde mit »3« kein sinnvoller Typ rauskommen.

                    Was meinst Du damit genau? Ich habe gelesen, diese Angabe wäre notwendig, um über PHP erzeugte Bilder an den Browser auszuliefern.

                    Du musst hier aber den MIME-Type angeben und der ist in deinem Fall 'image/png'.

                    Willst du die Bilder etwa bei jedem Seitenaufruf neu erzeugen?

                    @tk: darum ging es erst einmal in diesem Thread. Andere Ideen wurden aber schon andiskutiert.

                    Wenn man die Thumbs beim Hochladen neuer Bilder berechnen will, sollte man in einer Galerie, die enrico hier aufbauen will, auch nicht vergessen, sie wieder zu entfernen, wenn das große Bild nicht mehr vorhanden ist oder nicht mehr angezeigt werden soll.

                    Spirituelle Grüße
                    Euer Robert
                    robert.r@online.de

                    --
                    Möge der wahre Forumsgeist ewig leben!
        2. Tach!

          Eine Verkleinerung auf eine neue Breite funktioniert, eine Verkleinerung auf eine neue Höhe hingegen fragt mich, womit ich die Datei "Verkleinern.php" öffnen will?!

          Dann wird da vielleicht noch ein Fehler drin sein. Jedenfalls solltest du sicherstellen, dass da keine Fehlerausgabe dazwischenfunkt (und es gar nicht erst einen Grund gibt, dass ein Fehler gemeldet werden muss). Wie schon empfohlen, Quelltextansicht des Bildes oder mal vorübergehend den Content-Type-Header deaktivieren kann helfen, der Ursache auf den Grund zu gehen. Ebenso die üblichen Debugvorgänge, wie Ausgaben der Variableninhalte und Resultate von Funktionen. Bei binären Bilddaten wird man nicht viel erkennen könne, aber aus eventuellen anderen Ausgaben davor (vor allem da) oder danach.

          dedlfix.

          P.S. Auszeichnung als bestimmer Code für dieses Forum geht so, beispielsweise für PHP: ~~~php ... ~~~

      2. Tach!

        Ich habe nun alle return-Meldungen entfernt, da diese selber für Fehlermeldungen gesorgt haben.

        Sie haben jedenfalls das Script abgebrochen und statt der Bilddaten (vermutlich) Plaintext an den Browser gegeben. Dass der daraus kein Bild erkennen kann, ist nicht verwunderlich.

        Die ursprüngliche Grafik besteht aus einem schwarzen Dummy mit transparentem Hintergrund und wird nun auf weißem Hintergrund im Browser dargestellt. Bedeutet dies, dass auch die Transparenz erhalten wurdee?

        Weiß ich nicht. Das kannst du ja leicht selbst probieren, indem du etwas in den Hintergrund legst (eine andere Farbe reicht schon), das dann durch die als transparent geplanten Flächen zu sehen sein muss.

        dedlfix.