diff options
author | bait_dispatcher_monitor_system <bait_dispatcher_monitor_system@localhost> | 2015-02-19 23:39:07 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2015-02-19 23:39:07 -0800 |
commit | ec2987bc28d0840e889bd1ba74245abd5b2d100b (patch) | |
tree | 02e446140a64d7040f28b0f2a10ecf1ee5a5803f /src | |
parent | f2e911a3b847715ca7f98f127c17088246cfcb92 (diff) | |
parent | ac714ea974b4bd0ef99403def5aa7d8a3deecc5d (diff) | |
download | android_packages_apps_Snap-ec2987bc28d0840e889bd1ba74245abd5b2d100b.tar.gz android_packages_apps_Snap-ec2987bc28d0840e889bd1ba74245abd5b2d100b.tar.bz2 android_packages_apps_Snap-ec2987bc28d0840e889bd1ba74245abd5b2d100b.zip |
Merge "SnapdragonCamera: circular thumbnail icon"
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/camera/CameraActivity.java | 216 | ||||
-rw-r--r-- | src/com/android/camera/PhotoModule.java | 4 | ||||
-rw-r--r-- | src/com/android/camera/PhotoUI.java | 32 | ||||
-rw-r--r-- | src/com/android/camera/VideoModule.java | 4 | ||||
-rw-r--r-- | src/com/android/camera/VideoUI.java | 30 | ||||
-rw-r--r-- | src/com/android/camera/WideAnglePanoramaModule.java | 4 | ||||
-rw-r--r-- | src/com/android/camera/WideAnglePanoramaUI.java | 29 | ||||
-rw-r--r-- | src/com/android/camera/ui/FilmStripView.java | 4 |
8 files changed, 197 insertions, 126 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); diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index 93aefbe7c..e6a96f3d4 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -2547,10 +2547,6 @@ public class PhotoModule } } - public void updatePreviewThumbnail() { - mUI.updatePreviewThumbnail(); - } - private void setDisplayOrientation() { mDisplayRotation = CameraUtil.getDisplayRotation(mActivity); mDisplayOrientation = CameraUtil.getDisplayOrientation(mDisplayRotation, mCameraId); diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java index 0df2c30ca..a0b143737 100644 --- a/src/com/android/camera/PhotoUI.java +++ b/src/com/android/camera/PhotoUI.java @@ -54,7 +54,6 @@ import android.widget.PopupWindow; import android.widget.Toast; import android.graphics.drawable.AnimationDrawable; -import com.android.camera.CameraActivity.UpdatePreviewThumbnail; import com.android.camera.CameraPreference.OnPreferenceChangedListener; import com.android.camera.FocusOverlayManager.FocusUI; import com.android.camera.ui.AbstractSettingPopup; @@ -130,7 +129,7 @@ public class PhotoUI implements PieListener, private float mSurfaceTextureUncroppedWidth; private float mSurfaceTextureUncroppedHeight; - private ImageView mPreviewThumb; + private ImageView mThumbnail; private View mFlashOverlay; private SurfaceTextureSizeChangedListener mSurfaceTextureSizeListener; @@ -229,8 +228,6 @@ public class PhotoUI implements PieListener, @Override protected void onPostExecute(Bitmap bitmap) { - mPreviewThumb.setImageBitmap(bitmap); - updatePreviewThumbnail(bitmap); } } @@ -309,24 +306,6 @@ public class PhotoUI implements PieListener, mCameraControls.setMargins(mTopMargin, mBottomMargin); } - public void updatePreviewThumbnail() { - mPreviewThumb.setVisibility(View.VISIBLE); - Bitmap bitmap = mActivity.getPreviewThumbBitmap(); - if (bitmap != null) { - mPreviewThumb.setImageBitmap(bitmap); - } - else { - UpdatePreviewThumbnail task = mActivity.new UpdatePreviewThumbnail(mPreviewThumb); - task.execute(); - } - } - - public void updatePreviewThumbnail(Bitmap bitmap) { - mPreviewThumb.setVisibility(View.VISIBLE); - mPreviewThumb.setImageBitmap(bitmap); - mActivity.setPreviewThumbnailBitmap(bitmap); - } - public void setDownFactor(int factor) { mDownSampleFactor = factor; } @@ -472,7 +451,7 @@ public class PhotoUI implements PieListener, // Re-apply transform matrix for new surface texture setTransformMatrix(mPreviewWidth, mPreviewHeight); } - updatePreviewThumbnail(); + mActivity.updateThumbnail(mThumbnail); } @Override @@ -529,8 +508,7 @@ public class PhotoUI implements PieListener, public void animateCapture(final byte[] jpegData, int orientation, boolean mirror) { // Decode jpeg byte array and then animate the jpeg - DecodeTask task = new DecodeTask(jpegData, orientation, mirror); - task.execute(); + mActivity.updateThumbnail(jpegData); } public void showRefocusToast(boolean show) { @@ -549,8 +527,8 @@ public class PhotoUI implements PieListener, } public void initializeControlByIntent() { - mPreviewThumb = (ImageView) mRootView.findViewById(R.id.preview_thumb); - mPreviewThumb.setOnClickListener(new OnClickListener() { + mThumbnail = (ImageView) mRootView.findViewById(R.id.preview_thumb); + mThumbnail.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (!CameraControls.isAnimating()) diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java index 75d3f221d..d5b629bb8 100644 --- a/src/com/android/camera/VideoModule.java +++ b/src/com/android/camera/VideoModule.java @@ -1524,10 +1524,6 @@ public class VideoModule implements CameraModule, mCurrentVideoValues = null; } - public void updatePreviewThumbnail() { - mUI.updateWithNewPreviewThumbnail(); - } - private void deleteVideoFile(String fileName) { Log.v(TAG, "Deleting video " + fileName); File f = new File(fileName); diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java index 8362d0590..913a93e2a 100644 --- a/src/com/android/camera/VideoUI.java +++ b/src/com/android/camera/VideoUI.java @@ -46,7 +46,6 @@ import android.widget.ListView; import android.widget.PopupWindow; import android.widget.TextView; -import com.android.camera.CameraActivity.UpdatePreviewThumbnail; import com.android.camera.CameraPreference.OnPreferenceChangedListener; import com.android.camera.ui.AbstractSettingPopup; import com.android.camera.ui.CameraControls; @@ -98,7 +97,7 @@ public class VideoUI implements PieRenderer.PieListener, private VideoController mController; private int mZoomMax; private List<Integer> mZoomRatios; - private ImageView mPreviewThumb; + private ImageView mThumbnail; private View mFlashOverlay; private boolean mOrientationResize; private boolean mPrevOrientationResize; @@ -267,23 +266,6 @@ public class VideoUI implements PieRenderer.PieListener, mCameraControls.setMargins(topMargin, l / 4 - topMargin); } - public void updatePreviewThumbnail() { - mPreviewThumb.setVisibility(View.VISIBLE); - Bitmap bitmap = mActivity.getPreviewThumbBitmap(); - if (bitmap != null) - mPreviewThumb.setImageBitmap(bitmap); - else { - UpdatePreviewThumbnail task = mActivity.new UpdatePreviewThumbnail(mPreviewThumb); - task.execute(); - } - } - - public void updateWithNewPreviewThumbnail() { - mPreviewThumb.setVisibility(View.VISIBLE); - UpdatePreviewThumbnail task = mActivity.new UpdatePreviewThumbnail(mPreviewThumb); - task.execute(); - } - public void cameraOrientationPreviewResize(boolean orientation){ mPrevOrientationResize = mOrientationResize; mOrientationResize = orientation; @@ -433,8 +415,8 @@ public class VideoUI implements PieRenderer.PieListener, Log.e(TAG, "No valid bitmap for capture animation."); return; } - mPreviewThumb.setImageBitmap(bitmap); - mAnimationManager.startCaptureAnimation(mPreviewThumb); + mActivity.updateThumbnail(bitmap); + mAnimationManager.startCaptureAnimation(mThumbnail); } /** @@ -577,8 +559,8 @@ public class VideoUI implements PieRenderer.PieListener, mGestures.setRenderOverlay(mRenderOverlay); - mPreviewThumb = (ImageView) mRootView.findViewById(R.id.preview_thumb); - mPreviewThumb.setOnClickListener(new OnClickListener() { + mThumbnail = (ImageView) mRootView.findViewById(R.id.preview_thumb); + mThumbnail.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // Do not allow navigation to filmstrip during video recording @@ -1031,7 +1013,7 @@ public class VideoUI implements PieRenderer.PieListener, // Re-apply transform matrix for new surface texture setTransformMatrix(mPreviewWidth, mPreviewHeight); } - updatePreviewThumbnail(); + mActivity.updateThumbnail(mThumbnail); } @Override diff --git a/src/com/android/camera/WideAnglePanoramaModule.java b/src/com/android/camera/WideAnglePanoramaModule.java index e5ba57eb2..172f6105b 100644 --- a/src/com/android/camera/WideAnglePanoramaModule.java +++ b/src/com/android/camera/WideAnglePanoramaModule.java @@ -751,10 +751,6 @@ public class WideAnglePanoramaModule } } - public void updatePreviewThumbnail() { - mUI.updatePreviewThumbnail(); - } - // This function will be called upon the first camera frame is available. private void reset() { mCaptureState = CAPTURE_STATE_VIEWFINDER; diff --git a/src/com/android/camera/WideAnglePanoramaUI.java b/src/com/android/camera/WideAnglePanoramaUI.java index 7941ea88c..e270165c1 100644 --- a/src/com/android/camera/WideAnglePanoramaUI.java +++ b/src/com/android/camera/WideAnglePanoramaUI.java @@ -46,7 +46,6 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import com.android.camera.CameraActivity.UpdatePreviewThumbnail; import com.android.camera.ui.CameraControls; import com.android.camera.ui.CameraRootView; import com.android.camera.ui.ModuleSwitcher; @@ -86,7 +85,7 @@ public class WideAnglePanoramaUI implements private TextureView mTextureView; private ShutterButton mShutterButton; private CameraControls mCameraControls; - private ImageView mPreviewThumb; + private ImageView mThumbnail; private Matrix mProgressDirectionMatrix = new Matrix(); private float[] mProgressAngle = new float[2]; @@ -116,8 +115,8 @@ public class WideAnglePanoramaUI implements mSwitcher = (ModuleSwitcher) mRootView.findViewById(R.id.camera_switcher); mSwitcher.setCurrentIndex(ModuleSwitcher.WIDE_ANGLE_PANO_MODULE_INDEX); mSwitcher.setSwitchListener(mActivity); - mPreviewThumb = (ImageView) mRootView.findViewById(R.id.preview_thumb); - mPreviewThumb.setOnClickListener(new OnClickListener() { + mThumbnail = (ImageView) mRootView.findViewById(R.id.preview_thumb); + mThumbnail.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (!CameraControls.isAnimating()) @@ -230,23 +229,6 @@ public class WideAnglePanoramaUI implements mProgressDirectionMatrix.postRotate(orientation); } - public void updatePreviewThumbnail(Bitmap bitmap) { - mPreviewThumb.setVisibility(View.VISIBLE); - mPreviewThumb.setImageBitmap(bitmap); - mActivity.setPreviewThumbnailBitmap(bitmap); - } - - public void updatePreviewThumbnail() { - mPreviewThumb.setVisibility(View.VISIBLE); - Bitmap bitmap = mActivity.getPreviewThumbBitmap(); - if (bitmap != null) - mPreviewThumb.setImageBitmap(bitmap); - else { - UpdatePreviewThumbnail task = mActivity.new UpdatePreviewThumbnail(mPreviewThumb); - task.execute(); - } - } - public void showDirectionIndicators(int direction) { switch (direction) { case PanoProgressBar.DIRECTION_NONE: @@ -272,7 +254,7 @@ public class WideAnglePanoramaUI implements public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) { mSurfaceTexture = surfaceTexture; mController.onPreviewUIReady(); - updatePreviewThumbnail(); + mActivity.updateThumbnail(mThumbnail); } @Override @@ -329,8 +311,7 @@ public class WideAnglePanoramaUI implements // a framework bug. Call requestLayout() as a workaround. mSavingProgressBar.requestLayout(); - updatePreviewThumbnail(Bitmap.createScaledBitmap(bitmap, - bitmap.getWidth() / 2, bitmap.getHeight() / 2, false)); + mActivity.updateThumbnail(bitmap); } public void onConfigurationChanged( diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java index bc40b06b3..3f1029ed1 100644 --- a/src/com/android/camera/ui/FilmStripView.java +++ b/src/com/android/camera/ui/FilmStripView.java @@ -1735,7 +1735,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { mDataAdapter.setListener(new DataAdapter.Listener() { @Override public void onDataLoaded() { - mActivity.updatePreviewThumbnail(); + mActivity.updateThumbnail(false); if (!mIsLoaded) reload(); mIsLoaded = true; @@ -1754,7 +1754,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { return; } updateInsertion(dataID); - mActivity.updatePreviewThumbnailForVideo(); + mActivity.updateThumbnail(true); } @Override |