OSDN Git Service

Fix exif data saving for picasa images.
authorRuben Brunk <rubenbrunk@google.com>
Wed, 16 Jan 2013 01:23:40 +0000 (17:23 -0800)
committerRuben Brunk <rubenbrunk@google.com>
Wed, 16 Jan 2013 01:27:03 +0000 (17:27 -0800)
Bug: 7910836
Change-Id: I8ec1a1ab379c35b0602689a8f7850f5c861e0189

gallerycommon/src/com/android/gallery3d/common/Utils.java
gallerycommon/src/com/android/gallery3d/exif/ExifParser.java
src/com/android/gallery3d/filtershow/cache/ImageLoader.java
src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java

index 3a68745..614a081 100644 (file)
@@ -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);
         }
     }
 
index a1ce13e..1e4803f 100644 (file)
@@ -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");
         }
index a1a1ba1..2c5bc1d 100644 (file)
@@ -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);
         }
     }
 
index cce2e80..4bc973e 100644 (file)
@@ -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<ImagePreset, Void, Uri> {
         } 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<ImagePreset, Void, Uri> {
     }
 
     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<ImagePreset, Void, Uri> {
         } finally {
             Utils.closeSilently(is);
         }
-
     }
 
     /**
@@ -199,32 +171,37 @@ public class SaveCopyTask extends AsyncTask<ImagePreset, Void, Uri> {
         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);
         }
     }