Willi: Transparenz bei GIF-Bildern mit PHP („<img src="data: …“)

Dear forum,

Um den Spambots das Feld nicht kampflos zu überlassen, habe ich mich gestern dazu entschlossen, alle E-Mail-Adressen auf abi10-asg.de zu verschleiern. Ich habe mir überlegt, am besten geht das mit Bildern - da Adressen wie »willi292 (at) web (.) de« manche Leute doch eher verwirren. Um die Adressen dann nicht per URL an ein Script zu übergeben (weil dann ja in der URL die Adressen stehen müssten …) habe ich mir gedacht - benutze ich doch data-URLs.

Das hat auch alles problemlos geklappt. Doch nach dem Upload dann das erste Problem: die Schrift sieht hochgeladen anders aus! Ich vermute, dass Vista im Hintergrund die Schrift glättet und dann an PHP weitergibt und das auf dem Server eben nicht passiert. Naja, okay. Mit arial war das Ergebnis nicht so toll, jetzt habe ich sie geändert (Calibri) und es geht.

Bei dem Haupteinsatzzweck (die Steckbriefe, z.B. hier) sieht es nun auch ganz okay aus. Es fällt zwar auf, dass ein Bild verwendet wird, aber es fügt sich dennoch gut in den Rest der Seite ein.
An anderen Stellen ist das bei weitem nicht so toll. Für den Footer habe ich die Funktion um eine Farbwahl erweitert, sodass das Bild dort den gleichen Hintergrund hat wie der Absatz. Aber bei der Tabelle unter /schueler geht das nun mal nicht so gut. Mit transparenten GIFs wäre es auch hier kein Problem, doch das will nicht so recht klappen.

Kann mir jemand meinen Fehler in meiner function sagen?

function _email($address, $type = 'text', $link = 0, $bgcolor = array(255,255,255)){  
  
  $pos_at = strpos($address, '@');  
  $substr1 = substr($address, 0, $pos_at);  
  $substr2 = substr($address, $pos_at + 1);  
  $pos_dot = strrpos($substr2, '.');  
  $substr3 = substr($substr2, 0, $pos_dot);  
  $substr4 = substr($substr2, $pos_dot + 1);  
  $address_difficult = $substr1 . ' [an] ' . $substr3 . ' [.] ' . $substr4; // wird für alternativ-Text verwendet (für IE etc., die kein data: unterstützen)  
  
  switch($type){  
    case 'text':  
      return ($link == 0) ? $address : '<a href="mailto:'.$address.'">'.$address.'</a>';  
    case 'graphic':  
      $textsize = imagettfbbox(10, 0, 'fonts/calibri.ttf', $address);  
      $width = $textsize[2] - $textsize[0];  
      $height = $textsize[1] - $textsize[7];  
      $im = imagecreatetruecolor($width + 5, $height);  
      $background_color = ImageColorAllocatealpha ($im, $bgcolor[0], $bgcolor[1], $bgcolor[2], 127);  
      ImageFill($im, 0, 0, $background_color);  
      $black = ImageColorAllocate ($im, 0, 0, 0);  
      imagettftext($im, 10, 0, 0, $height - 3, $black, 'calibri.ttf', $address);  
      $tmpfname = tempnam ("/tmp", "FOO");  
      Imagegif($im,$tmpfname); the file  
      $temp = fopen($tmpfname,"rb");for reading binary  
      $buffer = fread($temp,filesize($tmpfname));  
      fclose($temp);the file  
      unlink($tmpfname); with the file, discard  
      $out = base64_encode($buffer); // encodieren  
      return '<img src="data:image/gif;base64,'.chunk_split($out).'" alt="'.$address_difficult.'" />';  
  }  
}

Fände ne hilfreiche Antwort echt toll :P ;)

— lg, gabriel

  1. Hallo,

    [E-Mail-Adressen verschleiern.] Ich habe mir überlegt, am besten geht das mit Bildern

    ja, mag sein.

    da Adressen wie »willi292 (at) web (.) de« manche Leute doch eher verwirren.

    Manche vielleicht, aber sicher nur sehr wenige.

    Um die Adressen dann nicht per URL an ein Script zu übergeben (weil dann ja in der URL die Adressen stehen müssten …) habe ich mir gedacht - benutze ich doch data-URLs.

    Und vergisst dabei, dass die von einigen Browsern nicht unterstützt werden. Nebenbei bemerkt: Warum so aufwendig? Wenn du schon Bilder generierst, dann speichere sie doch auch gleich als Datei mit einem "zufälligen" Namen auf dem Server (falls sie noch nicht existieren), und referenziere diese Bildressource im HTML-Code.

    Ich vermute, dass Vista im Hintergrund die Schrift glättet und dann an PHP weitergibt

    Vista hat mit PHP nichts zu tun! Vista läuft meinetwegen auf deinem Rechner, und PHP auf dem Server, aber Vista "gibt nichts an PHP weiter". Das tut nur dein Webserver.
    Vista glättet die Schriften, das stimmt, und die gdlib von PHP macht so einen Unsinn nicht.

    Naja, okay. Mit arial war das Ergebnis nicht so toll, jetzt habe ich sie geändert (Calibri) und es geht.

    Ist dir auch klar, dass du dabei rechtlich in die Bredouille kommst? Denn die Microsoft-Schriften sind ja kein Freiwild! Die darfst du nicht auf einem Server zur Verfügung stellen - auch nicht, um daraus nur ausgewählte Schriftfetzen zu generieren. Das kann Ärger geben.

    Bei dem Haupteinsatzzweck (die Steckbriefe, z.B. hier) sieht es nun auch ganz okay aus. Es fällt zwar auf, dass ein Bild verwendet wird, ...

    Ja, vor allem daran, dass es nicht angezeigt werden kann. ;-)
    Aber wenigstens hast du einen hilfreichen Alternativtext.

    So long,
     Martin

    --
    Man soll den Tag nicht vor dem Abend loben.
    Und den Mann nicht vor dem Morgen.
      (alte Volksweisheit)
    1. Hallo シ

      Um die Adressen dann nicht per URL an ein Script zu übergeben (weil dann ja in der URL die Adressen stehen müssten …) habe ich mir gedacht - benutze ich doch data-URLs.

      Und vergisst dabei, dass die von einigen Browsern nicht unterstützt werden.

      Nein. :)
      Habe ich nicht vergessen - aber dafür sind ja die Alternativtexte da. Auf der Website sind 72% Firefoxbenutzer, sie möchte ich mehr oder weniger "belohnen", dass sie nicht den IE benutzen - und ihnen eben ein paar Schmankerl anbieten. Außerdem ist sie mehr oder weniger meine "Spielwiese", auf der ich alle mögliche Sachen ausprobiere, die ich wohl nicht machen würde, wenn ich sie für Geld erstellen würde.

      Nebenbei bemerkt: Warum so aufwendig? Wenn du schon Bilder generierst, dann speichere sie doch auch gleich als Datei mit einem "zufälligen" Namen auf dem Server (falls sie noch nicht existieren), und referenziere diese Bildressource im HTML-Code.

      Ja, stimmt. Aber dann muss ich auch noch das Bild erstellen, wenn jemand seinen Steckbrief bzw. seine E-Mail-Adresse ändert etc. Hier brauche ich keine externen Dateien, keine Datenbankeinträge (weil ja die URL "zufällig" sein soll - okay, würde auch mit nem Algorithmus gehen).

      Ich vermute, dass Vista im Hintergrund die Schrift glättet und dann an PHP weitergibt

      Vista hat mit PHP nichts zu tun! Vista läuft meinetwegen auf deinem Rechner, und PHP auf dem Server, aber Vista "gibt nichts an PHP weiter". Das tut nur dein Webserver.
      Vista glättet die Schriften, das stimmt, und die gdlib von PHP macht so einen Unsinn nicht.

      Ja, okay. Aber wo liegt dann der Hund begraben? War halt so die erste Möglichkeit, die mir eingefallen ist.

      Naja, okay. Mit arial war das Ergebnis nicht so toll, jetzt habe ich sie geändert (Calibri) und es geht.

      Ist dir auch klar, dass du dabei rechtlich in die Bredouille kommst? Denn die Microsoft-Schriften sind ja kein Freiwild! Die darfst du nicht auf einem Server zur Verfügung stellen - auch nicht, um daraus nur ausgewählte Schriftfetzen zu generieren. Das kann Ärger geben.

      Stimmt. Werde mich dann mal auf die Suche nach einem freien Font machen. Habe mir da nicht so viele Gedanken gemacht. (Bin mir zwar auch sicher, dass da niemand was sagen würde, aber du hast Recht.)

      Bei dem Haupteinsatzzweck (die Steckbriefe, z.B. hier) sieht es nun auch ganz okay aus. Es fällt zwar auf, dass ein Bild verwendet wird, ...
      Ja, vor allem daran, dass es nicht angezeigt werden kann. ;-)
      Aber wenigstens hast du einen hilfreichen Alternativtext.

      Eben. Und das andere ist ja nur eine Hilfe für die Firefox-Benutzer :)

      —Gabriel

      1. Auf der Website sind 72% Firefoxbenutzer …

        Doch nicht, die 72% waren auf meinem Weblog.
        Auf abi10 dagegen benutzen 83% Firefox und nur 9% den IE.
        Daher halte ich meine Methode mit data-Referenzen durchaus für legitim.

      2. Hi,

        Ich vermute, dass Vista im Hintergrund die Schrift glättet und dann an PHP weitergibt
        Vista glättet die Schriften, das stimmt, und die gdlib von PHP macht so einen Unsinn nicht.
        Ja, okay. Aber wo liegt dann der Hund begraben? War halt so die erste Möglichkeit, die mir eingefallen ist.

        was ist daran so unverständlich?

        Fall 1: Die Mailadressen stehen als Text auf der Seite. Dein Browser stellt sie also auch als Text dar, ergo fällt das Betriebssystem (bzw. das Grafik-Subsystem) nochmal darüber her und verwischt die Konturen, während der Text in einzelne Pixel umgerechnet wird.

        Fall 2: Die Mailadressen werden durch die gd-lib auf der Serverseite in eine Grafik umgerechnet, dabei werden keine Kanten verwischt, sondern scharfe Konturen erzeugt, weil das in der gd-lib einfach nicht vorgesehen ist. Das Ergebnis wird als Grafik übertragen, die der Browser und das OS Pixel für Pixel exakt wiedergeben, ohne darin nochmal irgendwelche Kanten zu "glätten".

        Stimmt. Werde mich dann mal auf die Suche nach einem freien Font machen. Habe mir da nicht so viele Gedanken gemacht. (Bin mir zwar auch sicher, dass da niemand was sagen würde, aber du hast Recht.)

        Ich glaube auch nicht, dass sich wirklich jemand daran stören würde. Aber wenn doch, gibt's Geschrei, und dann kann die Sache womöglich teuer werden. Sicher ist sicher. ;-)

        Aber wenigstens hast du einen hilfreichen Alternativtext.
        Eben. Und das andere ist ja nur eine Hilfe für die Firefox-Benutzer :)

        Na gut, irgendeinen Vorteil sollen die ja auch mal haben.

        Ciao,
         Martin

        --
        Rizinus hat sich angeblich als sehr gutes Mittel gegen Husten bewährt.
        1. hi Martin ッ,

          Vista glättet die Schriften, das stimmt, und die gdlib von PHP macht so einen Unsinn nicht.
          Ja, okay. Aber wo liegt dann der Hund begraben? War halt so die erste Möglichkeit, die mir eingefallen ist.

          was ist daran so unverständlich?

          Fall 1: Die Mailadressen stehen als Text auf der Seite. Dein Browser stellt sie also auch als Text dar, ergo fällt das Betriebssystem (bzw. das Grafik-Subsystem) nochmal darüber her und verwischt die Konturen, während der Text in einzelne Pixel umgerechnet wird.

          Fall 2: Die Mailadressen werden durch die gd-lib auf der Serverseite in eine Grafik umgerechnet, dabei werden keine Kanten verwischt, sondern scharfe Konturen erzeugt, weil das in der gd-lib einfach nicht vorgesehen ist. Das Ergebnis wird als Grafik übertragen, die der Browser und das OS Pixel für Pixel exakt wiedergeben, ohne darin nochmal irgendwelche Kanten zu "glätten".

          Jaa, das ist schon klar.
          Aber ich meinte es anders :P
          Lokal sehen die GRAFIKEN anders aus als auf dem Webserver. ;)
          Das Text durch ClearType etc. geglättet wird ist mir auch klar, aber dass die *Grafiken* nicht gleich sind, hat mich halt gewundert.
          Beweis gefällig? Beispiel ist hier online.

          Stimmt. Werde mich dann mal auf die Suche nach einem freien Font machen. Habe mir da nicht so viele Gedanken gemacht. (Bin mir zwar auch sicher, dass da niemand was sagen würde, aber du hast Recht.)

          Ich glaube auch nicht, dass sich wirklich jemand daran stören würde. Aber wenn doch, gibt's Geschrei, und dann kann die Sache womöglich teuer werden. Sicher ist sicher. ;-)

          Ja, aber schau dir mal das Beispiel an … der kostenlose Font ist noch viel mehr verunstaltet. Da sieht Calibri noch deutlich besser aus.

          Aber wenigstens hast du einen hilfreichen Alternativtext.
          Eben. Und das andere ist ja nur eine Hilfe für die Firefox-Benutzer :)

          Na gut, irgendeinen Vorteil sollen die ja auch mal haben.

          Ja :)
          Das wird eins *der* Argumente für Firefox werden - auf www.abi10-asg.de, der Website, die jeder täglich besucht, werden die E-Mail-Adressen "normal" angezeigt! Das ist doch wirklich ein unschlagbares Argument! *g

          —Gabriel

          1. Hallo,

            Jaa, das ist schon klar.
            Aber ich meinte es anders :P
            Lokal sehen die GRAFIKEN anders aus als auf dem Webserver. ;)

            oh, dann habe ich dich komplett missverstanden - ich dachte wirklich, es ginge um das unterschiedliche Aussehen, ob die Zeichen als Text oder als Grafik erzeugt werden.

            Das Text durch ClearType etc. geglättet wird ist mir auch klar, aber dass die *Grafiken* nicht gleich sind, hat mich halt gewundert.

            Mich auch ...

            Beweis gefällig? Beispiel ist hier online.

            Ach du Sch...

            Abgesehen davon, dass der IE für die vom Webserver generierten Grafiken (mit data:-URL) nichts anzeigt und ich erst einen anderen bemühen musste - dann sehe ich, dass dein Webhoster die Schriften Arial und Geo Sans übel verunstaltet (fast bis zur Unleserlichkeit), während Calibri sauber und ordentlich erscheint. Dein lokaler Testserver produziert dagegen aus Calibri ein sauberes Schriftbild, Geo Sans ist gerade noch erträglich, während ich bei dem, was aus Arial produziert wird, früher oder später Augenkrebs kriege.

            Kann es sein, dass die gd-lib auf deinem lokalen Server auch die Rendering-Engine des Betriebssystems benutzt, so dass deshalb die Antialiasing-Algorithmen des Systems greifen? Sieht mir fast danach aus. Aber warum dann so unterschiedlich je nach Schriftart? Seltsam ...

            Ja, aber schau dir mal das Beispiel an … der kostenlose Font ist noch viel mehr verunstaltet. Da sieht Calibri noch deutlich besser aus.

            Um nicht zu sagen, es ist die einzige der drei Schriften, die auf beiden Systemen sauber und scharf abgebildet wird.

            Firefox-Benutzer :)
            Na gut, irgendeinen Vorteil sollen die ja auch mal haben.
            Das wird eins *der* Argumente für Firefox werden - auf www.abi10-asg.de, der Website, die jeder täglich besucht, werden die E-Mail-Adressen "normal" angezeigt! Das ist doch wirklich ein unschlagbares Argument! *g

            Naja, ein Darstellungsvorteil auf *einer* konkreten Seite kann mich noch nicht überzeigen, auf Firefox umzusteigen. So masochistisch bin ich dann doch nicht veranlagt.

            Ciao,
             Martin

            --
            F: Was sagt die kleine Kerze zur großen Kerze?
            A: Ich gehe heute nacht aus!
  2. function _email($address, $type = 'text', $link = 0, $bgcolor = array(255,255,255)){

    $pos_at = strpos($address, '@');
      $substr1 = substr($address, 0, $pos_at);
      $substr2 = substr($address, $pos_at + 1);
      $pos_dot = strrpos($substr2, '.');
      $substr3 = substr($substr2, 0, $pos_dot);
      $substr4 = substr($substr2, $pos_dot + 1);
      $address_difficult = $substr1 . ' [an] ' . $substr3 . ' [.] ' . $substr4; // wird für alternativ-Text verwendet (für IE etc., die kein data: unterstützen)

    switch($type){
        case 'text':
          return ($link == 0) ? $address : '<a href="mailto:'.$address.'">'.$address.'</a>';
        case 'graphic':
          $textsize = imagettfbbox(10, 0, 'fonts/calibri.ttf', $address);
          $width = $textsize[2] - $textsize[0];
          $height = $textsize[1] - $textsize[7];
          $im = imagecreatetruecolor($width + 5, $height);
          $background_color = ImageColorAllocate ($im, 255, 0, 255);
          ImageFill($im, 0, 0, $background_color);

    /und hier kommt der clue:/
    imagecolortransparent($im, $background_color);

    $black = ImageColorAllocate ($im, 0, 0, 0);
          imagettftext($im, 10, 0, 0, $height - 3, $black, 'calibri.ttf', $address);
          $tmpfname = tempnam ("/tmp", "FOO");
          Imagegif($im,$tmpfname); the file
          $temp = fopen($tmpfname,"rb");for reading binary
          $buffer = fread($temp,filesize($tmpfname));
          fclose($temp);the file
          unlink($tmpfname); with the file, discard
          $out = base64_encode($buffer); // encodieren
          return '<img src="data:image/gif;base64,'.chunk_split($out).'" alt="'.$address_difficult.'" />';
      }
    }

      
    So, statt ebenfalls nur zu kritisieren, sollst du von mir mal ausnahmsweise eine Lösung bekommen. Denke bitte trotzdem über Martins Vorschläge nach.  
      
    Das hier hilft dir vielleicht ebenfalls weiter: http://de.php.net/manual/en/function.imagecolortransparent.php  
      
    mfg,  
    Marc
    
    1. Hallo Marc シ,

      imagecolortransparent($im, $background_color);

      Aaah, okay. Danke :))
      Habe nur imagesavealpha im Manual gefunden, aber das ist ja nur für PNGs (hätte ich irgendwie auch selber drauf kommen können …).

      Jetzt hab ich aber imagecolortransparent eingebaut - und es klappt. Super :)

      So, statt ebenfalls nur zu kritisieren, sollst du von mir mal ausnahmsweise eine Lösung bekommen. Denke bitte trotzdem über Martins Vorschläge nach.

      Mach ich.

      Das hier hilft dir vielleicht ebenfalls weiter: http://de.php.net/manual/en/function.imagecolortransparent.php

      Da wär ich vielleicht auch grad noch selber drauf gekommen ;)

      —Gabriel [mailto:willi292@web.de@title=﹫]