2014-02-19 5 views
7

Ich habe eine App für Android 4.0 und höher entwickelt. (Die App unterstützt keine Android-Versionen unter 4.0 [Ice Cream Sandwich]).Android - Wie erhalte ich DPI (dots per inch) von JPEG-Dateien beim programmgesteuerten Laden oder Speichern?

Die Frage bezieht sich auf (Druck) DPI verschiedener Bilder (für zB JPEG oder PNG) Format.

Diese Frage bezieht sich NICHT auf SCREEN DPI oder Größen verschiedener Android-Geräte. Es bezieht sich auch NICHT darauf, das Bitmap auf dem Gerät in Bildschirmgröße anzuzeigen.

Ich verwende den folgenden Code, um die Bilddatei in 'Bitmap' zu laden. Dann habe ich es mit jpegCompression zugeschnitten und in eine andere Datei im JPEG-Format gespeichert. Ich war in der Lage, dies durch den folgenden Code zu tun, aber ich bin nicht in der Lage, DPI geladen zu bekommen oder die DPI der gespeicherten Bilddatei einzustellen.

Also habe ich zwei Fragen.

1) Wie kann ich die (Druck) DPI aus der JPEG-Datei erhalten, nachdem oder während sie in 'Bitmap' geladen wurde?

2) Wie kann ich beim Speichern der neu generierten 'Bitmap' die DPI erneut in der JPEG-Datei einstellen?

Folgendes ist der Teil des Codes als Referenz.

FileInputStream inputStream = new FileInputStream(theSourcePhotoFilePathName); 

    Bitmap bitmap = null; 
    BitmapRegionDecoder decoder = null; 

    BitmapFactory.Options options = new BitmapFactory.Options();   
    options.inSampleSize = 1; 
    options.inDensity = 300; // Tried this but not working. 

    try { 
     decoder = BitmapRegionDecoder.newInstance(in, false); 
     bitmap = decoder.decodeRegion(region, options);  // the region has cropping coordinates. 
    } catch (IllegalArgumentException e){ 
     Log.d("First Activity", "Failed to recycle bitmap for rect=" + region, e); 
    } catch (IOException e) { 
     Log.d("First Activity", "Failed to decode into rect=" + region, e); 
    } finally { 
     if (decoder != null) decoder.recycle(); 
    } 

    inputStream.close(); 
    inputStream = null; 

    FileOutputStream fos = new FileOutputStream(theTargetTempFolderDestFilePath); 
    bitmap.compress(CompressFormat.JPEG, jpegCompressionRatio, fos); 
    fos.flush(); 
    fos.close(); 
    fos = null; 

Ich habe versucht, durch googeln, von Stackoverflow und von anderen Websites zu finden, aber nicht die richtige verwandte Antwort bekommen kann. Also habe ich mich entschieden, es in diesem Forum zu stellen.

Ihre Hinweise und Vorschläge sind willkommen.

Sanjay.

Antwort

4

Beziehen Sie sich auf die DPI-Metadaten, die als Teil der JPEG-Datei geschrieben wurden? Ich habe kürzlich damit zu kämpfen gehabt, aber eine Lösung gefunden. Wenn Sie es bereits gelöst haben, kann diese Antwort anderen helfen, die auf das gleiche Problem stoßen.

Wenn ein Bitmap in Android zu JPEG komprimiert wird, wird es in einem JFIF-Segmentformat gespeichert. Bitte lesen Sie den Artikel hier (http://en.wikipedia.org/wiki/JPEG_File_Interchange_Format). Ich habe auch einen Screenshot von einem Android-JPEG-Bild angehängt, das in einem Hex-Editor geöffnet wurde, damit Sie sehen können, wie es zusammenpasst.

enter image description here

den Wert zu bearbeiten, müssen Sie zunächst ein byte [] Array erstellen, der die Bitmap.compress gespeichert werden(). Hier ist ein Teil meines Codes, wo ich genau das mache (Eingabe ist die Quell-Bitmap).

ByteArrayOutputStream uploadImageByteArray = new ByteArrayOutputStream(); 
input.compress(Bitmap.CompressFormat.JPEG, 100, uploadImageByteArray); 
byte[] uploadImageData = uploadImageByteArray.toByteArray(); 

Basierend auf der JFIF Struktur, müssen Sie den 13., 14., 15., 16. und 17. Indizes in der Byte-Array bearbeiten. 13. Stelle den Dichtetyp, 14. und 15. die X-Auflösung und 16. und 17. die Y-Auflösung ein. In meinem Fall habe ich es in den Metadaten auf 500 dpi als X- und Y-Auflösung geändert. Dies wird in 0000 0001 1111 0100 übersetzt, was 1F4 in Hex ist. Ich schrieb dann das Byte [] in die Datei, kopierte es von meinem Handy auf meinen Computer und verifizierte, dass die Details vorhanden waren, als ich die Bildeigenschaften sah.

   uploadImageData[13] = 00000001; 
       uploadImageData[14] = 00000001; 
       uploadImageData[15] = (byte) 244 
       uploadImageData[16] = 00000001; 
       uploadImageData[17] = (byte) 244 


       File image = new File(Environment 
       .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) 
       .getAbsolutePath() + "/meta Images/", imageFileName); 
       FileOutputStream sdCardOutput = new FileOutputStream(image); 
       sdCardOutput.write(uploadImageData); 

HINWEIS: Java verwendet ein Byte-System unterzeichnet, und Sie können in jedem binären Wert über 127, ohne den Compiler bellen Sie nicht eingeben.Ich stieß auf dieses Problem, das F4 als ein Byte eingab. Die Lösung besteht darin, Ihren Wert in dezimal zu konvertieren und dann eine (Byte-) Umwandlung zu verwenden.

Hoffe, das hilft!

+0

Gr8, konnte ich das Gleiche zu tun, indem Sie die Bibliothek von Drittanbietern sanselanandroid verwenden. Aber diese Methode ist besser und schneller. Dieser Ansatz ändert die Daten in Exif-Informationen. Mit diesem Ansatz können wir die JPEG 'X-Auflösung' und 'Y-Auflösung' ändern, wobei das Bild ohne Thumbnail ist. Als ich es mit Fotos probierte (von einer professionellen Kamera, die ein Thumbnail und mehr Exif-Informationen hatte), war ich ** nicht in der Lage, das DPI sowohl direkt als auch auf Sanselan einzustellen. – SHS

8

Nur der Einfachheit halber hier ist bereit, Kopieren und Einfügen Methode:

public static void saveBitmapToJpg(Bitmap bitmap, File file, int dpi) throws IOException { 
    ByteArrayOutputStream imageByteArray = new ByteArrayOutputStream(); 
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, imageByteArray); 
    byte[] imageData = imageByteArray.toByteArray(); 

    setDpi(imageData, dpi); 

    FileOutputStream fileOutputStream = new FileOutputStream(file); 
    fileOutputStream.write(imageData); 
    fileOutputStream.close(); 
} 

private static void setDpi(byte[] imageData, int dpi) { 
    imageData[13] = 1; 
    imageData[14] = (byte) (dpi >> 8); 
    imageData[15] = (byte) (dpi & 0xff); 
    imageData[16] = (byte) (dpi >> 8); 
    imageData[17] = (byte) (dpi & 0xff); 
} 

gespeicherte Datei wird richtig eingestellt Bild DPI Wert:

enter image description here

+0

Gr8 - Vereinfachende Lösung für neue Android-Entwickler. – SHS