summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRuben Brunk <rubenbrunk@google.com>2013-03-11 19:00:12 -0700
committerRuben Brunk <rubenbrunk@google.com>2013-03-13 18:01:42 -0700
commit29fd4aa661f7e626a1d11558f09e8f7c011efcc2 (patch)
treec493ac90f0f3783e2efeea17083164a742cc621f /src
parentacca4ee0fefe6442b853510b6b360f6cb7ad1bc5 (diff)
downloadandroid_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')
-rw-r--r--src/com/android/camera/Exif.java45
-rw-r--r--src/com/android/camera/PanoramaModule.java51
-rw-r--r--src/com/android/gallery3d/data/Exif.java44
-rw-r--r--src/com/android/gallery3d/data/LocalImage.java74
-rw-r--r--src/com/android/gallery3d/data/MediaDetails.java74
-rw-r--r--src/com/android/gallery3d/filtershow/cache/ImageLoader.java50
-rw-r--r--src/com/android/gallery3d/filtershow/tools/SaveCopyTask.java181
7 files changed, 198 insertions, 321 deletions
diff --git a/src/com/android/camera/Exif.java b/src/com/android/camera/Exif.java
index 605556599..ee39d675e 100644
--- a/src/com/android/camera/Exif.java
+++ b/src/com/android/camera/Exif.java
@@ -18,9 +18,7 @@ package com.android.camera;
import android.util.Log;
-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 java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -31,44 +29,23 @@ public class Exif {
// Returns the degrees in clockwise. Values are 0, 90, 180, or 270.
public static int getOrientation(byte[] jpeg) {
- if (jpeg == null) return 0;
+ if (jpeg == null) {
+ return 0;
+ }
+ ExifInterface exif = new ExifInterface();
InputStream is = new ByteArrayInputStream(jpeg);
-
try {
- 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 &&
- tag.hasValue()) {
- int orient = (int) tag.getValueAt(0);
- switch (orient) {
- case ExifTag.Orientation.TOP_LEFT:
- return 0;
- case ExifTag.Orientation.BOTTOM_LEFT:
- return 180;
- case ExifTag.Orientation.RIGHT_TOP:
- return 90;
- case ExifTag.Orientation.RIGHT_BOTTOM:
- return 270;
- default:
- Log.i(TAG, "Unsupported orientation");
- return 0;
- }
- }
- }
- event = parser.next();
+ exif.readExif(is);
+ Integer val = exif.getTagIntValue(ExifInterface.TAG_ORIENTATION);
+ if (val == null) {
+ return 0;
+ } else {
+ return ExifInterface.getRotationForOrientationValue(val.shortValue());
}
- Log.i(TAG, "Orientation not found");
- return 0;
} catch (IOException e) {
Log.w(TAG, "Failed to read EXIF orientation", e);
return 0;
- } catch (ExifInvalidFormatException e) {
- Log.w(TAG, "Failed to read EXIF orientation", e);
- return 0;
}
}
}
diff --git a/src/com/android/camera/PanoramaModule.java b/src/com/android/camera/PanoramaModule.java
index 623d96dc6..dc27f56f1 100644
--- a/src/com/android/camera/PanoramaModule.java
+++ b/src/com/android/camera/PanoramaModule.java
@@ -60,10 +60,7 @@ import com.android.camera.ui.PopupManager;
import com.android.camera.ui.Rotatable;
import com.android.gallery3d.R;
import com.android.gallery3d.common.ApiHelper;
-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.ExifInterface;
import com.android.gallery3d.exif.ExifTag;
import com.android.gallery3d.ui.GLRootView;
import com.android.gallery3d.util.UsageStatistics;
@@ -913,31 +910,18 @@ public class PanoramaModule implements CameraModule,
mActivity.getResources().getString(R.string.pano_file_name_format), mTimeTaken);
String filepath = Storage.generateFilepath(filename);
- ExifOutputStream out = null;
- InputStream is = null;
+ ExifInterface exif = new ExifInterface();
try {
- is = new ByteArrayInputStream(jpegData);
- ExifReader reader = new ExifReader();
- ExifData data = reader.read(is);
-
- // Add Exif tags.
- data.addGpsDateTimeStampTag(mTimeTaken);
- data.addDateTimeStampTag(ExifTag.TAG_DATE_TIME, mTimeTaken, TimeZone.getDefault());
- data.addTag(ExifTag.TAG_ORIENTATION).
- setValue(getExifOrientation(orientation));
-
- out = new ExifOutputStream(new FileOutputStream(filepath));
- out.setExifData(data);
- out.write(jpegData);
+ exif.readExif(jpegData);
+ exif.addGpsDateTimeStampTag(mTimeTaken);
+ exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, mTimeTaken,
+ TimeZone.getDefault());
+ exif.setTag(exif.buildTag(ExifInterface.TAG_ORIENTATION,
+ ExifInterface.getOrientationValueForRotation(orientation)));
+ exif.writeExif(jpegData, filepath);
} catch (IOException e) {
- Log.e(TAG, "Cannot set EXIF for " + filepath, e);
+ Log.e(TAG, "Cannot set exif for " + filepath, e);
Storage.writeFile(filepath, jpegData);
- } catch (ExifInvalidFormatException e) {
- Log.e(TAG, "Cannot set EXIF for " + filepath, e);
- Storage.writeFile(filepath, jpegData);
- } finally {
- Util.closeSilently(out);
- Util.closeSilently(is);
}
int jpegLength = (int) (new File(filepath).length());
@@ -947,21 +931,6 @@ public class PanoramaModule implements CameraModule,
return null;
}
- private static int getExifOrientation(int orientation) {
- switch (orientation) {
- case 0:
- return ExifTag.Orientation.TOP_LEFT;
- case 90:
- return ExifTag.Orientation.RIGHT_TOP;
- case 180:
- return ExifTag.Orientation.BOTTOM_LEFT;
- case 270:
- return ExifTag.Orientation.RIGHT_BOTTOM;
- default:
- throw new AssertionError("invalid: " + orientation);
- }
- }
-
private void clearMosaicFrameProcessorIfNeeded() {
if (!mPaused || mThreadRunning) return;
// Only clear the processor if it is initialized by this activity
diff --git a/src/com/android/gallery3d/data/Exif.java b/src/com/android/gallery3d/data/Exif.java
index 30aba7e97..950e7de18 100644
--- a/src/com/android/gallery3d/data/Exif.java
+++ b/src/com/android/gallery3d/data/Exif.java
@@ -18,55 +18,31 @@ package com.android.gallery3d.data;
import android.util.Log;
-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 java.io.IOException;
import java.io.InputStream;
public class Exif {
- private static final String TAG = "GalleryExif";
+ private static final String TAG = "CameraExif";
+ // Returns the degrees in clockwise. Values are 0, 90, 180, or 270.
public static int getOrientation(InputStream is) {
if (is == null) {
return 0;
}
-
+ ExifInterface exif = new ExifInterface();
try {
- 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 &&
- tag.hasValue()) {
- int orient = (int) tag.getValueAt(0);
- switch (orient) {
- case ExifTag.Orientation.TOP_LEFT:
- return 0;
- case ExifTag.Orientation.BOTTOM_LEFT:
- return 180;
- case ExifTag.Orientation.RIGHT_TOP:
- return 90;
- case ExifTag.Orientation.RIGHT_BOTTOM:
- return 270;
- default:
- Log.i(TAG, "Unsupported orientation");
- return 0;
- }
- }
- }
- event = parser.next();
+ exif.readExif(is);
+ Integer val = exif.getTagIntValue(ExifInterface.TAG_ORIENTATION);
+ if (val == null) {
+ return 0;
+ } else {
+ return ExifInterface.getRotationForOrientationValue(val.shortValue());
}
- Log.i(TAG, "Orientation not found");
- return 0;
} catch (IOException e) {
Log.w(TAG, "Failed to read EXIF orientation", e);
return 0;
- } catch (ExifInvalidFormatException e) {
- Log.w(TAG, "Failed to read EXIF orientation", e);
- return 0;
}
}
}
diff --git a/src/com/android/gallery3d/data/LocalImage.java b/src/com/android/gallery3d/data/LocalImage.java
index d5fad5483..1ed67ecf4 100644
--- a/src/com/android/gallery3d/data/LocalImage.java
+++ b/src/com/android/gallery3d/data/LocalImage.java
@@ -23,7 +23,6 @@ import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapRegionDecoder;
-import android.media.ExifInterface;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore.Images;
@@ -37,8 +36,7 @@ import com.android.gallery3d.app.StitchingProgressManager;
import com.android.gallery3d.common.ApiHelper;
import com.android.gallery3d.common.BitmapUtils;
import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.exif.ExifInvalidFormatException;
-import com.android.gallery3d.exif.ExifModifier;
+import com.android.gallery3d.exif.ExifInterface;
import com.android.gallery3d.exif.ExifTag;
import com.android.gallery3d.util.GalleryUtils;
import com.android.gallery3d.util.ThreadPool.Job;
@@ -46,6 +44,7 @@ import com.android.gallery3d.util.ThreadPool.JobContext;
import com.android.gallery3d.util.UpdateHelper;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel.MapMode;
@@ -196,15 +195,15 @@ public class LocalImage extends LocalMediaItem {
// try to decode from JPEG EXIF
if (type == MediaItem.TYPE_MICROTHUMBNAIL) {
- ExifInterface exif = null;
- byte [] thumbData = null;
+ ExifInterface exif = new ExifInterface();
+ byte[] thumbData = null;
try {
- exif = new ExifInterface(mLocalFilePath);
- if (exif != null) {
- thumbData = exif.getThumbnail();
- }
- } catch (Throwable t) {
- Log.w(TAG, "fail to get exif thumb", t);
+ exif.readExif(mLocalFilePath);
+ thumbData = exif.getThumbnail();
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "failed to find file to read thumbnail: " + mLocalFilePath);
+ } catch (IOException e) {
+ Log.w(TAG, "failed to get thumbnail from: " + mLocalFilePath);
}
if (thumbData != null) {
Bitmap bitmap = DecodeUtils.decodeIfBigEnough(
@@ -276,21 +275,6 @@ public class LocalImage extends LocalMediaItem {
new String[]{String.valueOf(id)});
}
- private static int getExifOrientation(int orientation) {
- switch (orientation) {
- case 0:
- return ExifInterface.ORIENTATION_NORMAL;
- case 90:
- return ExifInterface.ORIENTATION_ROTATE_90;
- case 180:
- return ExifInterface.ORIENTATION_ROTATE_180;
- case 270:
- return ExifInterface.ORIENTATION_ROTATE_270;
- default:
- throw new AssertionError("invalid: " + orientation);
- }
- }
-
@Override
public void rotate(int degrees) {
GalleryUtils.assertNotInRenderThread();
@@ -300,34 +284,22 @@ public class LocalImage extends LocalMediaItem {
if (rotation < 0) rotation += 360;
if (mimeType.equalsIgnoreCase("image/jpeg")) {
- RandomAccessFile file = null;
- try {
- // Because most of the images contain the orientation tag, we
- // use ExifModifier to modify the tag for better efficiency.
- // If the tag doesn't exist, ExifInterface will be used to replace the entire
- // header.
- file = new RandomAccessFile(filePath, "rw");
- ExifModifier modifier = new ExifModifier(
- file.getChannel().map(MapMode.READ_WRITE, 0, file.length()));
- ExifTag tag = ExifTag.buildTag(ExifTag.TAG_ORIENTATION);
- tag.setValue(getExifOrientation(rotation));
- modifier.modifyTag(tag);
- if (!modifier.commit()) {
- // Need to change the file size, use ExifInterface instead.
- ExifInterface exif = new ExifInterface(filePath);
- exif.setAttribute(ExifInterface.TAG_ORIENTATION,
- String.valueOf(getExifOrientation(rotation)));
- exif.saveAttributes();
- // We need to update the filesize as well
+ ExifInterface exifInterface = new ExifInterface();
+ ExifTag tag = exifInterface.buildTag(ExifInterface.TAG_ORIENTATION,
+ ExifInterface.getOrientationValueForRotation(rotation));
+ if(tag != null) {
+ exifInterface.setTag(tag);
+ try {
+ exifInterface.forceRewriteExif(filePath);
fileSize = new File(filePath).length();
values.put(Images.Media.SIZE, fileSize);
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "cannot find file to set exif: " + filePath);
+ } catch (IOException e) {
+ Log.w(TAG, "cannot set exif data: " + filePath);
}
- } catch (IOException e) {
- Log.w(TAG, "cannot set exif data: " + filePath);
- } catch (ExifInvalidFormatException e) {
- Log.w(TAG, "cannot set exif data: " + filePath);
- } finally {
- Utils.closeSilently(file);
+ } else {
+ Log.w(TAG, "Could not build tag: " + ExifInterface.TAG_ORIENTATION);
}
}
diff --git a/src/com/android/gallery3d/data/MediaDetails.java b/src/com/android/gallery3d/data/MediaDetails.java
index 662bd141c..cac524b88 100644
--- a/src/com/android/gallery3d/data/MediaDetails.java
+++ b/src/com/android/gallery3d/data/MediaDetails.java
@@ -18,12 +18,12 @@ package com.android.gallery3d.data;
import com.android.gallery3d.R;
import com.android.gallery3d.common.Utils;
-import com.android.gallery3d.exif.ExifData;
-import com.android.gallery3d.exif.ExifInvalidFormatException;
-import com.android.gallery3d.exif.ExifReader;
+import com.android.gallery3d.exif.ExifInterface;
import com.android.gallery3d.exif.ExifTag;
+import com.android.gallery3d.exif.Rational;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
@@ -115,11 +115,11 @@ public class MediaDetails implements Iterable<Entry<Integer, Object>> {
String value = null;
int type = tag.getDataType();
if (type == ExifTag.TYPE_UNSIGNED_RATIONAL || type == ExifTag.TYPE_RATIONAL) {
- value = String.valueOf(tag.getRational(0).toDouble());
+ value = String.valueOf(tag.getValueAsRational(0).toDouble());
} else if (type == ExifTag.TYPE_ASCII) {
- value = tag.getString();
+ value = tag.getValueAsString();
} else {
- value = String.valueOf(tag.getValueAt(0));
+ value = String.valueOf(tag.forceGetValueAsLong(0));
}
if (key == MediaDetails.INDEX_FLASH) {
MediaDetails.FlashState state = new MediaDetails.FlashState(
@@ -132,37 +132,39 @@ public class MediaDetails implements Iterable<Entry<Integer, Object>> {
}
public static void extractExifInfo(MediaDetails details, String filePath) {
- InputStream is = null;
+
+ ExifInterface exif = new ExifInterface();
try {
- is = new FileInputStream(filePath);
- ExifData data = new ExifReader().read(is);
- setExifData(details, data.getTag(ExifTag.TAG_FLASH), MediaDetails.INDEX_FLASH);
- setExifData(details, data.getTag(ExifTag.TAG_IMAGE_WIDTH), MediaDetails.INDEX_WIDTH);
- setExifData(details, data.getTag(ExifTag.TAG_IMAGE_LENGTH), MediaDetails.INDEX_HEIGHT);
- setExifData(details, data.getTag(ExifTag.TAG_MAKE), MediaDetails.INDEX_MAKE);
- setExifData(details, data.getTag(ExifTag.TAG_MODEL),MediaDetails.INDEX_MODEL);
- setExifData(details, data.getTag(ExifTag.TAG_APERTURE_VALUE),
- MediaDetails.INDEX_APERTURE);
- setExifData(details, data.getTag(ExifTag.TAG_ISO_SPEED_RATINGS),
- MediaDetails.INDEX_ISO);
- setExifData(details, data.getTag(ExifTag.TAG_WHITE_BALANCE),
- MediaDetails.INDEX_WHITE_BALANCE);
- setExifData(details, data.getTag(ExifTag.TAG_EXPOSURE_TIME),
- MediaDetails.INDEX_EXPOSURE_TIME);
- ExifTag focalTag = data.getTag(ExifTag.TAG_FOCAL_LENGTH);
- if (focalTag != null) {
- details.addDetail(MediaDetails.INDEX_FOCAL_LENGTH,
- focalTag.getRational(0).toDouble());
- details.setUnit(MediaDetails.INDEX_FOCAL_LENGTH, R.string.unit_mm);
- }
- } catch (IOException ex) {
- // ignore it.
- Log.w(TAG, "", ex);
- } catch (ExifInvalidFormatException ex) {
- // ignore it.
- Log.w(TAG, "", ex);
- } finally {
- Utils.closeSilently(is);
+ exif.readExif(filePath);
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Could not find file to read exif: " + filePath, e);
+ } catch (IOException e) {
+ Log.w(TAG, "Could not read exif from file: " + filePath, e);
+ }
+
+ setExifData(details, exif.getTag(ExifInterface.TAG_FLASH),
+ MediaDetails.INDEX_FLASH);
+ setExifData(details, exif.getTag(ExifInterface.TAG_IMAGE_WIDTH),
+ MediaDetails.INDEX_WIDTH);
+ setExifData(details, exif.getTag(ExifInterface.TAG_IMAGE_LENGTH),
+ MediaDetails.INDEX_HEIGHT);
+ setExifData(details, exif.getTag(ExifInterface.TAG_MAKE),
+ MediaDetails.INDEX_MAKE);
+ setExifData(details, exif.getTag(ExifInterface.TAG_MODEL),
+ MediaDetails.INDEX_MODEL);
+ setExifData(details, exif.getTag(ExifInterface.TAG_APERTURE_VALUE),
+ MediaDetails.INDEX_APERTURE);
+ setExifData(details, exif.getTag(ExifInterface.TAG_ISO_SPEED_RATINGS),
+ MediaDetails.INDEX_ISO);
+ setExifData(details, exif.getTag(ExifInterface.TAG_WHITE_BALANCE),
+ MediaDetails.INDEX_WHITE_BALANCE);
+ setExifData(details, exif.getTag(ExifInterface.TAG_EXPOSURE_TIME),
+ MediaDetails.INDEX_EXPOSURE_TIME);
+ ExifTag focalTag = exif.getTag(ExifInterface.TAG_FOCAL_LENGTH);
+ if (focalTag != null) {
+ details.addDetail(MediaDetails.INDEX_FOCAL_LENGTH,
+ focalTag.getValueAsRational(0).toDouble());
+ details.setUnit(MediaDetails.INDEX_FOCAL_LENGTH, R.string.unit_mm);
}
}
}
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);