diff options
author | Ruben Brunk <rubenbrunk@google.com> | 2013-03-11 19:00:12 -0700 |
---|---|---|
committer | Ruben Brunk <rubenbrunk@google.com> | 2013-03-13 18:01:42 -0700 |
commit | 29fd4aa661f7e626a1d11558f09e8f7c011efcc2 (patch) | |
tree | c493ac90f0f3783e2efeea17083164a742cc621f /src/com/android/gallery3d/filtershow | |
parent | acca4ee0fefe6442b853510b6b360f6cb7ad1bc5 (diff) | |
download | android_packages_apps_Snap-29fd4aa661f7e626a1d11558f09e8f7c011efcc2.tar.gz android_packages_apps_Snap-29fd4aa661f7e626a1d11558f09e8f7c011efcc2.tar.bz2 android_packages_apps_Snap-29fd4aa661f7e626a1d11558f09e8f7c011efcc2.zip |
Exif parser modifications.
Bug: 8018327
Change-Id: I66a2ec309f9807ac255bbf29d8f5f26de60e89b8
Diffstat (limited to 'src/com/android/gallery3d/filtershow')
-rw-r--r-- | src/com/android/gallery3d/filtershow/cache/ImageLoader.java | 50 | ||||
-rw-r--r-- | src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java | 181 |
2 files changed, 106 insertions, 125 deletions
diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java index 6cf462269..2c1a847f8 100644 --- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java +++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java @@ -27,7 +27,7 @@ import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; import android.graphics.Matrix; import android.graphics.Rect; -import android.media.ExifInterface; +import android.graphics.Bitmap.CompressFormat; import android.net.Uri; import android.provider.MediaStore; import android.util.Log; @@ -36,9 +36,8 @@ import com.adobe.xmp.XMPException; import com.adobe.xmp.XMPMeta; import com.android.gallery3d.R; import com.android.gallery3d.common.Utils; -import com.android.gallery3d.exif.ExifInvalidFormatException; -import com.android.gallery3d.exif.ExifParser; import com.android.gallery3d.exif.ExifTag; +import com.android.gallery3d.exif.ExifInterface; import com.android.gallery3d.filtershow.FilterShowActivity; import com.android.gallery3d.filtershow.HistoryAdapter; import com.android.gallery3d.filtershow.imageshow.ImageShow; @@ -48,6 +47,8 @@ import com.android.gallery3d.filtershow.tools.SaveCopyTask; import com.android.gallery3d.util.InterruptableOutputStream; import com.android.gallery3d.util.XmpUtilHelper; +import java.io.ByteArrayInputStream; +import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -79,14 +80,14 @@ public class ImageLoader { public static final String DEFAULT_SAVE_DIRECTORY = "EditedOnlinePhotos"; public static final int DEFAULT_COMPRESS_QUALITY = 95; - public static final int ORI_NORMAL = ExifInterface.ORIENTATION_NORMAL; - public static final int ORI_ROTATE_90 = ExifInterface.ORIENTATION_ROTATE_90; - public static final int ORI_ROTATE_180 = ExifInterface.ORIENTATION_ROTATE_180; - public static final int ORI_ROTATE_270 = ExifInterface.ORIENTATION_ROTATE_270; - public static final int ORI_FLIP_HOR = ExifInterface.ORIENTATION_FLIP_HORIZONTAL; - public static final int ORI_FLIP_VERT = ExifInterface.ORIENTATION_FLIP_VERTICAL; - public static final int ORI_TRANSPOSE = ExifInterface.ORIENTATION_TRANSPOSE; - public static final int ORI_TRANSVERSE = ExifInterface.ORIENTATION_TRANSVERSE; + public static final int ORI_NORMAL = ExifInterface.Orientation.TOP_LEFT; + public static final int ORI_ROTATE_90 = ExifInterface.Orientation.RIGHT_TOP; + public static final int ORI_ROTATE_180 = ExifInterface.Orientation.BOTTOM_LEFT; + public static final int ORI_ROTATE_270 = ExifInterface.Orientation.RIGHT_BOTTOM; + public static final int ORI_FLIP_HOR = ExifInterface.Orientation.TOP_RIGHT; + public static final int ORI_FLIP_VERT = ExifInterface.Orientation.BOTTOM_RIGHT; + public static final int ORI_TRANSPOSE = ExifInterface.Orientation.LEFT_TOP; + public static final int ORI_TRANSVERSE = ExifInterface.Orientation.LEFT_BOTTOM; private static final int BITMAP_LOAD_BACKOUT_ATTEMPTS = 5; private Context mContext = null; @@ -147,26 +148,13 @@ public class ImageLoader { String path = uri.getPath(); int orientation = -1; InputStream is = null; + ExifInterface exif = new ExifInterface(); try { - is = new FileInputStream(path); - ExifParser parser = ExifParser.parse(is, ExifParser.OPTION_IFD_0); - int event = parser.next(); - while (event != ExifParser.EVENT_END) { - if (event == ExifParser.EVENT_NEW_TAG) { - ExifTag tag = parser.getTag(); - if (tag.getTagId() == ExifTag.TAG_ORIENTATION) { - orientation = (int) tag.getValueAt(0); - break; - } - } - event = parser.next(); - } + exif.readExif(path); + orientation = ExifInterface.getRotationForOrientationValue( + exif.getTagIntValue(ExifInterface.TAG_ORIENTATION).shortValue()); } catch (IOException e) { - e.printStackTrace(); - } catch (ExifInvalidFormatException e) { - e.printStackTrace(); - } finally { - Utils.closeSilently(is); + Log.w(LOGTAG, "Failed to read EXIF orientation", e); } return orientation; } @@ -196,9 +184,9 @@ public class ImageLoader { return -1; } } catch (SQLiteException e) { - return ExifInterface.ORIENTATION_UNDEFINED; + return -1; } catch (IllegalArgumentException e) { - return ExifInterface.ORIENTATION_UNDEFINED; + return -1; } finally { Utils.closeSilently(cursor); } diff --git a/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java b/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java index b88dbbc47..aa7e70065 100644 --- a/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java +++ b/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java @@ -21,7 +21,6 @@ import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; -import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.AsyncTask; @@ -31,21 +30,15 @@ import android.provider.MediaStore.Images.ImageColumns; import android.util.Log; import com.android.gallery3d.common.Utils; -import com.android.gallery3d.exif.ExifData; -import com.android.gallery3d.exif.ExifInvalidFormatException; -import com.android.gallery3d.exif.ExifOutputStream; -import com.android.gallery3d.exif.ExifReader; -import com.android.gallery3d.exif.ExifTag; +import com.android.gallery3d.exif.ExifInterface; import com.android.gallery3d.filtershow.cache.ImageLoader; import com.android.gallery3d.filtershow.presets.ImagePreset; import com.android.gallery3d.util.XmpUtilHelper; import java.io.File; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; import java.sql.Date; import java.text.SimpleDateFormat; import java.util.TimeZone; @@ -55,35 +48,7 @@ import java.util.TimeZone; */ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { - private static final String LOGTAG = "SaveCopyTask"; - /** - * Saves the bitmap in the final destination - */ - public static void saveBitmap(Bitmap bitmap, File destination, Object xmp) { - saveBitmap(bitmap, destination, xmp, null); - } - - private static void saveBitmap(Bitmap bitmap, File destination, Object xmp, ExifData exif) { - OutputStream os = null; - try { - os = new FileOutputStream(destination); - if (exif != null) { - ExifOutputStream eos = new ExifOutputStream(os); - eos.setExifData(exif); - bitmap.compress(CompressFormat.JPEG, ImageLoader.DEFAULT_COMPRESS_QUALITY, eos); - } else { - bitmap.compress(CompressFormat.JPEG, ImageLoader.DEFAULT_COMPRESS_QUALITY, os); - } - } catch (FileNotFoundException e) { - Log.v(LOGTAG,"Error in writing "+destination.getAbsolutePath()); - } finally { - Utils.closeSilently(os);; - } - if (xmp != null) { - XmpUtilHelper.writeXMPMeta(destination.getAbsolutePath(), xmp); - } - } /** * Callback for the completed asynchronous task. @@ -128,7 +93,8 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { ImageLoader.DEFAULT_SAVE_DIRECTORY); } // Create the directory if it doesn't exist - if (!saveDirectory.exists()) saveDirectory.mkdirs(); + if (!saveDirectory.exists()) + saveDirectory.mkdirs(); return saveDirectory; } @@ -139,28 +105,59 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { return new File(saveDirectory, filename + ".JPG"); } - private ExifData getExifData(Uri sourceUri) { + public Object getPanoramaXMPData(Uri source, ImagePreset preset) { + Object xmp = null; + if (preset.isPanoramaSafe()) { + InputStream is = null; + try { + is = context.getContentResolver().openInputStream(source); + xmp = XmpUtilHelper.extractXMPMeta(is); + } catch (FileNotFoundException e) { + Log.w(LOGTAG, "Failed to get XMP data from image: ", e); + } finally { + Utils.closeSilently(is); + } + } + return xmp; + } + + public boolean putPanoramaXMPData(File file, Object xmp) { + if (xmp != null) { + return XmpUtilHelper.writeXMPMeta(file.getAbsolutePath(), xmp); + } + return false; + } + + public ExifInterface getExifData(Uri source) { + ExifInterface exif = new ExifInterface(); String mimeType = context.getContentResolver().getType(sourceUri); - if (mimeType != ImageLoader.JPEG_MIME_TYPE) { - return null; + if (mimeType == ImageLoader.JPEG_MIME_TYPE) { + InputStream inStream = null; + try { + inStream = context.getContentResolver().openInputStream(source); + exif.readExif(inStream); + } catch (FileNotFoundException e) { + Log.w(LOGTAG, "Cannot find file: " + source, e); + } catch (IOException e) { + Log.w(LOGTAG, "Cannot read exif for: " + source, e); + } finally { + Utils.closeSilently(inStream); + } } - InputStream is = null; + return exif; + } + + public boolean putExifData(File file, ExifInterface exif, Bitmap image) { + boolean ret = false; try { - is = context.getContentResolver().openInputStream(sourceUri); - ExifReader reader = new ExifReader(); - return reader.read(is); + exif.writeExif(image, file.getAbsolutePath()); + ret = true; } catch (FileNotFoundException e) { - Log.w(LOGTAG, "Failed to find file", e); - return null; - } catch (ExifInvalidFormatException e) { - Log.w(LOGTAG, "Invalid EXIF data", e); - return null; + Log.w(LOGTAG, "File not found: " + file.getAbsolutePath(), e); } catch (IOException e) { - Log.w(LOGTAG, "Failed to read original file", e); - return null; - } finally { - Utils.closeSilently(is); + Log.w(LOGTAG, "Could not write exif: ", e); } + return ret; } /** @@ -173,12 +170,12 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { return null; } ImagePreset preset = params[0]; - InputStream is = null; BitmapFactory.Options options = new BitmapFactory.Options(); + Uri uri = null; boolean noBitmap = true; int num_tries = 0; // Stopgap fix for low-memory devices. - while(noBitmap) { + while (noBitmap) { try { // Try to do bitmap operations, downsample if low-memory Bitmap bitmap = ImageLoader.loadMutableBitmap(context, sourceUri, options); @@ -189,24 +186,23 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { bitmap = preset.applyGeometry(bitmap); bitmap = preset.apply(bitmap); - Object xmp = null; - if (preset.isPanoramaSafe()) { - is = context.getContentResolver().openInputStream(sourceUri); - xmp = XmpUtilHelper.extractXMPMeta(is); - } - ExifData exif = getExifData(sourceUri); - if (exif != null) { - exif.addDateTimeStampTag(ExifTag.TAG_DATE_TIME, System.currentTimeMillis(), - TimeZone.getDefault()); - // Since the image has been modified, set the orientation to normal. - exif.addTag(ExifTag.TAG_ORIENTATION).setValue(ExifTag.Orientation.TOP_LEFT); + Object xmp = getPanoramaXMPData(sourceUri, preset); + ExifInterface exif = getExifData(sourceUri); + + // Set tags + long time = System.currentTimeMillis(); + exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, time, + TimeZone.getDefault()); + exif.setTag(exif.buildTag(ExifInterface.TAG_ORIENTATION, + ExifInterface.Orientation.TOP_LEFT)); + + // If we succeed in writing the bitmap as a jpeg, return a uri. + if (putExifData(this.destinationFile, exif, bitmap)) { + putPanoramaXMPData(this.destinationFile, xmp); + uri = insertContent(context, sourceUri, this.destinationFile, saveFileName, + time); } - saveBitmap(bitmap, this.destinationFile, xmp, exif); - bitmap.recycle(); noBitmap = false; - } catch (FileNotFoundException ex) { - Log.w(LOGTAG, "Failed to save image!", ex); - return null; } catch (java.lang.OutOfMemoryError e) { // Try 5 times before failing for good. if (++num_tries >= 5) { @@ -214,13 +210,9 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { } System.gc(); options.inSampleSize *= 2; - } finally { - Utils.closeSilently(is); } } - Uri uri = insertContent(context, sourceUri, this.destinationFile, saveFileName); return uri; - } @Override @@ -267,16 +259,17 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { /** * Insert the content (saved file) with proper source photo properties. */ - public static Uri insertContent(Context context, Uri sourceUri, File file, String saveFileName) { - long now = System.currentTimeMillis() / 1000; + public static Uri insertContent(Context context, Uri sourceUri, File file, String saveFileName, + long time) { + time /= 1000; final ContentValues values = new ContentValues(); values.put(Images.Media.TITLE, saveFileName); values.put(Images.Media.DISPLAY_NAME, file.getName()); values.put(Images.Media.MIME_TYPE, "image/jpeg"); - values.put(Images.Media.DATE_TAKEN, now); - values.put(Images.Media.DATE_MODIFIED, now); - values.put(Images.Media.DATE_ADDED, now); + values.put(Images.Media.DATE_TAKEN, time); + values.put(Images.Media.DATE_MODIFIED, time); + values.put(Images.Media.DATE_ADDED, time); values.put(Images.Media.ORIENTATION, 0); values.put(Images.Media.DATA, file.getAbsolutePath()); values.put(Images.Media.SIZE, file.length()); @@ -288,20 +281,20 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> { querySource(context, sourceUri, projection, new ContentResolverQueryCallback() { - @Override - public void onCursorResult(Cursor cursor) { - values.put(Images.Media.DATE_TAKEN, cursor.getLong(0)); - - double latitude = cursor.getDouble(1); - double longitude = cursor.getDouble(2); - // TODO: Change || to && after the default location issue is - // fixed. - if ((latitude != 0f) || (longitude != 0f)) { - values.put(Images.Media.LATITUDE, latitude); - values.put(Images.Media.LONGITUDE, longitude); - } - } - }); + @Override + public void onCursorResult(Cursor cursor) { + values.put(Images.Media.DATE_TAKEN, cursor.getLong(0)); + + double latitude = cursor.getDouble(1); + double longitude = cursor.getDouble(2); + // TODO: Change || to && after the default location + // issue is fixed. + if ((latitude != 0f) || (longitude != 0f)) { + values.put(Images.Media.LATITUDE, latitude); + values.put(Images.Media.LONGITUDE, longitude); + } + } + }); return context.getContentResolver().insert( Images.Media.EXTERNAL_CONTENT_URI, values); |