diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/camera/data/LocalMediaData.java | 6 | ||||
-rw-r--r-- | src/com/android/camera/data/SimpleViewData.java | 5 | ||||
-rw-r--r-- | src/com/android/camera/ui/FilmStripView.java | 107 | ||||
-rw-r--r-- | src/com/android/camera/ui/ZoomView.java | 51 |
4 files changed, 126 insertions, 43 deletions
diff --git a/src/com/android/camera/data/LocalMediaData.java b/src/com/android/camera/data/LocalMediaData.java index 3679b08e4..573da45db 100644 --- a/src/com/android/camera/data/LocalMediaData.java +++ b/src/com/android/camera/data/LocalMediaData.java @@ -127,6 +127,11 @@ public abstract class LocalMediaData implements LocalData { } @Override + public int getOrientation() { + return 0; + } + + @Override public String getPath() { return mPath; } @@ -383,6 +388,7 @@ public abstract class LocalMediaData implements LocalData { return result; } + @Override public int getOrientation() { return mOrientation; } diff --git a/src/com/android/camera/data/SimpleViewData.java b/src/com/android/camera/data/SimpleViewData.java index 3ff17226a..a73a52ece 100644 --- a/src/com/android/camera/data/SimpleViewData.java +++ b/src/com/android/camera/data/SimpleViewData.java @@ -75,6 +75,11 @@ public class SimpleViewData implements LocalData { } @Override + public int getOrientation() { + return 0; + } + + @Override public int getViewType() { return FilmStripView.ImageData.TYPE_REMOVABLE_VIEW; } diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java index abb2a84e5..9b9e974b9 100644 --- a/src/com/android/camera/ui/FilmStripView.java +++ b/src/com/android/camera/ui/FilmStripView.java @@ -159,6 +159,11 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { */ public int getHeight(); + /** + * Returns the orientation of the image. + */ + public int getOrientation(); + /** Returns the image data type */ public int getViewType(); @@ -1048,7 +1053,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { * Translates the {@link ViewItem} on the left of the current one to match * the full-screen layout. In full-screen, we show only one {@link ViewItem} * which occupies the whole screen. The other left ones are put on the left - * side in full scales. + * side in full scales. Does nothing if there's no next item. * * @param currItem The item ID of the current one to be translated. * @param drawAreaWidth The width of the current draw area. @@ -1088,7 +1093,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { /** * Fade out the {@link ViewItem} on the right of the current one in - * full-screen layout. + * full-screen layout. Does nothing if there's no previous item. * * @param currItem The ID of the item to fade. */ @@ -1155,59 +1160,90 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { (mScale - FILM_STRIP_SCALE) / (FULL_SCREEN_SCALE - FILM_STRIP_SCALE)); final int fullScreenWidth = mDrawArea.width() + mViewGap; + // Decide the position for all view items on the left and the right first. + + // Left items. + for (int itemID = mCurrentItem - 1; itemID >= 0; itemID--) { + final ViewItem curr = mViewItem[itemID]; + if (curr == null) { + break; + } + + // First, layout relatively to the next one. + final int currLeft = mViewItem[itemID + 1].getLeftPosition() + - curr.getView().getMeasuredWidth() - mViewGap; + curr.setLeftPosition(currLeft); + } + // Right items. + for (int itemID = mCurrentItem + 1; itemID < BUFFER_SIZE; itemID++) { + ViewItem curr = mViewItem[itemID]; + if (curr == null) { + break; + } + + // First, layout relatively to the previous one. + ViewItem prev = mViewItem[itemID - 1]; + int currLeft = + prev.getLeftPosition() + prev.getView().getMeasuredWidth() + + mViewGap; + curr.setLeftPosition(currLeft); + } + // Layout the current ViewItem first. if (scaleFraction == 1f) { - if (mCenterX < mViewItem[mCurrentItem].getCenterX()) { - // In full-screen and it's not the first one and mCenterX is on - // the left of the center, we draw the current one to "fade down". + final ViewItem currItem = mViewItem[mCurrentItem]; + final int currCenterX = currItem.getCenterX(); + if (mCenterX < currCenterX) { + // In full-screen and mCenterX is on the left of the center, + // we draw the current one to "fade down". fadeAndScaleRightViewItem(mCurrentItem); - } else if(mCenterX > mViewItem[mCurrentItem].getCenterX()) { - // In full-screen and it's not the last one and mCenterX is on - // the right of the center, we draw the current one translated. + } else if(mCenterX > currCenterX) { + // In full-screen and mCenterX is on the right of the center, + // we draw the current one translated. translateLeftViewItem(mCurrentItem, fullScreenWidth, scaleFraction); } else { - mViewItem[mCurrentItem].layoutIn(mDrawArea, mCenterX, mScale); - mViewItem[mCurrentItem].setTranslationX(0f, mScale); - mViewItem[mCurrentItem].getView().setAlpha(1f); + currItem.layoutIn(mDrawArea, mCenterX, mScale); + currItem.setTranslationX(0f, mScale); + currItem.getView().setAlpha(1f); } } else { + final ViewItem currItem = mViewItem[mCurrentItem]; // The normal filmstrip has no translation for the current item. If it has // translation before, gradually set it to zero. - mViewItem[mCurrentItem].setTranslationX( - mViewItem[mCurrentItem].getScaledTranslationX(mScale) * scaleFraction, + currItem.setTranslationX( + currItem.getScaledTranslationX(mScale) * scaleFraction, mScale); - mViewItem[mCurrentItem].layoutIn(mDrawArea, mCenterX, mScale); + currItem.layoutIn(mDrawArea, mCenterX, mScale); + if (mViewItem[mCurrentItem - 1] == null) { + currItem.getView().setAlpha(1f); + } else { + final int currCenterX = currItem.getCenterX(); + final int prevCenterX = mViewItem[mCurrentItem - 1].getCenterX(); + final float fadeDownFraction = + ((float) mCenterX - prevCenterX) / (currCenterX - prevCenterX); + currItem.getView().setAlpha( + (1 - fadeDownFraction) * (1 - scaleFraction) + fadeDownFraction); + } } // Layout the rest dependent on the current scale. - // images on the left + // Items on the left for (int itemID = mCurrentItem - 1; itemID >= 0; itemID--) { final ViewItem curr = mViewItem[itemID]; if (curr == null) { break; } - - // First, layout relatively to the next one. - final int currLeft = mViewItem[itemID + 1].getLeftPosition() - - curr.getView().getMeasuredWidth() - mViewGap; - curr.setLeftPosition(currLeft); translateLeftViewItem(itemID, fullScreenWidth, scaleFraction); } - // images on the right + // Items on the right for (int itemID = mCurrentItem + 1; itemID < BUFFER_SIZE; itemID++) { ViewItem curr = mViewItem[itemID]; if (curr == null) { - continue; + break; } - // First, layout relatively to the previous one. - ViewItem prev = mViewItem[itemID - 1]; - int currLeft = - prev.getLeftPosition() + prev.getView().getMeasuredWidth() - + mViewGap; - curr.setLeftPosition(currLeft); curr.layoutIn(mDrawArea, mCenterX, mScale); View currView = curr.getView(); if (scaleFraction == 1) { @@ -1227,7 +1263,7 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { } } curr.setTranslationX( - (mViewItem[mCurrentItem].getLeftPosition() - currLeft) + (mViewItem[mCurrentItem].getLeftPosition() - curr.getLeftPosition()) * scaleFraction, mScale); } } @@ -2109,8 +2145,11 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { return; } ViewItem curr = mViewItem[mCurrentItem]; - if(curr == null || !mDataAdapter.getImageData(curr.getId()) - .isUIActionSupported(ImageData.ACTION_ZOOM)) { + if (curr == null) { + return; + } + ImageData imageData = mDataAdapter.getImageData(curr.getId()); + if(!imageData.isUIActionSupported(ImageData.ACTION_ZOOM)) { return; } Uri uri = getCurrentContentUri(); @@ -2118,7 +2157,8 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { if (uri == null || uri == Uri.EMPTY) { return; } - mZoomView.loadBitmap(uri, viewRect); + int orientation = imageData.getOrientation(); + mZoomView.loadBitmap(uri, orientation, viewRect); } private void cancelLoadingZoomedImage() { @@ -2435,6 +2475,9 @@ public class FilmStripView extends ViewGroup implements BottomControlsListener { ViewItem curr = mViewItem[mCurrentItem]; // Make sure the image is not overly scaled newScale = Math.min(newScale, mMaxScale); + if (newScale == mScale) { + return true; + } float postScale = newScale / mScale; curr.postScale(focusX, focusY, postScale, mDrawArea.width(), mDrawArea.height()); mScale = newScale; diff --git a/src/com/android/camera/ui/ZoomView.java b/src/com/android/camera/ui/ZoomView.java index c4a49042c..65c4f2e4a 100644 --- a/src/com/android/camera/ui/ZoomView.java +++ b/src/com/android/camera/ui/ZoomView.java @@ -47,35 +47,58 @@ public class ZoomView extends ImageView { private DecodePartialBitmap mPartialDecodingTask; private Uri mUri; + private int mOrientation; private class DecodePartialBitmap extends AsyncTask<RectF, Void, Bitmap> { @Override protected Bitmap doInBackground(RectF... params) { RectF endRect = params[0]; + + // Calculate the rotation matrix to apply orientation on the original image + // rect. + RectF fullResRect = new RectF(0, 0, mFullResImageWidth - 1, mFullResImageHeight - 1); + Matrix rotationMatrix = new Matrix(); + rotationMatrix.setRotate(mOrientation, 0, 0); + rotationMatrix.mapRect(fullResRect); + // Set the translation of the matrix so that after rotation, the top left + // of the image rect is at (0, 0) + rotationMatrix.postTranslate(-fullResRect.left, -fullResRect.top); + rotationMatrix.mapRect(fullResRect, new RectF(0, 0, mFullResImageWidth - 1, + mFullResImageHeight - 1)); + // Find intersection with the screen RectF visibleRect = new RectF(endRect); visibleRect.intersect(0, 0, mViewportWidth - 1, mViewportHeight - 1); + // Calculate the mapping (i.e. transform) between current low res rect + // and full res image rect, and apply the mapping on current visible rect + // to find out the partial region in the full res image that we need + // to decode. + Matrix mapping = new Matrix(); + mapping.setRectToRect(endRect, fullResRect, Matrix.ScaleToFit.CENTER); + RectF visibleAfterRotation = new RectF(); + mapping.mapRect(visibleAfterRotation, visibleRect); - Matrix m2 = new Matrix(); - m2.setRectToRect(endRect, new RectF(0, 0, mFullResImageWidth - 1, - mFullResImageHeight - 1), Matrix.ScaleToFit.CENTER); + // Now the visible region we have is rotated, we need to reverse the + // rotation to find out the region in the original image RectF visibleInImage = new RectF(); - m2.mapRect(visibleInImage, visibleRect); + Matrix invertRotation = new Matrix(); + rotationMatrix.invert(invertRotation); + invertRotation.mapRect(visibleInImage, visibleAfterRotation); // Decode region - Rect v = new Rect(); - visibleInImage.round(v); + Rect region = new Rect(); + visibleInImage.round(region); // Make sure region to decode is inside the image. - v.intersect(0, 0, mFullResImageWidth - 1, mFullResImageHeight - 1); + region.intersect(0, 0, mFullResImageWidth - 1, mFullResImageHeight - 1); if (isCancelled()) { return null; } BitmapFactory.Options options = new BitmapFactory.Options(); - options.inSampleSize = getSampleFactor(v.width(), v.height()); + options.inSampleSize = getSampleFactor(region.width(), region.height()); if (mRegionDecoder == null) { InputStream is = getInputStream(); try { @@ -88,8 +111,13 @@ public class ZoomView extends ImageView { if (mRegionDecoder == null) { return null; } - Bitmap b = mRegionDecoder.decodeRegion(v, options); - return b; + Bitmap b = mRegionDecoder.decodeRegion(region, options); + if (isCancelled()) { + return null; + } + Matrix rotation = new Matrix(); + rotation.setRotate(mOrientation); + return Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), rotation, false); } @Override @@ -120,9 +148,10 @@ public class ZoomView extends ImageView { }); } - public void loadBitmap(Uri uri, RectF imageRect) { + public void loadBitmap(Uri uri, int orientation, RectF imageRect) { if (!uri.equals(mUri)) { mUri = uri; + mOrientation = orientation; mFullResImageHeight = 0; mFullResImageWidth = 0; decodeImageSize(); |