OSDN Git Service

Reworked crop/transform UI.
authorRuben Brunk <rubenbrunk@google.com>
Mon, 22 Oct 2012 10:50:38 +0000 (03:50 -0700)
committerRuben Brunk <rubenbrunk@google.com>
Tue, 23 Oct 2012 23:44:29 +0000 (16:44 -0700)
Bug: 7385644
Bug: 7378335
Bug: 7366075

Change-Id: Iee7e0a0741b69269b08726bad45e29d86834054e

src/com/android/gallery3d/filtershow/PanelController.java
src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java
src/com/android/gallery3d/filtershow/imageshow/GeometryMath.java
src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java
src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
src/com/android/gallery3d/filtershow/imageshow/ImageFlip.java
src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java
src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java
src/com/android/gallery3d/filtershow/imageshow/ImageShow.java
src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java

index 2bf95e7..8f1bdb4 100644 (file)
@@ -139,14 +139,7 @@ public class PanelController implements OnClickListener {
         private boolean mShowParameterValue = false;
         private View mAspectButton = null;
         private View mCurvesButton = null;
-        private int mCurrentAspectButton = 0;
-        private static final int NUMBER_OF_ASPECT_BUTTONS = 6;
-        private static final int ASPECT_NONE = 0;
-        private static final int ASPECT_1TO1 = 1;
-        private static final int ASPECT_5TO7 = 2;
-        private static final int ASPECT_4TO6 = 3;
-        private static final int ASPECT_16TO9 = 4;
-        private static final int ASPECT_ORIG = 5;
+        boolean firstTimeCropDisplayed = true;
 
         public UtilityPanel(Context context, View view, View textView,
                 View aspectButton, View curvesButton) {
@@ -198,69 +191,6 @@ public class PanelController implements OnClickListener {
             imageCrop.invalidate();
         }
 
-        public void nextAspectButton() {
-            if (mAspectButton instanceof ImageButtonTitle
-                    && mCurrentImage instanceof ImageCrop) {
-                switch (mCurrentAspectButton) {
-                    case ASPECT_NONE:
-                        ((ImageButtonTitle) mAspectButton).setText(mContext
-                                .getString(R.string.aspect)
-                                + " "
-                                + mContext.getString(R.string.aspect1to1_effect));
-                        ((ImageCrop) mCurrentImage).apply(1, 1);
-                        break;
-                    case ASPECT_1TO1:
-                        ((ImageButtonTitle) mAspectButton).setText(mContext
-                                .getString(R.string.aspect)
-                                + " "
-                                + mContext.getString(R.string.aspect5to7_effect));
-                        ((ImageCrop) mCurrentImage).apply(7, 5);
-                        break;
-                    case ASPECT_5TO7:
-                        ((ImageButtonTitle) mAspectButton).setText(mContext
-                                .getString(R.string.aspect)
-                                + " "
-                                + mContext.getString(R.string.aspect4to6_effect));
-                        ((ImageCrop) mCurrentImage).apply(6, 4);
-                        break;
-                    case ASPECT_4TO6:
-                        ((ImageButtonTitle) mAspectButton).setText(mContext
-                                .getString(R.string.aspect)
-                                + " "
-                                + mContext.getString(R.string.aspect9to16_effect));
-                        ((ImageCrop) mCurrentImage).apply(16, 9);
-                        break;
-                    case ASPECT_16TO9:
-                        ((ImageButtonTitle) mAspectButton).setText(mContext
-                                .getString(R.string.aspect)
-                                + " "
-                                + mContext.getString(R.string.aspectOriginal_effect));
-                        ((ImageCrop) mCurrentImage).applyOriginal();
-                        break;
-                    case ASPECT_ORIG:
-                        ((ImageButtonTitle) mAspectButton).setText(mContext
-                                .getString(R.string.aspect)
-                                + " "
-                                + mContext.getString(R.string.aspectNone_effect));
-                        ((ImageCrop) mCurrentImage).applyClear();
-                        break;
-                    default:
-                        ((ImageButtonTitle) mAspectButton).setText(mContext
-                                .getString(R.string.aspect)
-                                + " "
-                                + mContext.getString(R.string.aspectNone_effect));
-                        ((ImageCrop) mCurrentImage).applyClear();
-                        mCurrentAspectButton = ASPECT_NONE;
-                        break;
-                }
-                mCurrentAspectButton = (mCurrentAspectButton + 1) % NUMBER_OF_ASPECT_BUTTONS;
-            }
-        }
-
-        void setCurrentAspectButton(int n) {
-            mCurrentAspectButton = n;
-        }
-
         public void showAspectButtons() {
             if (mAspectButton != null)
                 mAspectButton.setVisibility(View.VISIBLE);
@@ -653,8 +583,10 @@ public class PanelController implements OnClickListener {
                 String ename = mCurrentImage.getContext().getString(R.string.crop);
                 mUtilityPanel.setEffectName(ename);
                 mUtilityPanel.setShowParameter(false);
-                mUtilityPanel.setCurrentAspectButton(-1);
-                mUtilityPanel.nextAspectButton();
+                if (mCurrentImage instanceof ImageCrop && mUtilityPanel.firstTimeCropDisplayed){
+                    ((ImageCrop) mCurrentImage).applyOriginal();
+                    mUtilityPanel.firstTimeCropDisplayed = false;
+                }
                 mUtilityPanel.showAspectButtons();
                 break;
             }
@@ -760,7 +692,6 @@ public class PanelController implements OnClickListener {
                 break;
             }
             case R.id.aspect: {
-                mUtilityPanel.nextAspectButton();
                 mUtilityPanel.showAspectButtons();
                 break;
             }
index 0405768..bdcb0ea 100644 (file)
@@ -23,6 +23,7 @@ import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.RectF;
 
+import com.android.gallery3d.filtershow.imageshow.GeometryMath;
 import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
 
 public class ImageFilterGeometry extends ImageFilter {
@@ -78,19 +79,18 @@ public class ImageFilterGeometry extends ImageFilter {
         } else {
             temp = Bitmap.createBitmap(cropBounds.width(), cropBounds.height(), mConfig);
         }
+        float[] displayCenter = {
+                temp.getWidth() / 2f, temp.getHeight() / 2f
+        };
+
+        Matrix m1 = mGeometry.buildTotalXform(bitmap.getWidth(), bitmap.getHeight(), displayCenter);
 
-        RectF rp = mGeometry.getPhotoBounds();
-        RectF rc = mGeometry.getPreviewCropBounds();
-        Matrix drawMatrix = mGeometry.buildTotalXform(rp.width(), rp.height(), rc.width(),
-                rc.height(), rc.left, rc.top,
-                mGeometry.getRotation(), mGeometry.getStraightenRotation(),
-                bitmap.getWidth() / rp.width(), null);
         Canvas canvas = new Canvas(temp);
         Paint paint = new Paint();
         paint.setAntiAlias(true);
         paint.setFilterBitmap(true);
         paint.setDither(true);
-        canvas.drawBitmap(bitmap, drawMatrix, paint);
+        canvas.drawBitmap(bitmap, m1, paint);
         return temp;
     }
 
index 3f9d4fa..d27946a 100644 (file)
 
 package com.android.gallery3d.filtershow.imageshow;
 
+import android.graphics.RectF;
+
 public class GeometryMath {
-    protected static float clamp(float i, float low, float high) {
+
+    // Math operations for 2d vectors
+    public static float clamp(float i, float low, float high) {
         return Math.max(Math.min(i, high), low);
     }
 
@@ -35,36 +39,58 @@ public class GeometryMath {
         float[] ret = {
                 (x1 + u * (x2 - x1)), (y1 + u * (y2 - y1))
         };
-        return ret;
+        float [] vec = {ret[0] - point[0], ret[1] - point[1] };
+        return vec;
     }
 
-    //A . B
-    protected static float dotProduct(float[] a, float[] b){
+    // A . B
+    public static float dotProduct(float[] a, float[] b){
         return a[0] * b[0] + a[1] * b[1];
     }
 
-    protected static float[] normalize(float[] a){
+    public static float[] normalize(float[] a){
         float length = (float) Math.sqrt(a[0] * a[0] + a[1] * a[1]);
         float[] b = { a[0] / length, a[1] / length };
         return b;
     }
 
-    //A onto B
-    protected static float scalarProjection(float[] a, float[] b){
+    // A onto B
+    public static float scalarProjection(float[] a, float[] b){
         float length = (float) Math.sqrt(b[0] * b[0] + b[1] * b[1]);
         return dotProduct(a, b) / length;
     }
 
-    protected static float[] getVectorFromPoints(float [] point1, float [] point2){
+    public static float[] getVectorFromPoints(float [] point1, float [] point2){
         float [] p = { point2[0] - point1[0], point2[1] - point1[1] };
         return p;
     }
 
-    protected static float[] getUnitVectorFromPoints(float [] point1, float [] point2){
+    public static float[] getUnitVectorFromPoints(float [] point1, float [] point2){
         float [] p = { point2[0] - point1[0], point2[1] - point1[1] };
         float length = (float) Math.sqrt(p[0] * p[0] + p[1] * p[1]);
         p[0] = p[0] / length;
         p[1] = p[1] / length;
         return p;
     }
+
+    public static RectF scaleRect(RectF r, float scale){
+        return new RectF(r.left * scale, r.top * scale, r.right * scale, r.bottom * scale);
+    }
+
+    // A - B
+    public static float[] vectorSubtract(float [] a, float [] b){
+        int len = a.length;
+        if (len != b.length)
+            return null;
+        float [] ret = new float[len];
+        for (int i = 0; i < len; i++){
+            ret[i] = a[i] - b[i];
+        }
+        return ret;
+    }
+
+    public static float vectorLength(float [] a){
+        return (float) Math.sqrt(a[0] * a[0] + a[1] * a[1]);
+    }
+
 }
index 58c6f6f..897c8cb 100644 (file)
@@ -22,6 +22,8 @@ import android.graphics.RectF;
 
 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?).
@@ -178,22 +180,34 @@ public class GeometryMetadata {
                 + ",photoRect=" + mPhotoBounds.toShortString() + "]";
     }
 
-    protected Matrix getHorizontalMatrix(float width) {
+    // TODO: refactor away
+    protected static Matrix getHorizontalMatrix(float width) {
         Matrix flipHorizontalMatrix = new Matrix();
         flipHorizontalMatrix.setScale(-1, 1);
         flipHorizontalMatrix.postTranslate(width, 0);
         return flipHorizontalMatrix;
     }
 
-    protected Matrix getVerticalMatrix(float height) {
+    protected static void concatHorizontalMatrix(Matrix m, float width) {
+        m.postScale(-1, 1);
+        m.postTranslate(width, 0);
+    }
+
+    // TODO: refactor away
+    protected static Matrix getVerticalMatrix(float height) {
         Matrix flipVerticalMatrix = new Matrix();
         flipVerticalMatrix.setScale(1, -1);
         flipVerticalMatrix.postTranslate(0, height);
         return flipVerticalMatrix;
     }
 
-    public Matrix getFlipMatrix(float width, float height) {
-        FLIP type = getFlipType();
+    protected static void concatVerticalMatrix(Matrix m, float height) {
+        m.postScale(1, -1);
+        m.postTranslate(0, height);
+    }
+
+    // TODO: refactor away
+    public static Matrix getFlipMatrix(float width, float height, FLIP type) {
         if (type == FLIP.HORIZONTAL) {
             return getHorizontalMatrix(width);
         } else if (type == FLIP.VERTICAL) {
@@ -209,10 +223,28 @@ public class GeometryMetadata {
         }
     }
 
+    public static void concatMirrorMatrix(Matrix m, float width, float height, FLIP type) {
+        if (type == FLIP.HORIZONTAL) {
+            concatHorizontalMatrix(m, width);
+        } else if (type == FLIP.VERTICAL) {
+            concatVerticalMatrix(m, height);
+        } else if (type == FLIP.BOTH) {
+            concatVerticalMatrix(m, height);
+            concatHorizontalMatrix(m, width);
+        }
+    }
+
+    // TODO: refactor away
+    public Matrix getFlipMatrix(float width, float height) {
+        FLIP type = getFlipType();
+        return getFlipMatrix(width, height, type);
+    }
+
     public boolean hasSwitchedWidthHeight() {
         return (((int) (mRotation / 90)) % 2) != 0;
     }
 
+    // TODO: refactor away
     public Matrix buildGeometryMatrix(float width, float height, float scaling, float dx, float dy,
             float rotation) {
         float dx0 = width / 2;
@@ -225,6 +257,7 @@ public class GeometryMetadata {
         return m;
     }
 
+    // TODO: refactor away
     public Matrix buildGeometryMatrix(float width, float height, float scaling, float dx, float dy,
             boolean onlyRotate) {
         float rot = mRotation;
@@ -234,28 +267,124 @@ public class GeometryMetadata {
         return buildGeometryMatrix(width, height, scaling, dx, dy, rot);
     }
 
+    // TODO: refactor away
     public Matrix buildGeometryUIMatrix(float scaling, float dx, float dy) {
         float w = mPhotoBounds.width();
         float h = mPhotoBounds.height();
         return buildGeometryMatrix(w, h, scaling, dx, dy, false);
     }
 
-    public Matrix buildTotalXform(float pwidth, float pheight, float cwidth, float cheight,
-            float cleft, float ctop, float rotation, float straighten, float scale, RectF dst) {
-        float s_pwidth = pwidth * scale;
-        float s_pheight = pheight * scale;
-        Matrix m = getFlipMatrix(s_pwidth, s_pheight);
-        m.postRotate(rotation + straighten, s_pwidth / 2, s_pheight / 2);
-        Matrix m1 = getFlipMatrix(s_pwidth, s_pheight);
-        m1.postRotate(rotation, s_pwidth / 2, s_pheight / 2);
-        // find new top left for crop.
-        RectF crop = new RectF(cleft * scale, ctop * scale, (cleft + cwidth) * scale,
-                (ctop + cheight) * scale);
-        if (!m1.mapRect(crop))
-            return null;
-        if (dst != null)
-            dst.set(crop);
-        m.postTranslate(-crop.left, -crop.top);
+    public static Matrix buildPhotoMatrix(RectF photo, RectF crop, float rotation,
+            float straighten, FLIP type) {
+        Matrix m = new Matrix();
+        m.setRotate(straighten, photo.centerX(), photo.centerY());
+        concatMirrorMatrix(m, photo.right, photo.bottom, type);
+        m.postRotate(rotation, crop.centerX(), crop.centerY());
+
+        return m;
+    }
+
+    public static Matrix buildCropMatrix(RectF crop, float rotation) {
+        Matrix m = new Matrix();
+        m.setRotate(rotation, crop.centerX(), crop.centerY());
+        return m;
+    }
+
+    public static void concatRecenterMatrix(Matrix m, float[] currentCenter, float[] newCenter) {
+        m.postTranslate(newCenter[0] - currentCenter[0], newCenter[1] - currentCenter[1]);
+    }
+
+    /**
+     * Builds a matrix to transform a bitmap of width bmWidth and height
+     * bmHeight so that the region of the bitmap being cropped to is
+     * oriented and centered at displayCenter.
+     *
+     * @param bmWidth
+     * @param bmHeight
+     * @param displayCenter
+     * @return
+     */
+    public Matrix buildTotalXform(float bmWidth, float bmHeight, float[] displayCenter) {
+        RectF rp = getPhotoBounds();
+        RectF rc = getPreviewCropBounds();
+
+        float scale = bmWidth / rp.width();
+        RectF scaledCrop = GeometryMath.scaleRect(rc, scale);
+        RectF scaledPhoto = GeometryMath.scaleRect(rp, scale);
+
+        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());
+        return m1;
+    }
+
+    /**
+     * Builds a matrix that rotates photo rect about it's center by the
+     * straighten angle, mirrors it about the crop center, and rotates it about
+     * the crop center by the rotation angle, and re-centers the photo rect.
+     *
+     * @param photo
+     * @param crop
+     * @param rotation
+     * @param straighten
+     * @param type
+     * @param newCenter
+     * @return
+     */
+    public static Matrix buildCenteredPhotoMatrix(RectF photo, RectF crop, float rotation,
+            float straighten, FLIP type, float[] newCenter) {
+        Matrix m = buildPhotoMatrix(photo, crop, rotation, straighten, type);
+        float[] center = {
+                photo.centerX(), photo.centerY()
+        };
+        m.mapPoints(center);
+        concatRecenterMatrix(m, center, newCenter);
+        return m;
+    }
+
+    /**
+     * Builds a matrix that rotates a crop rect about it's center by rotation
+     * angle, then re-centers the crop rect.
+     *
+     * @param crop
+     * @param rotation
+     * @param newCenter
+     * @return
+     */
+    public static Matrix buildCenteredCropMatrix(RectF crop, float rotation, float[] newCenter) {
+        Matrix m = buildCropMatrix(crop, rotation);
+        float[] center = {
+                crop.centerX(), crop.centerY()
+        };
+        m.mapPoints(center);
+        concatRecenterMatrix(m, center, newCenter);
+        return m;
+    }
+
+    /**
+     * Builds a matrix that transforms the crop rect to its view coordinates
+     * inside the photo rect.
+     *
+     * @param photo
+     * @param crop
+     * @param rotation
+     * @param straighten
+     * @param type
+     * @param newCenter
+     * @return
+     */
+    public static Matrix buildWanderingCropMatrix(RectF photo, RectF crop, float rotation,
+            float straighten, FLIP type, float[] newCenter) {
+        Matrix m = buildCenteredPhotoMatrix(photo, crop, rotation, straighten, type, newCenter);
+        m.preRotate(-straighten, photo.centerX(), photo.centerY());
         return m;
     }
 }
index c740977..f0c520a 100644 (file)
@@ -52,6 +52,7 @@ public class ImageCrop extends ImageGeometry {
     private float mAspectHeight = 1;
     private boolean mFixAspectRatio = false;
 
+    private float mLastRot = 0;
     private final Paint borderPaint;
 
     private int movingEdges;
@@ -90,6 +91,12 @@ public class ImageCrop extends ImageGeometry {
         return getContext().getString(R.string.crop);
     }
 
+    private void swapAspect(){
+        float temp = mAspectWidth;
+        mAspectWidth = mAspectHeight;
+        mAspectHeight = temp;
+    }
+
     private boolean switchCropBounds(int moving_corner, RectF dst) {
         RectF crop = getCropBoundsDisplayed();
         float dx1 = 0;
@@ -144,9 +151,7 @@ public class ImageCrop extends ImageGeometry {
                      Log.v(LOGTAG, "FAILED TO MAP RECTANGLE TO RECTANGLE");
                  return false;
              }
-             float temp = mAspectWidth;
-             mAspectWidth = mAspectHeight;
-             mAspectHeight = temp;
+             swapAspect();
              dst.set(newCrop);
              return true;
         }
@@ -565,6 +570,11 @@ public class ImageCrop extends ImageGeometry {
 
     @Override
     protected void gainedVisibility() {
+        float rot = getLocalRotation();
+        // if has changed orientation via rotate
+        if( ((int) ((rot - mLastRot) / 90)) % 2 != 0 ){
+            swapAspect();
+        }
         cropSetup();
         mFirstDraw = true;
     }
@@ -577,19 +587,20 @@ public class ImageCrop extends ImageGeometry {
 
     @Override
     protected void lostVisibility() {
+        mLastRot = getLocalRotation();
     }
 
-    private void drawRuleOfThird(Canvas canvas, RectF bounds) {
+    private void drawRuleOfThird(Canvas canvas, RectF bounds, Paint p) {
         float stepX = bounds.width() / 3.0f;
         float stepY = bounds.height() / 3.0f;
         float x = bounds.left + stepX;
         float y = bounds.top + stepY;
         for (int i = 0; i < 2; i++) {
-            canvas.drawLine(x, bounds.top, x, bounds.bottom, gPaint);
+            canvas.drawLine(x, bounds.top, x, bounds.bottom, p);
             x += stepX;
         }
         for (int j = 0; j < 2; j++) {
-            canvas.drawLine(bounds.left, y, bounds.right, y, gPaint);
+            canvas.drawLine(bounds.left, y, bounds.right, y, p);
             y += stepY;
         }
     }
@@ -607,17 +618,22 @@ public class ImageCrop extends ImageGeometry {
             mFirstDraw = false;
         }
         float rotation = getLocalRotation();
-        drawTransformedBitmap(canvas, image, gPaint, true);
+
+        RectF crop = drawTransformed(canvas, image, gPaint);
+        gPaint.setColor(mBorderColor);
+        gPaint.setStrokeWidth(3);
+        gPaint.setStyle(Paint.Style.STROKE);
+        drawRuleOfThird(canvas, crop, gPaint);
 
         gPaint.setColor(mBorderColor);
         gPaint.setStrokeWidth(3);
         gPaint.setStyle(Paint.Style.STROKE);
         drawStraighten(canvas, gPaint);
-        RectF scaledCrop = unrotatedCropBounds();
-        drawRuleOfThird(canvas, scaledCrop);
+
         int decoded_moving = decoder(movingEdges, rotation);
         canvas.save();
         canvas.rotate(rotation, mCenterX, mCenterY);
+        RectF scaledCrop = unrotatedCropBounds();
         boolean notMoving = decoded_moving == 0;
         if (((decoded_moving & MOVE_TOP) != 0) || notMoving) {
             drawIndicator(canvas, cropIndicator, scaledCrop.centerX(), scaledCrop.top);
index 931ef86..5d6fe50 100644 (file)
@@ -139,7 +139,7 @@ public class ImageFlip extends ImageGeometry {
         gPaint.setFilterBitmap(true);
         gPaint.setDither(true);
         gPaint.setARGB(255, 255, 255, 255);
-        drawTransformedBitmap(canvas, image, gPaint, false);
+        drawTransformedCropped(canvas, image, gPaint);
     }
 
 }
index 6bdbeb8..590b53c 100644 (file)
@@ -221,6 +221,7 @@ public abstract class ImageGeometry extends ImageSlave {
         return getLocalRotation() + getLocalStraighten();
     }
 
+
     protected static float[] getCornersFromRect(RectF r) {
         // Order is:
         // 0------->1
@@ -542,4 +543,67 @@ public abstract class ImageGeometry extends ImageSlave {
     protected void drawShape(Canvas canvas, Bitmap image) {
         // TODO: Override this stub.
     }
+
+    protected RectF drawTransformed(Canvas canvas, Bitmap photo, Paint p){
+        p.setARGB(255, 0, 0, 0);
+        RectF photoBounds = getLocalPhotoBounds();
+        RectF cropBounds = getLocalCropBounds();
+        float scale = computeScale(getWidth(), getHeight());
+        // put in screen coordinates
+        RectF scaledCrop = GeometryMath.scaleRect(cropBounds, scale);
+        RectF scaledPhoto = GeometryMath.scaleRect(photoBounds, scale);
+        float [] displayCenter = { getWidth() / 2f, getHeight() / 2f };
+        Matrix m = GeometryMetadata.buildCenteredPhotoMatrix(scaledPhoto, scaledCrop,
+                getLocalRotation(), getLocalStraighten(), getLocalFlip(), displayCenter);
+
+        Matrix m1 = GeometryMetadata.buildWanderingCropMatrix(scaledPhoto, scaledCrop,
+                getLocalRotation(), getLocalStraighten(), getLocalFlip(), displayCenter);
+        m1.mapRect(scaledCrop);
+        Path path = new Path();
+        path.addRect(scaledCrop, Path.Direction.CCW);
+
+        m.preScale(scale, scale);
+        canvas.save();
+        canvas.drawBitmap(photo, m, p);
+        canvas.restore();
+
+        p.setColor(Color.WHITE);
+        p.setStyle(Style.STROKE);
+        p.setStrokeWidth(2);
+        canvas.drawPath(path, p);
+        return scaledCrop;
+    }
+
+    protected void drawTransformedCropped(Canvas canvas, Bitmap photo, Paint p){
+        RectF photoBounds = getLocalPhotoBounds();
+        RectF cropBounds = getLocalCropBounds();
+        float imageWidth = cropBounds.width();
+        float imageHeight = cropBounds.height();
+        float scale = getWidth() / imageWidth;
+        if (imageHeight > imageWidth) {
+            scale = getHeight() / imageHeight;
+        }
+        // put in screen coordinates
+        RectF scaledCrop = GeometryMath.scaleRect(cropBounds, scale);
+        RectF scaledPhoto = GeometryMath.scaleRect(photoBounds, scale);
+        float [] displayCenter = { getWidth() / 2f, getHeight() / 2f };
+        Matrix m1 = GeometryMetadata.buildWanderingCropMatrix(scaledPhoto, scaledCrop,
+                getLocalRotation(), getLocalStraighten(), getLocalFlip(), displayCenter);
+        float [] cropCenter = { scaledCrop.centerX(), scaledCrop.centerY() };
+        m1.mapPoints(cropCenter);
+        GeometryMetadata.concatRecenterMatrix(m1, cropCenter, displayCenter);
+        m1.preRotate(getLocalStraighten(), scaledPhoto.centerX(), scaledPhoto.centerY());
+        m1.preScale(scale, scale);
+
+        p.setARGB(255, 0, 0, 0);
+        canvas.save();
+        canvas.drawBitmap(photo, m1, p);
+        canvas.restore();
+
+        p.setARGB(255, 0, 0, 0);
+        p.setStyle(Paint.Style.FILL);
+        scaledCrop.offset(displayCenter[0] - scaledCrop.centerX(), displayCenter[1]
+                - scaledCrop.centerY());
+        drawShadows(canvas, p, scaledCrop);
+    }
 }
index 0d458ca..90bbeaa 100644 (file)
@@ -84,6 +84,6 @@ public class ImageRotate extends ImageGeometry {
         gPaint.setFilterBitmap(true);
         gPaint.setDither(true);
         gPaint.setARGB(255, 255, 255, 255);
-        drawTransformedBitmap(canvas, image, gPaint, true);
+        drawTransformedCropped(canvas, image, gPaint);
     }
 }
index 72c594c..b157237 100644 (file)
@@ -64,7 +64,7 @@ public class ImageShow extends View implements OnGestureListener,
 
     protected ImageLoader mImageLoader = null;
     private ImageFilter mCurrentFilter = null;
-    private boolean mDirtyGeometry = true;
+    private boolean mDirtyGeometry = false;
 
     private Bitmap mBackgroundImage = null;
     private final boolean USE_BACKGROUND_IMAGE = false;
index 0f70b23..57a22aa 100644 (file)
@@ -19,6 +19,7 @@ package com.android.gallery3d.filtershow.imageshow;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.RectF;
@@ -33,7 +34,6 @@ public class ImageStraighten extends ImageGeometry {
 
     private static final String LOGTAG = "ImageStraighten";
     private static final Paint gPaint = new Paint();
-
     public ImageStraighten(Context context) {
         super(context);
     }
@@ -105,7 +105,7 @@ public class ImageStraighten extends ImageGeometry {
 
     @Override
     protected void drawShape(Canvas canvas, Bitmap image) {
-        drawTransformedBitmap(canvas, image, gPaint, false);
+        drawTransformed(canvas, image, gPaint);
 
         // Draw the grid
         RectF bounds = straightenBounds();