2D-Grafik Erstellungsdatum JPG direkt aus Header (EXIF) auslesen.

washpuda54

Mitglied
Hallo,

ich hoffe man kann mir weiterhelfen. Ich möchte mehrere JPG- Bilder nach dem Datum sortieren. Eine Möglichkeit besteht ja darin, das Änderungsdatum der Datei zu verwenden, was leider nicht immer dem tatsächlichen Aufnahmedatum des Bildes entspricht. Die Bessere Alternative besteht darin, das Datum direkt aus den Metadaten des JPG´s auszulesen. Dies soll möglichst performant und wichtig ohne Fremde Bibliotheken erfolgen.

Ich habe nachfolgendes Beispiel zum auslesen der Bildgröße direkt aus der Datei im Netz gefunden, was echt perfekt ist. Leider finde ich nirgendwo eine Information wie ich analog das Erstellungsdatum auslesen kann. Ich habe schon stundenlang nach einer Lösung gesucht. Vielleicht hat jemand eine Idee, ich bin schon am verzweifeln.

Code:
public static Dimension getJPEGDimension(File f) throws IOException {
    FileInputStream fis = new FileInputStream(f);

    // check for SOI marker
    if (fis.read() != 255 || fis.read() != 216)
        throw new RuntimeException("SOI (Start Of Image) marker 0xff 0xd8 missing");

    Dimension d = null;

    while (fis.read() == 255) {
        int marker = fis.read();
        int len = fis.read() << 8 | fis.read();

        if (marker == 192) {
            fis.skip(1);
            int height = fis.read() << 8 | fis.read();
            int width = fis.read() << 8 | fis.read();
            d = new Dimension(width, height);
            break;
        }
        fis.skip(len - 2);
    }

    fis.close();
    return d;
}
 

Thallius

Top Contributor
Dein Code holt sich die Daten nicht aus dem EXIF sondern aus dem Baseline DCT des JPEG Files. Um an das ERstellungsdatum des Bildes zu kommen must du aber die Exif lesen. Das ist ungleich komplizierter. Dazu solltest du am besten eine EXIF library benutzen. Wenn Du danach googlest wirst du sicher ein paar finden.

Gruß

Claus
 

washpuda54

Mitglied
Vielen Dank Claus, für die Schnelle Antwort.

die Verwendung von externen Bibliotheken möchte ich vermeiden. Ich habe heute noch etwas an einer Lösung gebastelt und bin auf die nachfolgende Lösung gekommen. Ich weiß, dass dies nicht der ideale weg ist und vielleicht hat ja noch jemand eine IDEE wie man dies besser lösen kann.

Beim Betrachten von mehreren JPG-Bildern (unterschiedliche Kameras und Hersteller) im Hex-Editor ist mir aufgefallen, dass das Datum, mehrfach als Text und immer in der gleichen Formatierung (yyyy:MM:dd HH:mm:ss) enthalten ist (wenn die Bilder mit einer Kamera erstellt wurden).

Ich durchsuche die ersten 5000 Bytes des nach diesem Muster. Wenn ich diesen String nicht finde, verwende ich das Datum der Datei. Dies ist sehr fix, 1000 Bilder unter 5 Sekunden. Bei den 11 Bildern wo das Datum nicht korrekt ausgelesen wurde, wird auch unter Windows und Eigenschaften als Erstellungsdatum nur das Dateidatum angezeigt.

(das nachfolgende Beispiel berücksichtigt nur Bilder mit Jahr 2xxx).

Code:
public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");

    public static long getDateFromJpgHeader(File imgFile){

        try (FileInputStream fis = new FileInputStream(imgFile);) {
            if (fis.read() != 255 || fis.read() != 216) {     // check for SOI marker
                throw new IllegalArgumentException("SOI (Start Of Image) marker 0xff 0xd8 missing");
            }

            byte[] bytes = new byte[19];  bytes[0] = 50; // array for date 

            for(int i = 0; i < (imgFile.length() > 5000 ? 5000: imgFile.length()) ; i++) {       
                if(fis.read() == 0x32) {
                    for(int j = 1; j < 19; j++) {
                        bytes[j] =  (byte) fis.read();
                    }

                    if(isValidTime(bytes)) {
                        String dateStr = new String(bytes);
                        try {
                            return sdf.parse(dateStr).getTime();
                        } catch (ParseException e) {
                            e.printStackTrace();
                            return imgFile.lastModified();
                        }
                    }else {
                        fis.skip(-18);  // reset pointer in file
                    }
                }
            }
        } catch (IOException e) {   
            e.printStackTrace();   
        }
        return imgFile.lastModified();
    }


    private static boolean isValidTime(byte[] bytes) {
        return (bytes[1] > 47 && bytes[1] < 58)             // y
                && (bytes[2] > 47 && bytes[2] < 58)            // y
                && (bytes[3] > 47 && bytes[3] < 58)            // y
                && (bytes[4] == 58)                            // :
                && (bytes[5] > 47 && bytes[5] < 58)            // M
                && (bytes[6] > 47 && bytes[6] < 58)            // M
                && (bytes[7] == 58)                            // :
                && (bytes[8] > 47 && bytes[8] < 58)            // d
                && (bytes[9] > 47 && bytes[9] < 58)            // d
                && (bytes[10] == 32)                        // space   
                && (bytes[11] > 47 && bytes[11] < 58)        // H
                && (bytes[12] > 47 && bytes[12] < 58)        // H   
                && (bytes[13] == 58)                        // :
                && (bytes[14] > 47 && bytes[14] < 58)        // m   
                && (bytes[15] > 47 && bytes[15] < 58)        // m
                && (bytes[16] == 58)                        // :
                && (bytes[17] > 47 && bytes[17] < 58)        // s
                && (bytes[18] > 47 && bytes[17] < 58);        // s
    }
 

Thallius

Top Contributor
Warum nimmst du nicht einfach immer einen 10 Byte langen Eintrag und versucht in mit dem simpleDateformatter zu parsen. Ob das schneller ist weiß ich nicht aber auf jeden Fall ist es schöner als dieses Konstrukt.

Gruß

Claus
 

washpuda54

Mitglied
Prinzipiell mach ich dass ja. nur lasse ich alle Einträge aus, die nicht mit einer zwei (Jahrtausend) beginnen und somit sowieso kein Datum sein können. Dadurch wird die Geschwindigkeit deutlich erhöht.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
MiMa Erstellungsdatum einer Datei Allgemeine Java-Themen 10
I Dateiattribute (Erstellungsdatum aus Datei auslesen) Allgemeine Java-Themen 7
D erstellungsdatum von .jpg herausbekommen Allgemeine Java-Themen 4
D Erstellungsdatum eines Ordners ermitteln Allgemeine Java-Themen 2
F Java Code ausführen direkt nach Anmelden in Windows Allgemeine Java-Themen 2
B Applikation ohne (direkt)Java installiert zu haben auszuführen Allgemeine Java-Themen 8
N ZIp datei direkt im eclipse speichern Allgemeine Java-Themen 4
HarleyDavidson Input/Output Heruntergeladene Datei direkt nach dem Download öffnen ohne zu speichern Allgemeine Java-Themen 1
X Eclipse Direkt von der Soundkarte aufnehmen? Allgemeine Java-Themen 3
H Mit Ant erstelltes jar funktioniert nicht wie direkt in Eclipse Allgemeine Java-Themen 8
C Kapselung Warum graift man auf Variablen nur über Methoden und nich direkt zu? Allgemeine Java-Themen 10
J CMD direkt in Java ausführen Allgemeine Java-Themen 11
H JPanel direkt in PDF umwandeln Allgemeine Java-Themen 2
G Prozess direkt starten beim Start des Appservers Allgemeine Java-Themen 3
B ZipDatei direkt online auslesen? Allgemeine Java-Themen 8
L Speicherplatz eies RIESEN objektes direkt wieder freigeben Allgemeine Java-Themen 5
G Direkt in ein Objekt deserialisieren Allgemeine Java-Themen 5
M Feld initialisieren, direkt oder Konstruktor Allgemeine Java-Themen 2
R Grafiken. direkt zeichnen Allgemeine Java-Themen 5
S Postscript Datei direkt ausdrucken? Allgemeine Java-Themen 5
S Drucker druckt nicht (Postscript direkt an Drucker) Allgemeine Java-Themen 5
S Änderungen im Source-Code direkt verwenden können? Allgemeine Java-Themen 3
G Licence-Header für InHouse entwickelten Source Allgemeine Java-Themen 8
C Itext Voralagen Header Footer -> PDF Allgemeine Java-Themen 0
V C-Header Datei aus .java File herstellen Allgemeine Java-Themen 10
D mp3 Header - wo könnte der Fehler liegen? Allgemeine Java-Themen 3
G Javamail Nachricht senden: Betreff und Header fehlen Allgemeine Java-Themen 4
S MP3 Header auslesen Allgemeine Java-Themen 7
lumo Row Header ist public, zeigt die funktion aber nicht public Allgemeine Java-Themen 8
R Header per Java senden Allgemeine Java-Themen 6
N JTable & JScrollPane - Wie den Header anpassen? Allgemeine Java-Themen 4
S Homepage-Header nach Tageszeit autom. ändern? Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben