summaryrefslogtreecommitdiffstats
path: root/src/com/android/camera/CameraActivity.java
diff options
context:
space:
mode:
authorLikai Ding <likaid@codeaurora.org>2015-02-04 09:38:16 +0800
committerLinux Build Service Account <lnxbuild@localhost>2015-02-17 02:55:12 -0700
commit77f75003277262bd4b3c9983f4c99ec260b92a59 (patch)
treeb0a55849236d2b94bfd97e8b5324441d17ba3d31 /src/com/android/camera/CameraActivity.java
parent12379846e84e949e5f96fb32ecf5ddd6f28d1a51 (diff)
downloadandroid_packages_apps_Snap-77f75003277262bd4b3c9983f4c99ec260b92a59.tar.gz
android_packages_apps_Snap-77f75003277262bd4b3c9983f4c99ec260b92a59.tar.bz2
android_packages_apps_Snap-77f75003277262bd4b3c9983f4c99ec260b92a59.zip
SnapdragonCamera: circular thumbnail icon
1. change thumbnail icon to circular and its background to transparent 2. speed up loading with optimal sample size and region decoder 3. fix orientation bug regarding panorama photos 4. don't fire load task on fake onDataLoaded() call Change-Id: I7f4eb8dad4c54a01a7ccd98907e06952e470840b (cherry picked from commit ac714ea974b4bd0ef99403def5aa7d8a3deecc5d)
Diffstat (limited to 'src/com/android/camera/CameraActivity.java')
-rw-r--r--src/com/android/camera/CameraActivity.java216
1 files changed, 179 insertions, 37 deletions
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index b3a7680a9..dd4a9897a 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -36,7 +36,18 @@ import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Shader;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.media.ThumbnailUtils;
import android.nfc.NfcAdapter;
@@ -86,6 +97,7 @@ import com.android.camera.data.LocalDataAdapter;
import com.android.camera.data.LocalMediaObserver;
import com.android.camera.data.MediaDetails;
import com.android.camera.data.SimpleViewData;
+import com.android.camera.exif.ExifInterface;
import com.android.camera.tinyplanet.TinyPlanetFragment;
import com.android.camera.ui.ModuleSwitcher;
import com.android.camera.ui.DetailsDialog;
@@ -101,6 +113,7 @@ import com.android.camera.util.UsageStatistics;
import org.codeaurora.snapcam.R;
import java.io.File;
+import java.io.IOException;
import static com.android.camera.CameraManager.CameraOpenErrorCallback;
@@ -214,7 +227,12 @@ public class CameraActivity extends Activity
private Intent mImageShareIntent;
public static int SETTING_LIST_WIDTH_1 = 250;
public static int SETTING_LIST_WIDTH_2 = 250;
- private Bitmap mPreviewThumbnailBitmap;
+
+ private ImageView mThumbnail;
+ private CircularDrawable mThumbnailDrawable;
+ // FilmStripView.setDataAdapter fires 2 onDataLoaded calls before any data is actually loaded
+ // Keep track of data request here to avoid creating useless UpdateThumbnailTask.
+ private boolean mDataRequested;
private AudioManager mAudioManager;
private int mShutterVol;
@@ -650,48 +668,47 @@ public class CameraActivity extends Activity
return s;
}
- public void setPreviewThumbnailBitmap(Bitmap bitmap) {
- mPreviewThumbnailBitmap = bitmap;
+ public void updateThumbnail(final byte[] jpegData) {
+ (new UpdateThumbnailTask(jpegData, false)).execute();
}
- public Bitmap getPreviewThumbBitmap() {
- return mPreviewThumbnailBitmap;
+ public void updateThumbnail(final Bitmap bitmap) {
+ mThumbnailDrawable = new CircularDrawable(bitmap);
+ if (mThumbnail != null) {
+ mThumbnail.setImageDrawable(mThumbnailDrawable);
+ mThumbnail.setVisibility(View.VISIBLE);
+ }
}
- public void updatePreviewThumbnail() {
- if (mCurrentModule != null) {
- if (mCurrentModule instanceof VideoModule) {
- ((VideoModule) mCurrentModule).updatePreviewThumbnail();
- }
- else if (mCurrentModule instanceof WideAnglePanoramaModule) {
- ((WideAnglePanoramaModule) mCurrentModule).updatePreviewThumbnail();
- }
- else if (mCurrentModule instanceof PhotoModule) {
- ((PhotoModule) mCurrentModule).updatePreviewThumbnail();
- }
+ public void updateThumbnail(ImageView thumbnail) {
+ mThumbnail = thumbnail;
+ if (mThumbnailDrawable != null) {
+ mThumbnail.setImageDrawable(mThumbnailDrawable);
+ mThumbnail.setVisibility(View.VISIBLE);
}
}
- public void updatePreviewThumbnailForVideo() {
- if (mCurrentModule != null) {
- if (mCurrentModule instanceof VideoModule) {
- ((VideoModule) mCurrentModule).updatePreviewThumbnail();
- }
+ public void updateThumbnail(boolean videoOnly) {
+ // Only handle OnDataInserted if it's video.
+ // Photo and Panorama have their own way of updating thumbnail.
+ if (!videoOnly || (mCurrentModule instanceof VideoModule)) {
+ (new UpdateThumbnailTask(null, true)).execute();
}
}
- public class UpdatePreviewThumbnail extends AsyncTask<Void, Void, Bitmap> {
- private ImageView imgView;
- private Bitmap imgBitmap = null;
+ private class UpdateThumbnailTask extends AsyncTask<Void, Void, Bitmap> {
+ private final byte[] mJpegData;
+ private final boolean mCheckOrientation;
- public UpdatePreviewThumbnail(ImageView view) {
- imgView = view;
+ public UpdateThumbnailTask(final byte[] jpegData, boolean checkOrientation) {
+ mJpegData = jpegData;
+ mCheckOrientation = checkOrientation;
}
@Override
protected Bitmap doInBackground(Void... params) {
- if (imgBitmap != null)
- return imgBitmap;
+ if (mJpegData != null)
+ return decodeImageCenter(null);
LocalDataAdapter adapter = getDataAdapter();
ImageData img = adapter.getImageData(1);
@@ -705,22 +722,146 @@ public class CameraActivity extends Activity
}
else {
if (img.isPhoto()) {
- BitmapFactory.Options opt = new BitmapFactory.Options();
- opt.inSampleSize = 4;
- return BitmapFactory.decodeFile(path, opt);
+ return decodeImageCenter(path);
} else {
return ThumbnailUtils
- .createVideoThumbnail(path, MediaStore.Video.Thumbnails.MICRO_KIND);
+ .createVideoThumbnail(path, MediaStore.Video.Thumbnails.MINI_KIND);
}
}
}
@Override
protected void onPostExecute(Bitmap bitmap) {
- if (imgView == null)
- return;
- imgView.setImageBitmap(bitmap);
- setPreviewThumbnailBitmap(bitmap);
+ if (bitmap == null) {
+ if (mThumbnail != null) {
+ mThumbnail.setVisibility(View.GONE);
+ }
+ } else {
+ updateThumbnail(bitmap);
+ }
+ }
+
+ private Bitmap decodeImageCenter(final String path) {
+ // Check photo orientation for Panorama. This is necessary during app launch because
+ // Panorama module generates thumbnail bitmap with orientation adjustment but only
+ // saves jpeg with orientation tag set.
+ int orientation = 0;
+ if (mCheckOrientation) {
+ ExifInterface exif = new ExifInterface();
+ try {
+ if (mJpegData != null) {
+ exif.readExif(mJpegData);
+ } else {
+ exif.readExif(path);
+ }
+ orientation = Exif.getOrientation(exif);
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+
+ final BitmapFactory.Options opt = new BitmapFactory.Options();
+ opt.inJustDecodeBounds = true;
+ if (mJpegData != null) {
+ BitmapFactory.decodeByteArray(mJpegData, 0, mJpegData.length, opt);
+ } else {
+ BitmapFactory.decodeFile(path, opt);
+ }
+
+ int w = opt.outWidth;
+ int h = opt.outHeight;
+ int d = w > h ? h : w;
+ final Rect rect = w > h ? new Rect((w - h) / 2, 0, (w + h) / 2, h)
+ : new Rect(0, (h - w) / 2, w, (h + w) / 2);
+
+ final int target = getResources().getDimensionPixelSize(R.dimen.capture_size);
+ int sample = 1;
+ if (d > target) {
+ while (d / sample / 2 > target) {
+ sample *= 2;
+ }
+ }
+
+ opt.inJustDecodeBounds = false;
+ opt.inSampleSize = sample;
+ final BitmapRegionDecoder decoder;
+ try {
+ if (mJpegData == null) {
+ decoder = BitmapRegionDecoder.newInstance(path, true);
+ } else {
+ decoder = BitmapRegionDecoder.newInstance(mJpegData, 0, mJpegData.length, true);
+ }
+ } catch (IOException e) {
+ return null;
+ }
+ Bitmap bitmap = decoder.decodeRegion(rect, opt);
+ if (orientation != 0) {
+ Matrix matrix = new Matrix();
+ matrix.setRotate(orientation);
+ bitmap = Bitmap.createBitmap(bitmap, 0, 0,
+ bitmap.getWidth(), bitmap.getHeight(), matrix, false);
+ }
+ return bitmap;
+ }
+ }
+
+ private class CircularDrawable extends Drawable {
+ private final BitmapShader mBitmapShader;
+ private final Paint mPaint;
+ private Rect mRect;
+ private int mLength;
+
+ public CircularDrawable(Bitmap bitmap) {
+ int w = bitmap.getWidth();
+ int h = bitmap.getHeight();
+ if (w > h) {
+ mLength = h;
+ bitmap = Bitmap.createBitmap(bitmap, (w - h) / 2, 0, h, h);
+ } else if (w < h) {
+ mLength = w;
+ bitmap = Bitmap.createBitmap(bitmap, 0, (h - w) / 2, w, w);
+ }
+
+ mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
+ mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mPaint.setShader(mBitmapShader);
+ }
+
+ @Override
+ protected void onBoundsChange(Rect bounds) {
+ super.onBoundsChange(bounds);
+ mRect = bounds;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ canvas.drawRoundRect(new RectF(mRect), (mRect.right - mRect.left) / 2,
+ (mRect.bottom - mRect.top) / 2, mPaint);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mPaint.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter filter) {
+ mPaint.setColorFilter(filter);
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mLength;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mLength;
}
}
@@ -1306,6 +1447,7 @@ public class CameraActivity extends Activity
mFilmStripView.setDataAdapter(mDataAdapter);
if (!isCaptureIntent()) {
mDataAdapter.requestLoad(getContentResolver());
+ mDataRequested = true;
}
} else {
// Put a lock placeholder as the last image by setting its date to
@@ -1455,7 +1597,7 @@ public class CameraActivity extends Activity
// If it's secure camera, requestLoad() should not be called
// as it will load all the data.
mDataAdapter.requestLoad(getContentResolver());
- setPreviewThumbnailBitmap(null);
+ mThumbnailDrawable = null;
}
}
mLocalImagesObserver.setActivityPaused(false);