OSDN Git Service

Fix zooming position
authornicolasroard <nicolasroard@google.com>
Fri, 26 Oct 2012 03:14:02 +0000 (20:14 -0700)
committernicolasroard <nicolasroard@google.com>
Sun, 28 Oct 2012 23:45:32 +0000 (16:45 -0700)
bug:7386221
Change-Id: I70215d3c3e12d08eee40a3cc848e3fc50f7dda75

src/com/android/gallery3d/filtershow/FilterShowActivity.java
src/com/android/gallery3d/filtershow/cache/ImageLoader.java
src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java
src/com/android/gallery3d/filtershow/imageshow/ImageZoom.java

index 1ed45ed..ef0415f 100644 (file)
@@ -157,6 +157,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
         ImageShow.setDefaultBackgroundColor(getResources().getColor(R.color.background_screen));
         ImageSmallFilter.setDefaultBackgroundColor(getResources().getColor(R.color.background_main_toolbar));
         // TODO: get those values from XML.
+        ImageZoom.setZoomedSize(getPixelsFromDip(256));
         FramedTextButton.setTextSize((int) getPixelsFromDip(14));
         ImageShow.setTextSize((int) getPixelsFromDip(12));
         ImageShow.setTextPadding((int) getPixelsFromDip(10));
index b661aad..308e49c 100644 (file)
@@ -68,19 +68,20 @@ public class ImageLoader {
 
     private FilterShowActivity mActivity = null;
 
-    private static final int ORI_NORMAL     = ExifInterface.ORIENTATION_NORMAL;
-    private static final int ORI_ROTATE_90  = ExifInterface.ORIENTATION_ROTATE_90;
-    private static final int ORI_ROTATE_180 = ExifInterface.ORIENTATION_ROTATE_180;
-    private static final int ORI_ROTATE_270 = ExifInterface.ORIENTATION_ROTATE_270;
-    private static final int ORI_FLIP_HOR   = ExifInterface.ORIENTATION_FLIP_HORIZONTAL;
-    private static final int ORI_FLIP_VERT  = ExifInterface.ORIENTATION_FLIP_VERTICAL;
-    private static final int ORI_TRANSPOSE  = ExifInterface.ORIENTATION_TRANSPOSE;
-    private static final int ORI_TRANSVERSE = ExifInterface.ORIENTATION_TRANSVERSE;
+    public static final int ORI_NORMAL     = ExifInterface.ORIENTATION_NORMAL;
+    public static final int ORI_ROTATE_90  = ExifInterface.ORIENTATION_ROTATE_90;
+    public static final int ORI_ROTATE_180 = ExifInterface.ORIENTATION_ROTATE_180;
+    public static final int ORI_ROTATE_270 = ExifInterface.ORIENTATION_ROTATE_270;
+    public static final int ORI_FLIP_HOR   = ExifInterface.ORIENTATION_FLIP_HORIZONTAL;
+    public static final int ORI_FLIP_VERT  = ExifInterface.ORIENTATION_FLIP_VERTICAL;
+    public static final int ORI_TRANSPOSE  = ExifInterface.ORIENTATION_TRANSPOSE;
+    public static final int ORI_TRANSVERSE = ExifInterface.ORIENTATION_TRANSVERSE;
 
     private Context mContext = null;
     private Uri mUri = null;
 
     private Rect mOriginalBounds = null;
+    private static int mZoomOrientation = ORI_NORMAL;
 
     public ImageLoader(FilterShowActivity activity, Context context) {
         mActivity = activity;
@@ -89,6 +90,10 @@ public class ImageLoader {
         mHiresCache = new DelayedPresetCache(this, 3);
     }
 
+    public static int getZoomOrientation() {
+        return mZoomOrientation;
+    }
+
     public FilterShowActivity getActivity() {
         return mActivity;
     }
@@ -170,6 +175,7 @@ public class ImageLoader {
 
     public static Bitmap rotateToPortrait(Bitmap bitmap,int ori) {
            Matrix matrix = new Matrix();
+           mZoomOrientation = ori;
            int w = bitmap.getWidth();
            int h = bitmap.getHeight();
            if (ori == ORI_ROTATE_90 ||
index 77e78fe..a5ccbe0 100644 (file)
@@ -20,10 +20,9 @@ import android.graphics.Bitmap;
 import android.graphics.Matrix;
 import android.graphics.RectF;
 
+import com.android.gallery3d.filtershow.cache.ImageLoader;
 import com.android.gallery3d.filtershow.filters.ImageFilterGeometry;
 
-import java.util.Arrays;
-
 public class GeometryMetadata {
     // Applied in order: rotate, crop, scale.
     // Do not scale saved image (presumably?).
@@ -62,7 +61,7 @@ public class GeometryMetadata {
         if (!mCropBounds.equals(mPhotoBounds)) {
             return true;
         }
-        if (!mFlip.equals(FLIP.NONE)){
+        if (!mFlip.equals(FLIP.NONE)) {
             return true;
         }
         return false;
@@ -236,6 +235,99 @@ public class GeometryMetadata {
         }
     }
 
+    public Matrix getMatrixOriginalOrientation(int orientation, float originalWidth,
+            float originalHeight) {
+        Matrix imageRotation = new Matrix();
+        switch (orientation) {
+            case ImageLoader.ORI_ROTATE_90: {
+                imageRotation.setRotate(90, originalWidth / 2f, originalHeight / 2f);
+                imageRotation.postTranslate(-(originalWidth - originalHeight) / 2f,
+                        -(originalHeight - originalWidth) / 2f);
+                break;
+            }
+            case ImageLoader.ORI_ROTATE_180: {
+                imageRotation.setRotate(180, originalWidth / 2f, originalHeight / 2f);
+                break;
+            }
+            case ImageLoader.ORI_ROTATE_270: {
+                imageRotation.setRotate(270, originalWidth / 2f, originalHeight / 2f);
+                imageRotation.postTranslate(-(originalWidth - originalHeight) / 2f,
+                        -(originalHeight - originalWidth) / 2f);
+                break;
+            }
+            case ImageLoader.ORI_FLIP_HOR: {
+                imageRotation.preScale(-1, 1);
+                break;
+            }
+            case ImageLoader.ORI_FLIP_VERT: {
+                imageRotation.preScale(1, -1);
+                break;
+            }
+            case ImageLoader.ORI_TRANSPOSE: {
+                imageRotation.setRotate(90, originalWidth / 2f, originalHeight / 2f);
+                imageRotation.postTranslate(-(originalWidth - originalHeight) / 2f,
+                        -(originalHeight - originalWidth) / 2f);
+                imageRotation.preScale(1, -1);
+                break;
+            }
+            case ImageLoader.ORI_TRANSVERSE: {
+                imageRotation.setRotate(270, originalWidth / 2f, originalHeight / 2f);
+                imageRotation.postTranslate(-(originalWidth - originalHeight) / 2f,
+                        -(originalHeight - originalWidth) / 2f);
+                imageRotation.preScale(1, -1);
+                break;
+            }
+        }
+        return imageRotation;
+    }
+
+    public Matrix getOriginalToScreen(boolean rotate, float originalWidth, float originalHeight,
+            float viewWidth, float viewHeight) {
+        RectF photoBounds = getPhotoBounds();
+        RectF cropBounds = getPreviewCropBounds();
+        float imageWidth = cropBounds.width();
+        float imageHeight = cropBounds.height();
+
+        int orientation = ImageLoader.getZoomOrientation();
+        Matrix imageRotation = getMatrixOriginalOrientation(orientation, originalWidth,
+                originalHeight);
+        if (orientation == ImageLoader.ORI_ROTATE_90 ||
+                orientation == ImageLoader.ORI_ROTATE_270 ||
+                orientation == ImageLoader.ORI_TRANSPOSE ||
+                orientation == ImageLoader.ORI_TRANSVERSE) {
+            float tmp = originalWidth;
+            originalWidth = originalHeight;
+            originalHeight = tmp;
+        }
+
+        float preScale = GeometryMath.scale(originalWidth, originalHeight,
+                photoBounds.width(), photoBounds.height());
+        float scale = GeometryMath.scale(imageWidth, imageHeight, viewWidth, viewHeight);
+        // checks if local rotation is an odd multiple of 90.
+        if (((int) (getRotation() / 90)) % 2 != 0) {
+            scale = GeometryMath.scale(imageWidth, imageHeight, viewHeight, viewWidth);
+        }
+        // put in screen coordinates
+        RectF scaledCrop = GeometryMath.scaleRect(cropBounds, scale);
+        RectF scaledPhoto = GeometryMath.scaleRect(photoBounds, scale);
+        float[] displayCenter = {
+                viewWidth / 2f, viewHeight / 2f
+        };
+        Matrix m1 = GeometryMetadata.buildWanderingCropMatrix(scaledPhoto, scaledCrop,
+                getRotation(), getStraightenRotation(), getFlipType(), displayCenter);
+        float[] cropCenter = {
+                scaledCrop.centerX(), scaledCrop.centerY()
+        };
+        m1.mapPoints(cropCenter);
+        GeometryMetadata.concatRecenterMatrix(m1, cropCenter, displayCenter);
+        m1.preRotate(getStraightenRotation(), scaledPhoto.centerX(), scaledPhoto.centerY());
+        m1.preScale(scale, scale);
+        m1.preScale(preScale, preScale);
+        m1.preConcat(imageRotation);
+
+        return m1;
+    }
+
     // TODO: refactor away
     public Matrix getFlipMatrix(float width, float height) {
         FLIP type = getFlipType();
index e659e90..c7586fe 100644 (file)
@@ -19,14 +19,20 @@ package com.android.gallery3d.filtershow.imageshow;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Matrix;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 
+import com.android.gallery3d.filtershow.cache.ImageLoader;
+
 public class ImageZoom extends ImageSlave {
+    private static final String LOGTAG = "ImageZoom";
     private boolean mTouchDown = false;
     private boolean mZoomedIn = false;
     private Rect mZoomBounds = null;
+    private static float mMaxSize = 512;
 
     public ImageZoom(Context context) {
         super(context);
@@ -36,6 +42,17 @@ public class ImageZoom extends ImageSlave {
         super(context, attrs);
     }
 
+    public static void setZoomedSize(float size) {
+        mMaxSize = size;
+    }
+
+    @Override
+    public void resetParameter() {
+        super.resetParameter();
+        mZoomedIn = false;
+        mTouchDown = false;
+    }
+
     @Override
     public void onTouchDown(float x, float y) {
         super.onTouchDown(x, y);
@@ -43,23 +60,28 @@ public class ImageZoom extends ImageSlave {
             return;
         }
         mTouchDown = true;
-        Rect originalBounds = mImageLoader.getOriginalBounds();
-        Rect imageBounds = getImageBounds();
-        float touchX = x - imageBounds.left;
-        float touchY = y - imageBounds.top;
-
-        float w = originalBounds.width();
-        float h = originalBounds.height();
-        float ratio = w / h;
-        int mw = getWidth() / 2;
-        int mh = getHeight() / 2;
-        int cx = (int) (w / 2);
-        int cy = (int) (h / 2);
-        cx = (int) (touchX / imageBounds.width() * w);
-        cy = (int) (touchY / imageBounds.height() * h);
-        int left = cx - mw;
-        int top = cy - mh;
-        mZoomBounds = new Rect(left, top, left + mw * 2, top + mh * 2);
+        GeometryMetadata geo = getImagePreset().mGeoData;
+        Matrix originalToScreen = geo.getOriginalToScreen(true,
+                mImageLoader.getOriginalBounds().width(),
+                mImageLoader.getOriginalBounds().height(),
+                getWidth(), getHeight());
+        float[] point = new float[2];
+        point[0] = x;
+        point[1] = y;
+        Matrix inverse = new Matrix();
+        originalToScreen.invert(inverse);
+        inverse.mapPoints(point);
+
+        float ratio = (float) getWidth() / (float) getHeight();
+        float mh = mMaxSize;
+        float mw = ratio * mh;
+        RectF zoomRect = new RectF(mTouchX - mw, mTouchY - mh, mTouchX + mw, mTouchY + mw);
+        inverse.mapRect(zoomRect);
+        zoomRect.set(zoomRect.centerX() - mw, zoomRect.centerY() - mh,
+                zoomRect.centerX() + mw, zoomRect.centerY() + mh);
+        mZoomBounds = new Rect((int) zoomRect.left, (int) zoomRect.top,
+                (int) zoomRect.right, (int) zoomRect.bottom);
+        invalidate();
     }
 
     @Override
@@ -70,14 +92,42 @@ public class ImageZoom extends ImageSlave {
     @Override
     public void onDraw(Canvas canvas) {
         drawBackground(canvas);
+
         Bitmap filteredImage = null;
-        if ((mZoomedIn ||mTouchDown) && mImageLoader != null) {
-            filteredImage = mImageLoader.getScaleOneImageForPreset(this, getImagePreset(), mZoomBounds, false);
+        if ((mZoomedIn || mTouchDown) && mImageLoader != null) {
+            filteredImage = mImageLoader.getScaleOneImageForPreset(this, getImagePreset(),
+                    mZoomBounds, false);
         } else {
             requestFilteredImages();
             filteredImage = getFilteredImage();
         }
+        canvas.save();
+        if (mZoomedIn || mTouchDown) {
+            int orientation = ImageLoader.getZoomOrientation();
+            switch (orientation) {
+                case ImageLoader.ORI_ROTATE_90: {
+                    canvas.rotate(90, getWidth() / 2, getHeight() / 2);
+                    break;
+                }
+                case ImageLoader.ORI_ROTATE_270: {
+                    canvas.rotate(270, getWidth() / 2, getHeight() / 2);
+                    break;
+                }
+                case ImageLoader.ORI_TRANSPOSE: {
+                    canvas.rotate(90, getWidth() / 2, getHeight() / 2);
+                    canvas.scale(1,  -1);
+                    break;
+                }
+                case ImageLoader.ORI_TRANSVERSE: {
+                    canvas.rotate(270, getWidth() / 2, getHeight() / 2);
+                    canvas.scale(1,  -1);
+                    break;
+                }
+            }
+        }
         drawImage(canvas, filteredImage);
+        canvas.restore();
+
         if (showControls()) {
             mSliderController.onDraw(canvas);
         }
@@ -97,4 +147,4 @@ public class ImageZoom extends ImageSlave {
         invalidate();
         return false;
     }
-}
\ No newline at end of file
+}