summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/camera/data/LocalMediaData.java6
-rw-r--r--src/com/android/camera/data/SimpleViewData.java5
-rw-r--r--src/com/android/camera/ui/FilmStripView.java107
-rw-r--r--src/com/android/camera/ui/ZoomView.java51
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();