Multi: Bildformat aus Blob extrahieren

Hi,
ich hab ein Problem. Ich hab Bilder in einer Datenbank gespeichert.
Auslesen und Ausgeben ist ja kein Problem, aber gibt es ne Möglichkeit, festzustellen, ob es ein Gif, ein Jpeg oder Png ist?

Es sollte ja möglich sein, die ersten paar bytes auszulesen, da stehts ja, aber wenns dafür was fertiges gibt, wär das ne feine Sache.

Es geht mir darum, den richtigen Content-Type auszugeben.

thx4hlp

  1. Nachtrag:
    das Blob ist in einer Mysql-DB und das Auslesen erfolgt per PHP

    1. Ich würde den MimeType bereits beim speichern in die DB ermitteln und im extra Feld speichern.

      Ansonsten: wenn du PHP >= 5.3.0 incl. FileInfo-Extension zur Verfügung hast.
      http://www.php.net/manual/en/function.finfo-buffer.php

      Sonst bleibt dir nur noch, temp. abspeichern und mit getimagesize() ermitteln.

      1. Ich würde den MimeType bereits beim speichern in die DB ermitteln und im extra Feld speichern.

        Tja, dummerweise wird der Softwarehersteller nicht wegen mir seine Datenbankstruktur ändern ...

        Ansonsten: wenn du PHP >= 5.3.0 incl. FileInfo-Extension zur Verfügung hast.
        http://www.php.net/manual/en/function.finfo-buffer.php

        Schau ich mir an. Da eigener Server, nur ein relatives Problem ;)

        Sonst bleibt dir nur noch, temp. abspeichern und mit getimagesize() ermitteln.

        Das wollte ich vermeiden, aber hab ich als letzte Lösung im Hinterkopf.
        Danke für die Hilfe :)

        1. Ob das jetzt alle Images abdeckt, kann ich nicht versprechen.

          [code=sql]
          SELECT
              CASE
                  WHEN SUBSTR(data, 1, 3) = 'GIF' THEN 'image/gif'
                  WHEN SUBSTR(data, 2, 3) = 'PNG' THEN 'image/png'
                  WHEN SUBSTR(data, 7, 4) = 'JFIF' THEN 'image/jpeg'
                  ELSE ''
              END mime
          FROM tabelle
          [/code]

          1. Hallo,

            SELECT

            CASE
                    WHEN SUBSTR(data, 1, 3) = 'GIF' THEN 'image/gif'
                    WHEN SUBSTR(data, 2, 3) = 'PNG' THEN 'image/png'

              
            plus/minus-eins-Problem? Der String "GIF87a" oder "GIF89a" steht ganz am Anfang, also ab Index 0, und "PNG" steht ab Dateiindex 1.  
              
            Ciao,  
             Martin  
            
            -- 
            Die Natur ist gnädig: Wer viel verspricht, dem schenkt sie zum Ausgleich ein schlechtes Gedächtnis.  
            Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
            
            1. plus/minus-eins-Problem? Der String "GIF87a" oder "GIF89a" steht ganz am Anfang, also ab Index 0, und "PNG" steht ab Dateiindex 1.

              MySQL SUBSTR() berechnet den Index ab 1 nicht (wie etwa PHP) ab 0.

              1. Hallo,

                plus/minus-eins-Problem? Der String "GIF87a" oder "GIF89a" steht ganz am Anfang, also ab Index 0, und "PNG" steht ab Dateiindex 1.
                MySQL SUBSTR() berechnet den Index ab 1 nicht (wie etwa PHP) ab 0.

                tatsächlich? Pfui, das ist ja pervers ...

                So long,
                 Martin

                --
                Drei Sachen vergesse ich immer wieder: Telefonnummern, Geburtstage und ... äääh ...
                Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
                1. tatsächlich? Pfui, das ist ja pervers ...

                  Ist bei allen mir bekannten SQL-Dialekten so.

                  1. Hello,

                    tatsächlich? Pfui, das ist ja pervers ...

                    Ist bei allen mir bekannten SQL-Dialekten so.

                    Nicht nur bei SQL-Dialekten, auch bei XBase und anderen.

                    Liebe Grüße aus dem schönen Oberharz

                    Tom vom Berg

                    --
                     ☻_
                    /▌
                    / \ Nur selber lernen macht schlau
                    http://bergpost.annerschbarrich.de
                2. Hello,

                  plus/minus-eins-Problem? Der String "GIF87a" oder "GIF89a" steht ganz am Anfang, also ab Index 0, und "PNG" steht ab Dateiindex 1.
                  MySQL SUBSTR() berechnet den Index ab 1 nicht (wie etwa PHP) ab 0.

                  tatsächlich? Pfui, das ist ja pervers ...

                  Das machen alle Datenbanken, die ich kenne, über ihre Textschnittstellen so.

                  Der Index 0 bedeutet: gesuchter String ist nicht enthalten

                  Liebe Grüße aus dem schönen Oberharz

                  Tom vom Berg

                  --
                   ☻_
                  /▌
                  / \ Nur selber lernen macht schlau
                  http://bergpost.annerschbarrich.de
          2. WHEN SUBSTR(data, 7, 4) = 'JFIF' THEN 'image/jpeg'

            Zumindest bei Bildern mit Exif-Erweiterung klappt das nicht. Ich habs zwar nur kurz getestet, weil ich das Bild jetzt erst abspeichere, dann per getimagesize() die nötigen Daten hole und die Datei dann umbenenne.

            Somit benutze ich nur Boardmittel von PHP und da das nur dann durchgeführt wird, wenn sich der Artikel geändert hat, ist es auch relativ egal ob es eine etwas schnellere Lösung gibt.

            1. WHEN SUBSTR(data, 7, 4) = 'JFIF' THEN 'image/jpeg'

              Zumindest bei Bildern mit Exif-Erweiterung klappt das nicht.

              Stimmt, der Exif-Header überschreibt, aber eine Gemeinsamkeit haben alle Jpegs.
              [code=sql]        WHEN HEX(SUBSTR(data, 1, 2)) = 'FFD8' THEN 'image/jpeg'
              [/code]

  2. Grüße,
    wenn es das nciht gibt, solltest du es schreiben :) so komplex ist es nciht, die header musst du ja nur unterscheiden können und die sind osgar bei wikipedia dokumentiert, sparere audi!
    MFG
    bleicher

    --
    __________________________-

    FirefoxMyth
    1. Hallo,

      wenn es das nciht gibt, solltest du es schreiben :) so komplex ist es nciht, die header musst du ja nur unterscheiden können und die sind osgar bei wikipedia dokumentiert, sparere audi!

      die Grafikformate zu erkennen, ist sicher nicht das Problem, erst recht nicht, wenn es wirklich nur die drei genannten sind. Aber soweit ich weiß, kann man BLOBs aus einer mySQL-DB nicht partiell auslesen, sondern nur komplett. Man würde also pro Bild mehrere hundert kB bewegen, obwohl die ersten vier Bytes schon genügen würden.

      Klar, das ist möglich und sehr einfach. Aber außerordentlich ineffizient.

      Ich finde übrigens den Vorschlag von DiBo33 sehr gut, den MIME-Type als separates Feld mit zu speichern. Für die schon in der DB existierenden Bilder müsste man das halt dann auf die beschriebene ineffiziente Weise nachtragen. Das wäre dann aber eine einmalige Operation.

      Ciao,
       Martin

      --
      Wenn der Computer wirklich alles kann,
      dann kann er mich mal kreuzweise.
      Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
      1. Grüße,

        Ich finde übrigens den Vorschlag von DiBo33 sehr gut, den MIME-Type als separates Feld mit zu speichern.

        ist das nicht die übliche/normale/immer verwendete Lösung?

        MFG
        bleicher

        --
        __________________________-

        FirefoxMyth
        1. Hi,

          Ich finde übrigens den Vorschlag von DiBo33 sehr gut, den MIME-Type als separates Feld mit zu speichern.
          ist das nicht die übliche/normale/immer verwendete Lösung?

          keine Ahnung, ob das üblich oder normal ist - ich finde es zumindest sinnvoll.

          Aber wenn Multi von dieser Voraussetzung ausgehen könnte, bräuchte er nicht zu fragen, oder?
          Wir müssen also annehmen, dass er den jetzigen ungünstigen DB-Entwurf entweder von Dritten erhalten hat und damit zurechtkommen muss, oder dass er selber irgendwann früher mal nicht ausreichend nachgedacht hat und nun die Quittung bekommt. Aber das ist im Moment völlig nebensächlich.

          So long,
           Martin

          --
          Wer im Glashaus sitzt, sollte Spaß am Fensterputzen haben.
          Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
        2. Hallo,

          Ich finde übrigens den Vorschlag von DiBo33 sehr gut, den MIME-Type als separates Feld mit zu speichern.
          ist das nicht die übliche/normale/immer verwendete Lösung?

          wenn man schon Bilder als BLOB abspeichert, wäre man sehr d***h, wenn man für Metadaten keine zusätzlichen Felder vorsähe.

          Freundliche Grüße

          Vinzenz

          1. wenn man schon Bilder als BLOB abspeichert, wäre man sehr d***h, wenn man für Metadaten keine zusätzlichen Felder vorsähe.

            http://www.openbravo.com/de/

            Dann erklär denen das doch. Bei einem solchen Kassensystem sind Bilder völlig Nebensache. Für den Onlineshop, den ich dazu programmiere aber nicht.

            Da ich aber sowieso mit der fremden Struktur leben muss, ist es völlig unerheblich, wieso die Metadaten nicht mitgespeichert wurden, sie sind einfach nicht da ;)

            1. Grüße,
              so nebensächliche frage - woz ubrauchst du die daten?
              die jedes mal zu ermitteln ist zwar fraglich, aber wenn du kontrolle hast, kannst du doch einfach dafür sogren, dass alle bilder gleciehs ofrmat haben? das ist oft der fall.
              MFG
              bleicher

              --
              __________________________-

              FirefoxMyth
              1. Grüße,
                so nebensächliche frage - woz ubrauchst du die daten?

                Ich übernehme die Daten aus dem Kassensystem-Bestand direkt in einen Onlineshop.

                die jedes mal zu ermitteln ist zwar fraglich, aber wenn du kontrolle hast, kannst du doch einfach dafür sogren, dass alle bilder gleciehs ofrmat haben? das ist oft der fall.

                Ich tendiere im Moment dahin, dass ich die Bilder auf die Festplatte speicher. Ich muss mir nur noch überlegen, wie ich das mache ohne jedesmal alle Bilder prüfen zu müssen ob schon vorhanden. Mal sehen ob in der Datenbank irgendwo eine Timestamp zu finden ist, wann der Artikel geändertt wurde, dann könnte ich diesen nutzen um festzustellen ob ich die Bilder neu generieren muss.

                Die Bilder sind aktuell im PNG-Format. Da ich aber nicht wissen kann, ob das beim nächsten Release so bleibt, will ich lieber gleich flexibel bleiben.

                1. Hi,

                  Ich tendiere im Moment dahin, dass ich die Bilder auf die Festplatte speicher.

                  Das würde ich auch machen.

                  Ich muss mir nur noch überlegen, wie ich das mache ohne jedesmal alle Bilder prüfen zu müssen ob schon vorhanden.

                  Du musst nicht jedes Mal alle Bilder prüfen, sondern nur das jeweils angeforderte.

                  Die Nutzung von mod_rewrite o.ä. bietet sich an, um nur bei nicht vorhandener Bilddatei ein Script aufzurufen, welches das Bild ausliest, ausgibt, und auf Platte speichert.

                  Mal sehen ob in der Datenbank irgendwo eine Timestamp zu finden ist, wann der Artikel geändertt wurde, dann könnte ich diesen nutzen um festzustellen ob ich die Bilder neu generieren muss.

                  Oder du versuchst dich an der Stelle einzuklinken, wo der Artikel geändert wird - und löschst dort einfach die ggf. bestehende Bilddatei, damit bei der nächsten Anforderung dann wieder das erzeugende Script aufgerufen wird, s.o.

                  MfG ChrisB

                  --
                  RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
                  1. Du musst nicht jedes Mal alle Bilder prüfen, sondern nur das jeweils angeforderte.

                    In der Übersicht können bis zu 50 Bilder angefordert werden, je nach Einstellung des Users.

                    Die Nutzung von mod_rewrite o.ä. bietet sich an, um nur bei nicht vorhandener Bilddatei ein Script aufzurufen, welches das Bild ausliest, ausgibt, und auf Platte speichert.

                    Ja, hab ich mir auch schon überlegt, ich will aber mod_rewrite bei meinem Systemnur als Option aber nicht als Vorraussetzung nutzen.

                    Oder du versuchst dich an der Stelle einzuklinken, wo der Artikel geändert wird - und löschst dort einfach die ggf. bestehende Bilddatei, damit bei der nächsten Anforderung dann wieder das erzeugende Script aufgerufen wird, s.o.

                    Auch das hab ich mir überlegt. Da das Kassensystem Scriptfähig ist, dürfte das machbar sein. Zumindest könnte das Kassensystem einen Flag setzen der von nem Cron-Job ausgewertet wird. das würde verhindern, dass beim Anlegen von vielen Prokdukten nacheinander jedesmal Zeit verbraucht wird obwohl nur ein Artikel geändert wurde.

                    Ich muss mir das nochmal genau überlegen, vom direkten Auslesen aus der Datenbank bin ich momentan komplett weg. Jezt schau ich mir die Scripting-Doku an ob ein Event existiert der nach dem Speichern des Artikels ausgelöst wird. Wenn ja, mach ich es damit.

                    Danke an den Schubs in die richtige Richtung.

                    1. Hi,

                      In der Übersicht können bis zu 50 Bilder angefordert werden, je nach Einstellung des Users.

                      Die im Idealfall alle schon auf Platte liegen, weil sie vorher bereits mindestens ein Mal angefordert wurden.

                      Die Nutzung von mod_rewrite o.ä. bietet sich an, um nur bei nicht vorhandener Bilddatei ein Script aufzurufen, welches das Bild ausliest, ausgibt, und auf Platte speichert.

                      Ja, hab ich mir auch schon überlegt, ich will aber mod_rewrite bei meinem Systemnur als Option aber nicht als Vorraussetzung nutzen.

                      mod_rewrite halte ich für Quasi-Standard.
                      Wer Webspace nutzt, wo dies nicht verfügbar ist, ist selber Schuld.

                      Ich halte absolut nichts davon, die sinnvollste Technik nicht einzusetzen, weil sie mit geringer Wahrscheinlichkeit nicht verfügbar sein könnte.
                      Man definiert Systemanforderungen, und dann hat der Nutzer sich darum zu kümmern, dass diese gegeben sind.

                      MfG ChrisB

                      --
                      RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?
                      1. Die im Idealfall alle schon auf Platte liegen, weil sie vorher bereits mindestens ein Mal angefordert wurden.

                        Richtig. Aber trotzdem müsste ich das jedesmal prüfen inkl. der Prüfung ob sich das Bild evtl. geändert hat.

                        mod_rewrite halte ich für Quasi-Standard.
                        Wer Webspace nutzt, wo dies nicht verfügbar ist, ist selber Schuld.

                        Ich halte absolut nichts davon, die sinnvollste Technik nicht einzusetzen, weil sie mit geringer Wahrscheinlichkeit nicht verfügbar sein könnte.
                        Man definiert Systemanforderungen, und dann hat der Nutzer sich darum zu kümmern, dass diese gegeben sind.

                        Dummerweise sehen manche Kunden das anders. Und so selten ist es in meinem Umfeld nicht, das mod_rewrite nicht aktiviert ist oder nur gegen Aufpreis. Wie solche (meist winzig kleinen) Hoster noch Kunden haben können, weiss ich nicht, aber einige dieser Kunden wollen nicht wechseln (Ist ein Kumpel ... da bin ich schon seit Jahren ... usw.)

                        Somit hab ich das System von Grundauf so aufgebaut, dass mod_rewrite optional ist. War nicht so viel Arbeit, macht aber IMO Sinn.

                        Zu meinem Problem: Ich werde jetzt in der Datenbank einen Trigger einsetzen, der beim Ändern von Produkten in eine andere Tabelle die Artikelnummer inkl. Zeitstempel schreibt. Und diese Datenbank wird per Cron abgefragt und dann die Bilder neu auf die Platte geschrieben.
                        Dadurch muss ich keine Änderung an der Kassensoftware vornehmen (gibt leider keinen Event, der ausgelöst wird, wenn ein Artikel geändert wird,also kein Script möglich) und der Shop muss sich nicht um die Bilder kümmern, der zeit einfach ne normale Bild-Ressource im img an.

                        Ich denke, das ist die beste Lösung. Wenn jemand nen besseren Vorschlag hat, immer her damit ;)

      2. Hello,

        die Grafikformate zu erkennen, ist sicher nicht das Problem, erst recht nicht, wenn es wirklich nur die drei genannten sind. Aber soweit ich weiß, kann man BLOBs aus einer mySQL-DB nicht partiell auslesen, sondern nur komplett. Man würde also pro Bild mehrere hundert kB bewegen, obwohl die ersten vier Bytes schon genügen würden.

        MMn geht das ganz normal mit der Substring-Funktion.

        Liebe Grüße aus dem schönen Oberharz

        Tom vom Berg

        --
         ☻_
        /▌
        / \ Nur selber lernen macht schlau
        http://bergpost.annerschbarrich.de
      3. Hallo,

        Aber soweit ich weiß, kann man BLOBs aus einer mySQL-DB nicht partiell auslesen, sondern nur komplett. Man würde also pro Bild mehrere hundert kB bewegen, obwohl die ersten vier Bytes schon genügen würden.

        was spricht gegen LEFT()? Selbstverständlich kann LEFT() auch mit den BLOB- und TEXT-Datemtypen umgehen.

        Dass das keine besonders gute Idee ist, um das Problem des OP zu lösen, hab' ich bereits angemerkt ...

        Freundliche Grüße

        Vinzenz

        1. Hi,

          Aber soweit ich weiß, kann man BLOBs aus einer mySQL-DB nicht partiell auslesen, sondern nur komplett. Man würde also pro Bild mehrere hundert kB bewegen, obwohl die ersten vier Bytes schon genügen würden.
          was spricht gegen LEFT()? Selbstverständlich kann LEFT() auch mit den BLOB- und TEXT-Datemtypen umgehen.

          das war mir nicht klar; ich dachte, diese Funktionen könnten nur mit "echten" String-Typen umgehen. Dann ist auch Toms Anmerkung ein Posting weiter oben ein Schritt in die richtige Richtung.

          Dass das keine besonders gute Idee ist, um das Problem des OP zu lösen, hab' ich bereits angemerkt ...

          Richtig, das sehe ich auch so. Ich betrachte das auch nur als Hilfskonstruktion, um die Metainformationen nachträglich zu generieren, die von Anfang an in der DB hätten sein sollen - obwohl man andererseits so nicht von MIME-Typen abhängig wäre, die möglicherweise falsch sind.

          Ciao,
           Martin

          --
          "Drogen machen gleichgültig."
           - "Na und? Mir doch egal."
          Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
      4. Klar, das ist möglich und sehr einfach. Aber außerordentlich ineffizient.

        Ich muss das Bild ja sowieso komplett einlesen um es auszugeben. Da kann ich auch erstmal ein paar Byte überprüfen um welches Format es sich handelt.

        Schau ich mir an, wie ich das umsetze. Wäre halt schön gewesen wenn da schon jemand was fertiges hätte, würde Zeit sparen *g*

        1. Hi,

          Ich muss das Bild ja sowieso komplett einlesen um es auszugeben.

          Und dich selber um HTTP-Caching kümmern, wenn du es vernünftig umsetzen willst - eine Aufgabe, die sonst auch der Webserver übernehmen würde, wenn die Bilder da liegen würden, wo sie hin gehören, im Dateisystem.

          Wäre halt schön gewesen wenn da schon jemand was fertiges hätte, würde Zeit sparen *g*

          getimagesize ist fertig.

          php://memory existiert, wenn nicht extra eine Temp-Datei erstellt werden soll. (Geht natürlich zu Lasten des RAM.)

          MfG ChrisB

          --
          RGB is totally confusing - I mean, at least #C0FFEE should be brown, right?