Ändern der Größe von Android-Bildern und Beibehalten von EXIF-Daten (Ausrichtung, Drehung usw.)

Lesezeit: 6 Minuten

Benutzer-Avatar
Mike Repass

Wenn Ihre Android-App die Gerätekamera verwendet, um ein Bild aufzunehmen und es dann in der Größe ändert (dies ist sehr, sehr häufig, um die Größe für das Hochladen zu reduzieren), erkennen Sie möglicherweise nicht, dass dieser Vorgang zur Größenänderung erfolgt Streifen die Exif-Metadaten.

Dies kann zu Problemen führen, insbesondere wenn das betreffende Gerät auf das ‘Orientation’-Tag angewiesen ist, um das Bild korrekt aufrecht anzuzeigen.

Verschiedene Android-Geräte handhaben die Kamera-/Bilddrehung auf unterschiedliche Weise – mein treuer alter Nexus One scheint das Bild immer sofort nach der Aufnahme zu drehen, sodass der native Inhalt der Datei beim Betrachten immer „aufrecht“ ist.

Andere Geräte (insbesondere Samsung-Telefone in meinen Tests) tun dies jedoch nicht den Inhalt der Bilddatei drehen – sie setzen stattdessen das Exif-Tag ‘Orientation’. Immer wenn das Bild später angezeigt wird, sollte der relevante Bildcode das Vorhandensein des Ausrichtungs-Tags erkennen und das Bild entsprechend drehen. Wenn Sie jedoch eine Bitmap-Verarbeitung an dem Bild vorgenommen und es in einer neuen Datei gespeichert haben, gehen alle diese Exif-Daten verloren.

Zusätzlich zu den Orientierungsdaten können Sie auch andere wertvolle Metadaten wie Marke/Modell usw. verlieren.

Dies verwirrte mich einige Wochen lang (das Bild erscheint aufrecht, wenn es in der Telefongalerie angezeigt wird, kommt dann aber mit schlechter Ausrichtung und ohne offensichtliche Metadaten auf meinem Server an). Ich füge diese Selbstfrage hier hinzu, um anderen zu helfen. Dieser Blogbeitrag war sehr hilfreich:

Android-Bildgröße ändern, ohne EXIF-Informationen zu verlieren

Benutzer-Avatar
Mike Repass

Soweit ich das beurteilen kann, gibt es das nein Mechanismus, um die Metadaten automatisch beizubehalten oder sogar Schnappschüsse von allem, was vorhanden ist, und in großen Mengen zu übertragen.

Vielmehr müssen Sie anscheinend explizit nach bestimmten Eigenschaften suchen und diese mithilfe des ExifInterface selbst in die neue Bilddatei kopieren.

http://developer.android.com/reference/android/media/ExifInterface.html

Also sowas wie:

ExifInterface oldExif = new ExifInterface(oldImagePath);
String exifOrientation = oldExif.getAttribute(ExifInterface.TAG_ORIENTATION);

if (exifOrientation != null) {
   ExifInterface newExif = new ExifInterface(imagePath);
   newExif.setAttribute(ExifInterface.TAG_ORIENTATION, exifOrientation);
   newExif.saveAttributes();
}

  • Sie sind mein Held.

    – Alysson Alexandre

    13. Juli 2021 um 18:14 Uhr

Für die Faulen hier eine wiederverwendbare Funktion:

public static void copyExif(String oldPath, String newPath) throws IOException
{
    ExifInterface oldExif = new ExifInterface(oldPath);

    String[] attributes = new String[]
    {
            ExifInterface.TAG_APERTURE,
            ExifInterface.TAG_DATETIME,
            ExifInterface.TAG_DATETIME_DIGITIZED,
            ExifInterface.TAG_EXPOSURE_TIME,
            ExifInterface.TAG_FLASH,
            ExifInterface.TAG_FOCAL_LENGTH,
            ExifInterface.TAG_GPS_ALTITUDE,
            ExifInterface.TAG_GPS_ALTITUDE_REF,
            ExifInterface.TAG_GPS_DATESTAMP,
            ExifInterface.TAG_GPS_LATITUDE,
            ExifInterface.TAG_GPS_LATITUDE_REF,
            ExifInterface.TAG_GPS_LONGITUDE,
            ExifInterface.TAG_GPS_LONGITUDE_REF,
            ExifInterface.TAG_GPS_PROCESSING_METHOD,
            ExifInterface.TAG_GPS_TIMESTAMP,
            ExifInterface.TAG_IMAGE_LENGTH,
            ExifInterface.TAG_IMAGE_WIDTH,
            ExifInterface.TAG_ISO,
            ExifInterface.TAG_MAKE,
            ExifInterface.TAG_MODEL,
            ExifInterface.TAG_ORIENTATION,
            ExifInterface.TAG_SUBSEC_TIME,
            ExifInterface.TAG_SUBSEC_TIME_DIG,
            ExifInterface.TAG_SUBSEC_TIME_ORIG,
            ExifInterface.TAG_WHITE_BALANCE
    };

    ExifInterface newExif = new ExifInterface(newPath);
    for (int i = 0; i < attributes.length; i++)
    {
        String value = oldExif.getAttribute(attributes[i]);
        if (value != null)
            newExif.setAttribute(attributes[i], value);
    }
    newExif.saveAttributes();
}

  • Wenn Sie die Größe ändern, denken Sie daran, TAG_IMAGE_LENGTH und TAG_IMAGE_WIDTH zu aktualisieren oder nicht zu kopieren

    – Desmond Lua

    25. Oktober 2016 um 7:11 Uhr

Benutzer-Avatar
Das Ö

Wie andere angegeben haben, müssen Sie die Exif-Daten vom Originalbild in das endgültige Bild mit geänderter Größe kopieren. Die Sanselan Android-Bibliothek ist dafür normalerweise am besten geeignet. Je nach Version des Android-Betriebssystems beschädigt das ExifInterface manchmal die Exifdaten.

Darüber hinaus verarbeitet das ExifInterface auch eine begrenzte Anzahl von Exif-Tags – nämlich nur die Tags, die es „kennt“. Sanselan hingegen behält alle Exiftags und Markierungsnotizen.

Hier ist ein Blogbeitrag, der zeigt, wie man Sanselan zum Kopieren von Bilddaten verwendet:

Kopieren von Exif-Metadaten mit Sanselan

Übrigens, auf Android neige ich auch dazu, die Bilder zu drehen und das Orientierungs-Exiftag zu entfernen. Beispielsweise setzte die Kamera auf einem Nexus S mit Android 4.03 ein Orientierungs-Tag in den Exif-Metadaten, aber die Webansicht ignorierte diese Informationen und zeigte das Bild falsch an. Leider ist das Drehen der eigentlichen Bilddaten und das Entfernen des Exiforientation-Tags die einzige Möglichkeit, jedes Programm dazu zu bringen, Bilder korrekt anzuzeigen.

  • Danke Theo, ich schätze diese Antwort und habe sie akzeptiert. Haben Sie einen Link für weitere Informationen zu diesem Thema “Abhängig von der Android-Betriebssystemversion beschädigt das ExifInterface manchmal die EXIF-Daten.”

    – Mike Repass

    13. Dezember 2012 um 0:34 Uhr

  • Es basiert auf meiner Erfahrung, und ich bin nicht die erste Person, die feststellt, dass ExifInterface fehlerhaft ist [1]. Je nachdem, wie viel Zeit ich in den nächsten Tagen habe, werde ich vielleicht ein paar anschauliche Fälle zusammenstellen und berichten. [1] mail-archives.apache.org/mod_mbox/commons-issues/201106.mbox/…

    – Das Ö

    13. Dezember 2012 um 22:07 Uhr

  • @Theo Ich habe Ihren Code getestet und er scheint die meisten/alle Attribute für einige Geräte und Bilder zu kopieren. Beispiele für Attribute, die sich nicht gut kopieren lassen: ISOSpeedRatings, FocalLength, FNumber . Kannst du bitte erklären, wie das sein kann? Ich habe es auf einem Nexus 4-Gerät mit Android 4.4.2 getestet und das auf der Originaldatei und der neuen Datei erstellte ExifInterface verglichen.

    – Android-Entwickler

    11. Februar 2014 um 9:03 Uhr

Es ist bereits 2019 und es gibt immer noch keine bessere Antwort als die von @prom85, Mike Repass und Theo.

Im Jahr 2016 stellte das Android-Team vor ExifInterface-Unterstützungsbibliothek Was kann die beste Option sein, wenn Sie ein konsistentes Verhalten zwischen Android-Versionen haben möchten. Am Ende habe ich eine Teilmenge von Tags erstellt ExifInterface#EXIF_TAGS (Quellcode) und ich iteriere einfach über diese Teilmenge, um Metadaten aus der Eingabedatei zu extrahieren und sie in einer Ausgabe festzulegen. Wenn Sie jemals aufgefordert werden, alle Tags zu kopieren, empfehle ich Ihnen, dies nicht zu tun! Der Wert einiger Tags muss ohnehin entsprechend aktualisiert werden (z TAG_IMAGE_LENGTH und TAG_IMAGE_WIDTH). Persönlich habe ich immer wieder Fragen gestellt, warum wir überhaupt alle Metedata-Daten speichern müssen (es unterscheidet sich je nach Gerät und Kamera, die Sie sowieso verwenden), und wir haben festgestellt, dass GPS-Standort- und Datums- / Uhrzeitdaten ebenfalls gespeichert werden müssen.

Warum ändern Sie nicht einfach die ExifInterface-Quelle und fügen Ihre eigene Implementierung hinzu, um das Lesen/Schreiben in großen Mengen zu unterstützen, sodass Sie nicht Tag für Tag angeben müssen. Hier ist ein Ausschnitt dessen, was ich tun würde.

Neue Methode hinzufügen, um die internen Attribute verfügbar zu machen:

public HashMap<String, ExifAttribute>[] getAllAttributes() {
    return mAttributes;
}

Fügen Sie eine neue Methode hinzu, um alle Attribute festzulegen:

public void setAttributes(HashMap<String, ExifAttribute>[] attributes) {
    for (int i = 0 ; i < EXIF_TAGS.length; ++i) {
        mAttributes[i] = attributes[i];
    }
}

Verwenden Sie es dann so, um Exif beizubehalten und in einer anderen Datei zu speichern

// Grab all the original exif attributes from an image file and save to memory or wherever
let attributes = ExifInterface2(sourceImagePath).attributes

// Later on you can just copy those attributes to another image
ExifInterface2(destImagePath)
    .setAttributes(attributes)
    .saveAttributes();

1180450cookie-checkÄndern der Größe von Android-Bildern und Beibehalten von EXIF-Daten (Ausrichtung, Drehung usw.)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy