From: Ruben Brunk Date: Wed, 16 Jan 2013 01:23:40 +0000 (-0800) Subject: Fix exif data saving for picasa images. X-Git-Tag: android-x86-7.1-r1~1238 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=aeb7d79d2a35f534276bc6bf8128349f9768ae6b;p=android-x86%2Fpackages-apps-Gallery2.git Fix exif data saving for picasa images. Bug: 7910836 Change-Id: I8ec1a1ab379c35b0602689a8f7850f5c861e0189 --- diff --git a/gallerycommon/src/com/android/gallery3d/common/Utils.java b/gallerycommon/src/com/android/gallery3d/common/Utils.java index 3a68745c4..614a081c8 100644 --- a/gallerycommon/src/com/android/gallery3d/common/Utils.java +++ b/gallerycommon/src/com/android/gallery3d/common/Utils.java @@ -26,6 +26,7 @@ import android.text.TextUtils; import android.util.Log; import java.io.Closeable; +import java.io.IOException; import java.io.InterruptedIOException; public class Utils { @@ -173,8 +174,8 @@ public class Utils { if (c == null) return; try { c.close(); - } catch (Throwable t) { - Log.w(TAG, "close fail", t); + } catch (IOException t) { + Log.w(TAG, "close fail ", t); } } diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java b/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java index a1ce13e69..1e4803f68 100644 --- a/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java +++ b/gallerycommon/src/com/android/gallery3d/exif/ExifParser.java @@ -179,6 +179,9 @@ public class ExifParser { private ExifParser(InputStream inputStream, int options) throws IOException, ExifInvalidFormatException { + if (inputStream == null) { + throw new IOException("Null argument inputStream to ExifParser"); + } mContainExifData = seekTiffData(inputStream); mTiffStream = new CountedDataInputStream(inputStream); mOptions = options; @@ -682,7 +685,6 @@ public class ExifParser { private boolean seekTiffData(InputStream inputStream) throws IOException, ExifInvalidFormatException { CountedDataInputStream dataStream = new CountedDataInputStream(inputStream); - if (dataStream.readShort() != JpegHeader.SOI) { throw new ExifInvalidFormatException("Invalid JPEG format"); } diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java index a1a1ba186..2c5bc1df9 100644 --- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java +++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java @@ -79,6 +79,8 @@ public class ImageLoader { private FilterShowActivity mActivity = null; + public static final String JPEG_MIME_TYPE = "image/jpeg"; + public static final String DEFAULT_SAVE_DIRECTORY = "EditedOnlinePhotos"; public static final int DEFAULT_COMPRESS_QUALITY = 95; @@ -144,9 +146,36 @@ public class ImageLoader { public static int getOrientation(Context context, Uri uri) { if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { - return getOrientationFromPath(uri.getPath()); + String mimeType = context.getContentResolver().getType(uri); + if (mimeType != ImageLoader.JPEG_MIME_TYPE) { + return -1; + } + String path = uri.getPath(); + int orientation = -1; + InputStream is = null; + 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(); + } + } catch (IOException e) { + e.printStackTrace(); + } catch (ExifInvalidFormatException e) { + e.printStackTrace(); + } finally { + Utils.closeSilently(is); + } + return orientation; } - Cursor cursor = null; try { cursor = context.getContentResolver().query(uri, @@ -181,33 +210,6 @@ public class ImageLoader { } } - static int getOrientationFromPath(String path) { - int orientation = -1; - InputStream is = null; - 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(); - } - } catch (IOException e) { - e.printStackTrace(); - } catch (ExifInvalidFormatException e) { - e.printStackTrace(); - } finally { - Utils.closeSilently(is); - } - return orientation; - } - private void updateBitmaps() { if (mOrientation > 1) { mOriginalBitmapSmall = rotateToPortrait(mOriginalBitmapSmall, mOrientation); @@ -264,16 +266,6 @@ public class ImageLoader { bitmap.getHeight(), matrix, true); } - private void closeStream(Closeable stream) { - if (stream != null) { - try { - stream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - private Bitmap loadRegionBitmap(Uri uri, Rect bounds) { InputStream is = null; try { @@ -285,7 +277,7 @@ public class ImageLoader { } catch (Exception e) { e.printStackTrace(); } finally { - closeStream(is); + Utils.closeSilently(is); } return null; } @@ -323,7 +315,7 @@ public class ImageLoader { BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; - closeStream(is); + Utils.closeSilently(is); is = mContext.getContentResolver().openInputStream(uri); return BitmapFactory.decodeStream(is, null, o2); } catch (FileNotFoundException e) { @@ -331,7 +323,7 @@ public class ImageLoader { } catch (Exception e) { e.printStackTrace(); } finally { - closeStream(is); + Utils.closeSilently(is); } return null; } @@ -458,15 +450,27 @@ public class ImageLoader { }).execute(preset); } - public static Bitmap loadMutableBitmap(Context context, Uri sourceUri) - throws FileNotFoundException { + public static Bitmap loadMutableBitmap(Context context, Uri sourceUri) { BitmapFactory.Options options = new BitmapFactory.Options(); // TODO: on <3.x we need a copy of the bitmap (inMutable doesn't // exist) options.inMutable = true; - InputStream is = context.getContentResolver().openInputStream(sourceUri); - Bitmap bitmap = BitmapFactory.decodeStream(is, null, options); + InputStream is = null; + Bitmap bitmap = null; + try { + is = context.getContentResolver().openInputStream(sourceUri); + bitmap = BitmapFactory.decodeStream(is, null, options); + } catch (FileNotFoundException e) { + Log.w(LOGTAG, "could not load bitmap ", e); + is = null; + bitmap = null; + } finally { + Utils.closeSilently(is); + } + if (bitmap == null) { + return null; + } int orientation = ImageLoader.getOrientation(context, sourceUri); bitmap = ImageLoader.rotateToPortrait(bitmap, orientation); return bitmap; @@ -493,13 +497,12 @@ public class ImageLoader { if (param == null) { return null; } - try { - Bitmap bitmap = param.apply(loadMutableBitmap(mContext, mUri)); - return bitmap; - } catch (FileNotFoundException ex) { - Log.w(LOGTAG, "Failed to save image!", ex); + Bitmap bitmap = loadMutableBitmap(mContext, mUri); + if (bitmap == null) { + Log.w(LOGTAG, "Failed to save image!"); return null; } + return param.apply(bitmap); } }; @@ -584,40 +587,41 @@ public class ImageLoader { * @return true if it is a light Cycle image that is full 360 */ public boolean queryLightCycle360() { + InputStream is = null; try { - InputStream is = mContext.getContentResolver().openInputStream(getUri()); + is = mContext.getContentResolver().openInputStream(getUri()); XMPMeta meta = XmpUtilHelper.extractXMPMeta(is); if (meta == null) { return false; } String name = meta.getPacketHeader(); - try { - String namespace = "http://ns.google.com/photos/1.0/panorama/"; - String cropWidthName = "GPano:CroppedAreaImageWidthPixels"; - String fullWidthName = "GPano:FullPanoWidthPixels"; - - if (!meta.doesPropertyExist(namespace, cropWidthName)) { - return false; - } - if (!meta.doesPropertyExist(namespace, fullWidthName)) { - return false; - } - - Integer cropValue = meta.getPropertyInteger(namespace, cropWidthName); - Integer fullValue = meta.getPropertyInteger(namespace, fullWidthName); - - // Definition of a 360: - // GFullPanoWidthPixels == CroppedAreaImageWidthPixels - if (cropValue != null && fullValue != null) { - return cropValue.equals(fullValue); - } + String namespace = "http://ns.google.com/photos/1.0/panorama/"; + String cropWidthName = "GPano:CroppedAreaImageWidthPixels"; + String fullWidthName = "GPano:FullPanoWidthPixels"; + if (!meta.doesPropertyExist(namespace, cropWidthName)) { return false; - } catch (XMPException e) { + } + if (!meta.doesPropertyExist(namespace, fullWidthName)) { return false; } + + Integer cropValue = meta.getPropertyInteger(namespace, cropWidthName); + Integer fullValue = meta.getPropertyInteger(namespace, fullWidthName); + + // Definition of a 360: + // GFullPanoWidthPixels == CroppedAreaImageWidthPixels + if (cropValue != null && fullValue != null) { + return cropValue.equals(fullValue); + } + + return false; } catch (FileNotFoundException e) { return false; + } catch (XMPException e) { + return false; + } finally { + Utils.closeSilently(is); } } diff --git a/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java b/src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java index cce2e80bc..4bc973ed8 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.BitmapFactory; import android.graphics.Bitmap.CompressFormat; import android.net.Uri; import android.os.AsyncTask; @@ -40,9 +39,7 @@ import com.android.gallery3d.filtershow.cache.ImageLoader; import com.android.gallery3d.filtershow.presets.ImagePreset; import com.android.gallery3d.util.XmpUtilHelper; -import java.io.Closeable; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -80,22 +77,11 @@ public class SaveCopyTask extends AsyncTask { } catch (FileNotFoundException e) { Log.v(LOGTAG,"Error in writing "+destination.getAbsolutePath()); } finally { - closeStream(os); + Utils.closeSilently(os);; } if (xmp != null) { XmpUtilHelper.writeXMPMeta(destination.getAbsolutePath(), xmp); } - - } - - private static void closeStream(Closeable stream) { - if (stream != null) { - try { - stream.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } } /** @@ -153,33 +139,20 @@ public class SaveCopyTask extends AsyncTask { } private ExifData getExifData(Uri sourceUri) { - String path = null; - if (ContentResolver.SCHEME_FILE.equals(sourceUri.getScheme())) { - path = sourceUri.getPath(); - } - - final String[] PROJECTION = new String[] { - ImageColumns.DATA - }; - try { - Cursor c = context.getContentResolver().query(sourceUri, PROJECTION, - null, null, null); - if (c.moveToFirst()) { - path = c.getString(0); - } - c.close(); - } catch (Exception e) { - Log.w(LOGTAG, "Failed to copy exif", e); + String mimeType = context.getContentResolver().getType(sourceUri); + if (mimeType != ImageLoader.JPEG_MIME_TYPE) { + return null; } - InputStream is = null; try { - is = new FileInputStream(path); + is = context.getContentResolver().openInputStream(sourceUri); ExifReader reader = new ExifReader(); return reader.read(is); } 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; } catch (IOException e) { Log.w(LOGTAG, "Failed to read original file", e); @@ -187,7 +160,6 @@ public class SaveCopyTask extends AsyncTask { } finally { Utils.closeSilently(is); } - } /** @@ -199,32 +171,37 @@ public class SaveCopyTask extends AsyncTask { if (params[0] == null) { return null; } - ImagePreset preset = params[0]; - + InputStream is = null; try { - Bitmap bitmap = preset.apply(ImageLoader.loadMutableBitmap(context, sourceUri)); + Bitmap bitmap = ImageLoader.loadMutableBitmap(context, sourceUri); + if (bitmap == null) { + return null; + } + bitmap = preset.apply(bitmap); Object xmp = null; - InputStream is = null; if (preset.isPanoramaSafe()) { is = context.getContentResolver().openInputStream(sourceUri); xmp = XmpUtilHelper.extractXMPMeta(is); } ExifData exif = getExifData(sourceUri); - 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); + 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); + } saveBitmap(bitmap, this.destinationFile, xmp, exif); Uri uri = insertContent(context, sourceUri, this.destinationFile, saveFileName); bitmap.recycle(); return uri; - } catch (FileNotFoundException ex) { Log.w(LOGTAG, "Failed to save image!", ex); return null; + } finally { + Utils.closeSilently(is); } }