From 0cea1fca1ac717b0bf6f4f75c2e41e8549bc97e2 Mon Sep 17 00:00:00 2001 From: Ruben Brunk Date: Tue, 2 Apr 2013 13:15:57 -0700 Subject: Speed improvements for ExifOutputStream. Change-Id: I7d3ee9c157aefe67734e7b49cfa7868254c134ef --- .../com/android/gallery3d/exif/ExifInterface.java | 8 +++- .../android/gallery3d/exif/ExifOutputStream.java | 4 +- .../gallery3d/exif/ExifOutputStreamTest.java | 55 ++++++++++++++++++++++ .../gallery3d/exif/ExifXmlDataTestCase.java | 13 +++++ 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java b/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java index 2fef9ede0..a1cf0fc85 100644 --- a/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java +++ b/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java @@ -20,6 +20,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.SparseIntArray; +import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Closeable; @@ -758,7 +759,7 @@ public class ExifInterface { } InputStream is = null; try { - is = (InputStream) new FileInputStream(inFileName); + is = (InputStream) new BufferedInputStream(new FileInputStream(inFileName)); readExif(is); } catch (IOException e) { closeSilently(is); @@ -800,6 +801,7 @@ public class ExifInterface { } OutputStream s = getExifWriterStream(exifOutStream); s.write(jpeg, 0, jpeg.length); + s.flush(); } /** @@ -817,6 +819,7 @@ public class ExifInterface { } OutputStream s = getExifWriterStream(exifOutStream); bmap.compress(Bitmap.CompressFormat.JPEG, 90, s); + s.flush(); } /** @@ -834,6 +837,7 @@ public class ExifInterface { } OutputStream s = getExifWriterStream(exifOutStream); doExifStreamIO(jpegStream, s); + s.flush(); } /** @@ -1010,7 +1014,7 @@ public class ExifInterface { boolean ret; try { File temp = new File(filename); - is = new FileInputStream(temp); + is = new BufferedInputStream(new FileInputStream(temp)); // Parse beginning of APP1 in exif to find size of exif header. ExifParser parser = null; diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java b/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java index e5a5bf009..96672e8d7 100644 --- a/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java +++ b/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java @@ -18,6 +18,7 @@ package com.android.gallery3d.exif; import android.util.Log; +import java.io.BufferedOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -58,6 +59,7 @@ import java.nio.ByteOrder; class ExifOutputStream extends FilterOutputStream { private static final String TAG = "ExifOutputStream"; private static final boolean DEBUG = false; + private static final int STREAMBUFFER_SIZE = 0x00010000; // 64Kb private static final int STATE_SOI = 0; private static final int STATE_FRAME_HEADER = 1; @@ -79,7 +81,7 @@ class ExifOutputStream extends FilterOutputStream { private final ExifInterface mInterface; protected ExifOutputStream(OutputStream ou, ExifInterface iRef) { - super(ou); + super(new BufferedOutputStream(ou, STREAMBUFFER_SIZE)); mInterface = iRef; } diff --git a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java b/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java index 8c4fc3dea..1286c5801 100644 --- a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java +++ b/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java @@ -18,6 +18,7 @@ package com.android.gallery3d.exif; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.util.Log; import java.io.ByteArrayInputStream; import java.io.File; @@ -131,6 +132,60 @@ public class ExifOutputStreamTest extends ExifXmlDataTestCase { } } + public void testOutputSpeed() throws Exception { + final String LOGTAG = "testOutputSpeed"; + InputStream imageInputStream = null; + OutputStream imageOutputStream = null; + try { + try { + imageInputStream = getImageInputStream(); + // Read the image data + Bitmap bmp = BitmapFactory.decodeStream(imageInputStream); + // The image is invalid + if (bmp == null) { + return; + } + imageInputStream.close(); + int nLoops = 20; + long totalReadDuration = 0; + long totalWriteDuration = 0; + for (int i = 0; i < nLoops; i++) { + imageInputStream = reopenFileStream(); + // Read exif data + long startTime = System.nanoTime(); + ExifData exifData = new ExifReader(mInterface).read(imageInputStream); + long endTime = System.nanoTime(); + long duration = endTime - startTime; + totalReadDuration += duration; + Log.v(LOGTAG, " read time: " + duration); + imageInputStream.close(); + + // Encode the image with the exif data + imageOutputStream = (OutputStream) new FileOutputStream(mTmpFile); + ExifOutputStream exifOutputStream = new ExifOutputStream(imageOutputStream, + mInterface); + exifOutputStream.setExifData(exifData); + startTime = System.nanoTime(); + bmp.compress(Bitmap.CompressFormat.JPEG, 90, exifOutputStream); + endTime = System.nanoTime(); + duration = endTime - startTime; + totalWriteDuration += duration; + Log.v(LOGTAG, " write time: " + duration); + exifOutputStream.close(); + } + Log.v(LOGTAG, "======================= normal"); + Log.v(LOGTAG, "avg read time: " + totalReadDuration / nLoops); + Log.v(LOGTAG, "avg write time: " + totalWriteDuration / nLoops); + Log.v(LOGTAG, "======================="); + } finally { + Util.closeSilently(imageInputStream); + Util.closeSilently(imageOutputStream); + } + } catch (Exception e) { + throw new Exception(getImageTitle(), e); + } + } + @Override public void tearDown() throws Exception { super.tearDown(); diff --git a/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java b/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java index 5f200ea92..da860208b 100644 --- a/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java +++ b/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java @@ -92,4 +92,17 @@ public class ExifXmlDataTestCase extends InstrumentationTestCase { return String.format(RES_ID_TITLE, mImageResourceId); } } + + protected InputStream reopenFileStream() throws Exception { + try { + if (mImagePath != null) { + return new FileInputStream(mImagePath); + } else { + Resources res = getInstrumentation().getContext().getResources(); + return res.openRawResource(mImageResourceId); + } + } catch (Exception e) { + throw new Exception(getImageTitle(), e); + } + } } -- cgit v1.2.3