summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/data/LocalMediaData.java
diff options
context:
space:
mode:
authorztenghui <ztenghui@google.com>2013-08-23 11:47:56 -0700
committerztenghui <ztenghui@google.com>2013-08-28 13:07:45 -0700
commita16e7b50f3148f581439509279f242092e254309 (patch)
treeaa5ba2660ad79635b4f3d4a14691c7ebeac907d7 /src/com/android/camera/data/LocalMediaData.java
parent7446e9fde7cd8dd7904beff592e8819513797ab9 (diff)
downloadandroid_packages_apps_Snap-a16e7b50f3148f581439509279f242092e254309.tar.gz
android_packages_apps_Snap-a16e7b50f3148f581439509279f242092e254309.tar.bz2
android_packages_apps_Snap-a16e7b50f3148f581439509279f242092e254309.zip
Add rotate support in Film Strip
Move the exif related code under src.com.android.camera.exif. Refactor the member variables under LocalMediaData.java. Refactor the LocalData to make sure they are immutables for thread safety. bug:10367037 Change-Id: I0e84bcc0097925b2be749fe016984177a68e0a4d
Diffstat (limited to 'src/com/android/camera/data/LocalMediaData.java')
-rw-r--r--src/com/android/camera/data/LocalMediaData.java332
1 files changed, 185 insertions, 147 deletions
diff --git a/src/com/android/camera/data/LocalMediaData.java b/src/com/android/camera/data/LocalMediaData.java
index 88f127f3e..f692cbcc0 100644
--- a/src/com/android/camera/data/LocalMediaData.java
+++ b/src/com/android/camera/data/LocalMediaData.java
@@ -52,18 +52,18 @@ import java.util.Locale;
* return a bitmap.
*/
public abstract class LocalMediaData implements LocalData {
- protected long id;
- protected String title;
- protected String mimeType;
- protected long dateTakenInSeconds;
- protected long dateModifiedInSeconds;
- protected String path;
+ protected final long mId;
+ protected final String mTitle;
+ protected final String mMimeType;
+ protected final long mDateTakenInSeconds;
+ protected final long mDateModifiedInSeconds;
+ protected final String mPath;
// width and height should be adjusted according to orientation.
- protected int width;
- protected int height;
- protected long sizeInBytes;
- protected double latitude;
- protected double longitude;
+ protected final int mWidth;
+ protected final int mHeight;
+ protected final long mSizeInBytes;
+ protected final double mLatitude;
+ protected final double mLongitude;
/** The panorama metadata information of this media data. */
protected PhotoSphereHelper.PanoramaMetadata mPanoramaMetadata;
@@ -77,34 +77,62 @@ public abstract class LocalMediaData implements LocalData {
*/
protected Boolean mUsing = false;
+ public LocalMediaData (long id, String title, String mimeType,
+ long dateTakenInSeconds, long dateModifiedInSeconds, String path,
+ int width, int height, long sizeInBytes, double latitude,
+ double longitude) {
+ mId = id;
+ mTitle = new String(title);
+ mMimeType = new String(mimeType);
+ mDateTakenInSeconds = dateTakenInSeconds;
+ mDateModifiedInSeconds = dateModifiedInSeconds;
+ mPath = new String(path);
+ mWidth = width;
+ mHeight = height;
+ mSizeInBytes = sizeInBytes;
+ mLatitude = latitude;
+ mLongitude = longitude;
+ return;
+ }
+
@Override
public long getDateTaken() {
- return dateTakenInSeconds;
+ return mDateTakenInSeconds;
}
@Override
public long getDateModified() {
- return dateModifiedInSeconds;
+ return mDateModifiedInSeconds;
+ }
+
+ @Override
+ public long getId() {
+ return mId;
}
@Override
public String getTitle() {
- return new String(title);
+ return new String(mTitle);
}
@Override
public int getWidth() {
- return width;
+ return mWidth;
}
@Override
public int getHeight() {
- return height;
+ return mHeight;
}
@Override
public String getPath() {
- return path;
+ return mPath;
+ }
+
+ @Override
+ public long getSizeInBytes() {
+ return mSizeInBytes;
}
@Override
@@ -119,7 +147,7 @@ public abstract class LocalMediaData implements LocalData {
@Override
public boolean delete(Context ctx) {
- File f = new File(path);
+ File f = new File(mPath);
return f.delete();
}
@@ -199,11 +227,11 @@ public abstract class LocalMediaData implements LocalData {
@Override
public double[] getLatLong() {
- if (latitude == 0 && longitude == 0) {
+ if (mLatitude == 0 && mLongitude == 0) {
return null;
}
return new double[] {
- latitude, longitude
+ mLatitude, mLongitude
};
}
@@ -215,25 +243,25 @@ public abstract class LocalMediaData implements LocalData {
@Override
public String getMimeType() {
- return mimeType;
+ return mMimeType;
}
@Override
public MediaDetails getMediaDetails(Context context) {
DateFormat dateFormatter = DateFormat.getDateTimeInstance();
MediaDetails mediaDetails = new MediaDetails();
- mediaDetails.addDetail(MediaDetails.INDEX_TITLE, title);
- mediaDetails.addDetail(MediaDetails.INDEX_WIDTH, width);
- mediaDetails.addDetail(MediaDetails.INDEX_HEIGHT, height);
- mediaDetails.addDetail(MediaDetails.INDEX_PATH, path);
+ mediaDetails.addDetail(MediaDetails.INDEX_TITLE, mTitle);
+ mediaDetails.addDetail(MediaDetails.INDEX_WIDTH, mWidth);
+ mediaDetails.addDetail(MediaDetails.INDEX_HEIGHT, mHeight);
+ mediaDetails.addDetail(MediaDetails.INDEX_PATH, mPath);
mediaDetails.addDetail(MediaDetails.INDEX_DATETIME,
- dateFormatter.format(new Date(dateModifiedInSeconds * 1000)));
- if (sizeInBytes > 0) {
- mediaDetails.addDetail(MediaDetails.INDEX_SIZE, sizeInBytes);
+ dateFormatter.format(new Date(mDateModifiedInSeconds * 1000)));
+ if (mSizeInBytes > 0) {
+ mediaDetails.addDetail(MediaDetails.INDEX_SIZE, mSizeInBytes);
}
- if (latitude != 0 && longitude != 0) {
- String locationString = String.format(Locale.getDefault(), "%f, %f", latitude,
- longitude);
+ if (mLatitude != 0 && mLongitude != 0) {
+ String locationString = String.format(Locale.getDefault(), "%f, %f", mLatitude,
+ mLongitude);
mediaDetails.addDetail(MediaDetails.INDEX_LOCATION, locationString);
}
return mediaDetails;
@@ -245,7 +273,7 @@ public abstract class LocalMediaData implements LocalData {
protected abstract BitmapLoadTask getBitmapLoadTask(
ImageView v, int decodeWidth, int decodeHeight);
- public static class PhotoData extends LocalMediaData {
+ public static final class PhotoData extends LocalMediaData {
private static final String TAG = "CAM_PhotoData";
public static final int COL_ID = 0;
@@ -293,54 +321,69 @@ public abstract class LocalMediaData implements LocalData {
private static final byte[] DECODE_TEMP_STORAGE = new byte[32 * 1024];
/** from MediaStore, can only be 0, 90, 180, 270 */
- public int orientation;
+ private final int mOrientation;
+
+ public PhotoData(long id, String title, String mimeType,
+ long dateTakenInSeconds, long dateModifiedInSeconds,
+ String path, int orientation, int width, int height,
+ long sizeInBytes, double latitude, double longitude) {
+ super(id, title, mimeType, dateTakenInSeconds, dateModifiedInSeconds,
+ path, width, height, sizeInBytes, latitude, longitude);
+ mOrientation = orientation;
+ }
static PhotoData buildFromCursor(Cursor c) {
- PhotoData d = new PhotoData();
- d.id = c.getLong(COL_ID);
- d.title = c.getString(COL_TITLE);
- d.mimeType = c.getString(COL_MIME_TYPE);
- d.dateTakenInSeconds = c.getLong(COL_DATE_TAKEN);
- d.dateModifiedInSeconds = c.getLong(COL_DATE_MODIFIED);
- d.path = c.getString(COL_DATA);
- d.orientation = c.getInt(COL_ORIENTATION);
- d.width = c.getInt(COL_WIDTH);
- d.height = c.getInt(COL_HEIGHT);
- if (d.width <= 0 || d.height <= 0) {
+ long id = c.getLong(COL_ID);
+ String title = c.getString(COL_TITLE);
+ String mimeType = c.getString(COL_MIME_TYPE);
+ long dateTakenInSeconds = c.getLong(COL_DATE_TAKEN);
+ long dateModifiedInSeconds = c.getLong(COL_DATE_MODIFIED);
+ String path = c.getString(COL_DATA);
+ int orientation = c.getInt(COL_ORIENTATION);
+ int width = c.getInt(COL_WIDTH);
+ int height = c.getInt(COL_HEIGHT);
+ if (width <= 0 || height <= 0) {
Log.w(TAG, "Warning! zero dimension for "
- + d.path + ":" + d.width + "x" + d.height);
+ + path + ":" + width + "x" + height);
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
- BitmapFactory.decodeFile(d.path, opts);
+ BitmapFactory.decodeFile(path, opts);
if (opts.outWidth != -1 && opts.outHeight != -1) {
- d.width = opts.outWidth;
- d.height = opts.outHeight;
+ width = opts.outWidth;
+ height = opts.outHeight;
} else {
- Log.w(TAG, "Warning! dimension decode failed for " + d.path);
- Bitmap b = BitmapFactory.decodeFile(d.path);
+ Log.w(TAG, "Warning! dimension decode failed for " + path);
+ Bitmap b = BitmapFactory.decodeFile(path);
if (b == null) {
return null;
}
- d.width = b.getWidth();
- d.height = b.getHeight();
+ width = b.getWidth();
+ height = b.getHeight();
}
}
- if (d.orientation == 90 || d.orientation == 270) {
- int b = d.width;
- d.width = d.height;
- d.height = b;
+ if (orientation == 90 || orientation == 270) {
+ int b = width;
+ width = height;
+ height = b;
}
- d.sizeInBytes = c.getLong(COL_SIZE);
- d.latitude = c.getDouble(COL_LATITUDE);
- d.longitude = c.getDouble(COL_LONGITUDE);
- return d;
+ long sizeInBytes = c.getLong(COL_SIZE);
+ double latitude = c.getDouble(COL_LATITUDE);
+ double longitude = c.getDouble(COL_LONGITUDE);
+ PhotoData result = new PhotoData(id, title, mimeType, dateTakenInSeconds,
+ dateModifiedInSeconds, path, orientation, width, height,
+ sizeInBytes, latitude, longitude);
+ return result;
+ }
+
+ public int getOrientation() {
+ return mOrientation;
}
@Override
public String toString() {
- return "Photo:" + ",data=" + path + ",mimeType=" + mimeType
- + "," + width + "x" + height + ",orientation=" + orientation
- + ",date=" + new Date(dateTakenInSeconds);
+ return "Photo:" + ",data=" + mPath + ",mimeType=" + mMimeType
+ + "," + mWidth + "x" + mHeight + ",orientation=" + mOrientation
+ + ",date=" + new Date(mDateTakenInSeconds);
}
@Override
@@ -361,20 +404,20 @@ public abstract class LocalMediaData implements LocalData {
@Override
public boolean delete(Context c) {
ContentResolver cr = c.getContentResolver();
- cr.delete(CONTENT_URI, MediaStore.Images.ImageColumns._ID + "=" + id, null);
+ cr.delete(CONTENT_URI, MediaStore.Images.ImageColumns._ID + "=" + mId, null);
return super.delete(c);
}
@Override
public Uri getContentUri() {
Uri baseUri = CONTENT_URI;
- return baseUri.buildUpon().appendPath(String.valueOf(id)).build();
+ return baseUri.buildUpon().appendPath(String.valueOf(mId)).build();
}
@Override
public MediaDetails getMediaDetails(Context context) {
MediaDetails mediaDetails = super.getMediaDetails(context);
- MediaDetails.extractExifInfo(mediaDetails, path);
+ MediaDetails.extractExifInfo(mediaDetails, mPath);
return mediaDetails;
}
@@ -391,23 +434,14 @@ public abstract class LocalMediaData implements LocalData {
}
@Override
- public boolean refresh(ContentResolver resolver) {
+ public LocalData refresh(ContentResolver resolver) {
Cursor c = resolver.query(
getContentUri(), QUERY_PROJECTION, null, null, null);
if (c == null || !c.moveToFirst()) {
- return false;
+ return null;
}
PhotoData newData = buildFromCursor(c);
- id = newData.id;
- title = newData.title;
- mimeType = newData.mimeType;
- dateTakenInSeconds = newData.dateTakenInSeconds;
- dateModifiedInSeconds = newData.dateModifiedInSeconds;
- path = newData.path;
- orientation = newData.orientation;
- width = newData.width;
- height = newData.height;
- return true;
+ return newData;
}
@Override
@@ -434,9 +468,9 @@ public abstract class LocalMediaData implements LocalData {
@Override
protected Bitmap doInBackground(Void... v) {
int sampleSize = 1;
- if (width > mDecodeWidth || height > mDecodeHeight) {
- int heightRatio = Math.round((float) height / (float) mDecodeHeight);
- int widthRatio = Math.round((float) width / (float) mDecodeWidth);
+ if (mWidth > mDecodeWidth || mHeight > mDecodeHeight) {
+ int heightRatio = Math.round((float) mHeight / (float) mDecodeHeight);
+ int widthRatio = Math.round((float) mWidth / (float) mDecodeWidth);
sampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
@@ -446,21 +480,30 @@ public abstract class LocalMediaData implements LocalData {
if (isCancelled() || !isUsing()) {
return null;
}
- Bitmap b = BitmapFactory.decodeFile(path, opts);
- if (orientation != 0) {
+ Bitmap b = BitmapFactory.decodeFile(mPath, opts);
+ if (mOrientation != 0) {
if (isCancelled() || !isUsing()) {
return null;
}
Matrix m = new Matrix();
- m.setRotate(orientation);
+ m.setRotate(mOrientation);
b = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), m, false);
}
return b;
}
}
+
+ @Override
+ public void rotate90Degrees(Context context, LocalDataAdapter adapter,
+ int currentDataId, boolean clockwise) {
+ RotationTask task = new RotationTask(context, adapter,
+ currentDataId, clockwise);
+ task.execute(this);
+ return;
+ }
}
- public static class VideoData extends LocalMediaData {
+ public static final class VideoData extends LocalMediaData {
public static final int COL_ID = 0;
public static final int COL_TITLE = 1;
public static final int COL_MIME_TYPE = 2;
@@ -505,26 +548,31 @@ public abstract class LocalMediaData implements LocalData {
MediaStore.Video.VideoColumns.DURATION // 12 long
};
- private Uri mPlayUri;
-
/** The duration in milliseconds. */
- private long durationInSeconds;
+ private long mDurationInSeconds;
+
+ public VideoData(long id, String title, String mimeType,
+ long dateTakenInSeconds, long dateModifiedInSeconds,
+ String path, int width, int height, long sizeInBytes,
+ double latitude, double longitude, long durationInSeconds) {
+ super(id, title, mimeType, dateTakenInSeconds, dateModifiedInSeconds,
+ path, width, height, sizeInBytes, latitude, longitude);
+ mDurationInSeconds = durationInSeconds;
+ }
static VideoData buildFromCursor(Cursor c) {
- VideoData d = new VideoData();
- d.id = c.getLong(COL_ID);
- d.title = c.getString(COL_TITLE);
- d.mimeType = c.getString(COL_MIME_TYPE);
- d.dateTakenInSeconds = c.getLong(COL_DATE_TAKEN);
- d.dateModifiedInSeconds = c.getLong(COL_DATE_MODIFIED);
- d.path = c.getString(COL_DATA);
- d.width = c.getInt(COL_WIDTH);
- d.height = c.getInt(COL_HEIGHT);
- d.mPlayUri = d.getContentUri();
+ long id = c.getLong(COL_ID);
+ String title = c.getString(COL_TITLE);
+ String mimeType = c.getString(COL_MIME_TYPE);
+ long dateTakenInSeconds = c.getLong(COL_DATE_TAKEN);
+ long dateModifiedInSeconds = c.getLong(COL_DATE_MODIFIED);
+ String path = c.getString(COL_DATA);
+ int width = c.getInt(COL_WIDTH);
+ int height = c.getInt(COL_HEIGHT);
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
String rotation = null;
try {
- retriever.setDataSource(d.path);
+ retriever.setDataSource(path);
} catch (IllegalArgumentException ex) {
retriever.release();
Log.e(TAG, "MediaMetadataRetriever.setDataSource() fail:"
@@ -533,33 +581,43 @@ public abstract class LocalMediaData implements LocalData {
}
rotation = retriever.extractMetadata(
MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
- if (d.width == 0 || d.height == 0) {
- retrieveVideoDimension(retriever, d);
+
+ // Extracts video height/width if available. If unavailable, set to 0.
+ if (width == 0 || height == 0) {
+ String val = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
+ width = (val == null) ? 0 : Integer.parseInt(val);
+ val = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
+ height = (val == null) ? 0 : Integer.parseInt(val);
}
retriever.release();
- if (d.width == 0 || d.height == 0) {
+ if (width == 0 || height == 0) {
// Width or height is still not available.
- Log.e(TAG, "Unable to retrieve dimension of video:" + d.path);
+ Log.e(TAG, "Unable to retrieve dimension of video:" + path);
return null;
}
if (rotation != null
&& (rotation.equals("90") || rotation.equals("270"))) {
- int b = d.width;
- d.width = d.height;
- d.height = b;
+ int b = width;
+ width = height;
+ height = b;
}
- d.sizeInBytes = c.getLong(COL_SIZE);
- d.latitude = c.getDouble(COL_LATITUDE);
- d.longitude = c.getDouble(COL_LONGITUDE);
- d.durationInSeconds = c.getLong(COL_DURATION) / 1000;
+ long sizeInBytes = c.getLong(COL_SIZE);
+ double latitude = c.getDouble(COL_LATITUDE);
+ double longitude = c.getDouble(COL_LONGITUDE);
+ long durationInSeconds = c.getLong(COL_DURATION) / 1000;
+ VideoData d = new VideoData(id, title, mimeType, dateTakenInSeconds,
+ dateModifiedInSeconds, path, width, height, sizeInBytes,
+ latitude, longitude, durationInSeconds);
return d;
}
@Override
public String toString() {
- return "Video:" + ",data=" + path + ",mimeType=" + mimeType
- + "," + width + "x" + height + ",date=" + new Date(dateTakenInSeconds);
+ return "Video:" + ",data=" + mPath + ",mimeType=" + mMimeType
+ + "," + mWidth + "x" + mHeight + ",date=" + new Date(mDateTakenInSeconds);
}
@Override
@@ -580,20 +638,20 @@ public abstract class LocalMediaData implements LocalData {
@Override
public boolean delete(Context ctx) {
ContentResolver cr = ctx.getContentResolver();
- cr.delete(CONTENT_URI, MediaStore.Video.VideoColumns._ID + "=" + id, null);
+ cr.delete(CONTENT_URI, MediaStore.Video.VideoColumns._ID + "=" + mId, null);
return super.delete(ctx);
}
@Override
public Uri getContentUri() {
Uri baseUri = CONTENT_URI;
- return baseUri.buildUpon().appendPath(String.valueOf(id)).build();
+ return baseUri.buildUpon().appendPath(String.valueOf(mId)).build();
}
@Override
public MediaDetails getMediaDetails(Context context) {
MediaDetails mediaDetails = super.getMediaDetails(context);
- String duration = MediaDetails.formatDuration(context, durationInSeconds);
+ String duration = MediaDetails.formatDuration(context, mDurationInSeconds);
mediaDetails.addDetail(MediaDetails.INDEX_DURATION, duration);
return mediaDetails;
}
@@ -604,26 +662,14 @@ public abstract class LocalMediaData implements LocalData {
}
@Override
- public boolean refresh(ContentResolver resolver) {
+ public LocalData refresh(ContentResolver resolver) {
Cursor c = resolver.query(
getContentUri(), QUERY_PROJECTION, null, null, null);
if (c == null || !c.moveToFirst()) {
- return false;
+ return null;
}
VideoData newData = buildFromCursor(c);
- if (newData == null) {
- return false;
- }
- id = newData.id;
- title = newData.title;
- mimeType = newData.mimeType;
- dateTakenInSeconds = newData.dateTakenInSeconds;
- dateModifiedInSeconds = newData.dateModifiedInSeconds;
- path = newData.path;
- width = newData.width;
- height = newData.height;
- mPlayUri = newData.mPlayUri;
- return true;
+ return newData;
}
@Override
@@ -647,7 +693,7 @@ public abstract class LocalMediaData implements LocalData {
icon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- CameraUtil.playVideo(ctx, mPlayUri, title);
+ CameraUtil.playVideo(ctx, getContentUri(), mTitle);
}
});
@@ -680,7 +726,7 @@ public abstract class LocalMediaData implements LocalData {
return null;
}
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
- retriever.setDataSource(path);
+ retriever.setDataSource(mPath);
byte[] data = retriever.getEmbeddedPicture();
Bitmap bitmap = null;
if (isCancelled() || !isUsing()) {
@@ -698,20 +744,12 @@ public abstract class LocalMediaData implements LocalData {
}
}
- /**
- * Extracts video height/width if available. If unavailable, set to 0.
- *
- * @param retriever An initialized metadata retriever.
- * @param d The {@link VideoData} whose width/height are to update.
- */
- private static void retrieveVideoDimension(
- MediaMetadataRetriever retriever, VideoData d) {
- String val = retriever.extractMetadata(
- MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
- d.width = (val == null) ? 0 : Integer.parseInt(val);
- val = retriever.extractMetadata(
- MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
- d.height = (val == null) ? 0 : Integer.parseInt(val);
+ @Override
+ public void rotate90Degrees(Context context, LocalDataAdapter adapter,
+ int currentDataId, boolean clockwise) {
+ // We don't support rotation for video data.
+ Log.e(TAG, "Unexpected call in rotate90Degrees()");
+ return;
}
}
@@ -733,7 +771,7 @@ public abstract class LocalMediaData implements LocalData {
return;
}
if (bitmap == null) {
- Log.e(TAG, "Failed decoding bitmap for file:" + path);
+ Log.e(TAG, "Failed decoding bitmap for file:" + mPath);
return;
}
BitmapDrawable d = new BitmapDrawable(bitmap);