summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRuben Brunk <rubenbrunk@google.com>2012-10-15 12:02:54 -0700
committerRuben Brunk <rubenbrunk@google.com>2012-10-16 18:25:00 -0700
commit0225fcd8513803711a3d5647e4927e2d8a9cfe34 (patch)
treef931cb3c3178fe2761b5f67c8cd786509457529f
parentc057d64b701fc2de9f0d5fec7dbd34779647a442 (diff)
downloadandroid_packages_apps_Snap-0225fcd8513803711a3d5647e4927e2d8a9cfe34.tar.gz
android_packages_apps_Snap-0225fcd8513803711a3d5647e4927e2d8a9cfe34.tar.bz2
android_packages_apps_Snap-0225fcd8513803711a3d5647e4927e2d8a9cfe34.zip
Added fixed aspect ratio support for cropping.
Bug: 7350377 Change-Id: I8110ea999c764de675fe11f586ab9bc7af205f46
-rw-r--r--src/com/android/gallery3d/filtershow/FilterShowActivity.java47
-rw-r--r--src/com/android/gallery3d/filtershow/PanelController.java97
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/GeometryMath.java54
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java245
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java38
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java28
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java20
-rw-r--r--src/com/android/gallery3d/filtershow/ui/ImageButtonTitle.java4
8 files changed, 420 insertions, 113 deletions
diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
index f76179d8b..35c74ebe1 100644
--- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java
+++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java
@@ -222,7 +222,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mPanelController.addPanel(mColorsButton, mListColors, 3);
- int []recastIDs = {
+ int[] recastIDs = {
R.id.vignetteButton,
R.id.vibranceButton,
R.id.contrastButton,
@@ -232,7 +232,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
R.id.exposureButton,
R.id.shadowRecoveryButton
};
- ImageFilter []filters = {
+ ImageFilter[] filters = {
new ImageFilterVignette(),
new ImageFilterVibrance(),
new ImageFilterContrast(),
@@ -243,7 +243,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
new ImageFilterShadows()
};
-
for (int i = 0; i < filters.length; i++) {
ImageSmallFilter fView = new ImageSmallFilter(this);
@@ -258,36 +257,36 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
fView.setId(recastIDs[i]);
mPanelController.addComponent(mColorsButton, fView);
- listColors.addView(fView,pos);
+ listColors.addView(fView, pos);
}
- int []overlayIDs = {
+ int[] overlayIDs = {
R.id.sharpenButton,
R.id.curvesButtonRGB
};
- int []overlayBitmaps = {
+ int[] overlayBitmaps = {
R.drawable.filtershow_button_colors_sharpen,
R.drawable.filtershow_button_colors_curve
};
- int []overlayNames = {
+ int[] overlayNames = {
R.string.sharpen,
R.string.curvesRGB
};
- for (int i = 0; i < overlayIDs.length; i++) {
+ for (int i = 0; i < overlayIDs.length; i++) {
ImageWithIcon fView = new ImageWithIcon(this);
View v = listColors.findViewById(overlayIDs[i]);
int pos = listColors.indexOfChild(v);
listColors.removeView(v);
- final int sid =overlayNames[i];
- ImageFilterExposure efilter = new ImageFilterExposure(){
+ final int sid = overlayNames[i];
+ ImageFilterExposure efilter = new ImageFilterExposure() {
{
mName = getString(sid);
}
};
efilter.setParameter(-300);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
- overlayBitmaps[i] );
+ overlayBitmaps[i]);
fView.setIcon(bitmap);
fView.setImageFilter(efilter);
@@ -296,7 +295,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
fView.setId(overlayIDs[i]);
mPanelController.addComponent(mColorsButton, fView);
- listColors.addView(fView,pos);
+ listColors.addView(fView, pos);
}
mPanelController.addComponent(mColorsButton, findViewById(R.id.curvesButtonRGB));
@@ -311,6 +310,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mPanelController.addView(findViewById(R.id.applyEffect));
mPanelController.addView(findViewById(R.id.pickCurvesChannel));
+ mPanelController.addView(findViewById(R.id.aspect));
findViewById(R.id.resetOperationsButton).setOnClickListener(
createOnClickResetOperationsButton());
@@ -330,27 +330,27 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
mImageZoom.setSeekBar(seekBar);
mPanelController.setRowPanel(findViewById(R.id.secondRowPanel));
mPanelController.setUtilityPanel(this, findViewById(R.id.filterButtonsList),
- findViewById(R.id.applyEffect));
+ findViewById(R.id.applyEffect), findViewById(R.id.aspect));
mPanelController.setMasterImage(mImageShow);
mPanelController.setCurrentPanel(mFxButton);
Intent intent = getIntent();
String data = intent.getDataString();
if (data != null) {
Uri uri = Uri.parse(data);
- mImageLoader.loadBitmap(uri,getScreenImageSize());
+ mImageLoader.loadBitmap(uri, getScreenImageSize());
} else {
pickImage();
}
}
- private int getScreenImageSize(){
- DisplayMetrics metrics = new DisplayMetrics();
+ private int getScreenImageSize() {
+ DisplayMetrics metrics = new DisplayMetrics();
Display display = getWindowManager().getDefaultDisplay();
- Point size = new Point();
+ Point size = new Point();
display.getSize(size);
display.getMetrics(metrics);
int msize = Math.min(size.x, size.y);
- return (133*msize)/metrics.densityDpi;
+ return (133 * msize) / metrics.densityDpi;
}
private void showSavingProgress() {
@@ -540,7 +540,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
filter.setController(this);
filter.setImageLoader(mImageLoader);
listFilters.addView(filter);
- ImageSmallFilter previousFilter = filter;
+ ImageSmallFilter previousFilter = filter;
BitmapFactory.Options o = new BitmapFactory.Options();
o.inScaled = false;
@@ -577,9 +577,11 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
Drawable npd2 = getResources().getDrawable(R.drawable.filtershow_border_brush);
borders[p++] = new ImageFilterBorder(npd2);
borders[p++] = new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize, 0);
- borders[p++] = new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize, mImageBorderSize);
+ borders[p++] = new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize,
+ mImageBorderSize);
borders[p++] = new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize, 0);
- borders[p++] = new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize, mImageBorderSize);
+ borders[p++] = new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize,
+ mImageBorderSize);
ImageSmallFilter previousFilter = null;
for (int i = 0; i < p; i++) {
@@ -637,7 +639,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
}
}
-
// //////////////////////////////////////////////////////////////////////////////
// imageState panel...
@@ -809,7 +810,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
if (resultCode == RESULT_OK) {
if (requestCode == SELECT_PICTURE) {
Uri selectedImageUri = data.getData();
- mImageLoader.loadBitmap(selectedImageUri,getScreenImageSize());
+ mImageLoader.loadBitmap(selectedImageUri, getScreenImageSize());
}
}
}
diff --git a/src/com/android/gallery3d/filtershow/PanelController.java b/src/com/android/gallery3d/filtershow/PanelController.java
index a21bb4fe1..6c69cf567 100644
--- a/src/com/android/gallery3d/filtershow/PanelController.java
+++ b/src/com/android/gallery3d/filtershow/PanelController.java
@@ -20,9 +20,11 @@ import com.android.gallery3d.filtershow.filters.ImageFilterSharpen;
import com.android.gallery3d.filtershow.filters.ImageFilterVibrance;
import com.android.gallery3d.filtershow.filters.ImageFilterVignette;
import com.android.gallery3d.filtershow.filters.ImageFilterWBalance;
+import com.android.gallery3d.filtershow.imageshow.ImageCrop;
import com.android.gallery3d.filtershow.imageshow.ImageShow;
import com.android.gallery3d.filtershow.presets.ImagePreset;
import com.android.gallery3d.filtershow.ui.ImageCurves;
+import com.android.gallery3d.filtershow.ui.ImageButtonTitle;
import java.util.HashMap;
import java.util.Vector;
@@ -113,17 +115,96 @@ public class PanelController implements OnClickListener {
private String mEffectName = null;
private int mParameterValue = 0;
private boolean mShowParameterValue = false;
-
- public UtilityPanel(Context context, View view, View textView) {
+ private View mAspectButton = 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;
+
+ public UtilityPanel(Context context, View view, View textView, View button) {
mContext = context;
mView = view;
mTextView = (TextView) textView;
+ mAspectButton = button;
}
public boolean selected() {
return mSelected;
}
+ 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.aspect1to1_effect));
+ ((ImageCrop) mCurrentImage).applyClear();
+ break;
+ }
+ mCurrentAspectButton = (mCurrentAspectButton + 1) % NUMBER_OF_ASPECT_BUTTONS;
+ }
+ }
+
+ public void showAspectButtons() {
+ if (mAspectButton != null)
+ mAspectButton.setVisibility(View.VISIBLE);
+ mCurrentAspectButton = ASPECT_NONE;
+ }
+
+ public void hideAspectButtons() {
+ if (mAspectButton != null)
+ mAspectButton.setVisibility(View.GONE);
+ }
+
public void onNewValue(int value) {
mParameterValue = value;
updateText();
@@ -259,8 +340,9 @@ public class PanelController implements OnClickListener {
mRowPanel = rowPanel;
}
- public void setUtilityPanel(Context context, View utilityPanel, View textView) {
- mUtilityPanel = new UtilityPanel(context, utilityPanel, textView);
+ public void setUtilityPanel(Context context, View utilityPanel, View textView,
+ View button) {
+ mUtilityPanel = new UtilityPanel(context, utilityPanel, textView, button);
}
public void setMasterImage(ImageShow imageShow) {
@@ -402,7 +484,7 @@ public class PanelController implements OnClickListener {
if (mCurrentImage != null) {
mCurrentImage.unselect();
}
-
+ mUtilityPanel.hideAspectButtons();
switch (view.getId()) {
case R.id.straightenButton: {
mCurrentImage = showImageView(R.id.imageStraighten);
@@ -415,6 +497,7 @@ public class PanelController implements OnClickListener {
String ename = mCurrentImage.getContext().getString(R.string.crop);
mUtilityPanel.setEffectName(ename);
mUtilityPanel.setShowParameter(false);
+ mUtilityPanel.showAspectButtons();
break;
}
case R.id.rotateButton: {
@@ -510,6 +593,10 @@ public class PanelController implements OnClickListener {
ensureFilter("Redeye");
break;
}
+ case R.id.aspect: {
+ mUtilityPanel.nextAspectButton();
+ break;
+ }
case R.id.applyEffect: {
showPanel(mCurrentPanel);
break;
diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMath.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMath.java
new file mode 100644
index 000000000..95d174f42
--- /dev/null
+++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMath.java
@@ -0,0 +1,54 @@
+package com.android.gallery3d.filtershow.imageshow;
+
+public class GeometryMath {
+ protected static float clamp(float i, float low, float high) {
+ return Math.max(Math.min(i, high), low);
+ }
+
+ protected static float[] shortestVectorFromPointToLine(float[] point, float[] l1, float[] l2) {
+ float x1 = l1[0];
+ float x2 = l2[0];
+ float y1 = l1[1];
+ float y2 = l2[1];
+ float xdelt = x2 - x1;
+ float ydelt = y2 - y1;
+ if (xdelt == 0 && ydelt == 0)
+ return null;
+ float u = ((point[0] - x1) * xdelt + (point[1] - y1) * ydelt)
+ / (xdelt * xdelt + ydelt * ydelt);
+ float[] ret = {
+ (x1 + u * (x2 - x1)), (y1 + u * (y2 - y1))
+ };
+ return ret;
+ }
+
+ //A . B
+ protected static float dotProduct(float[] a, float[] b){
+ return a[0] * b[0] + a[1] * b[1];
+ }
+
+ protected 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){
+ 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){
+ float [] p = { point2[0] - point1[0], point2[1] - point1[1] };
+ return p;
+ }
+
+ protected 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;
+ }
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
index 4d171bf4c..e34e3a249 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
@@ -36,6 +36,12 @@ public class ImageCrop extends ImageGeometry {
private static final int MOVE_BOTTOM = 8;
private static final int MOVE_BLOCK = 16;
+ //Corners
+ private static final int TOP_LEFT = MOVE_TOP | MOVE_LEFT;
+ private static final int TOP_RIGHT = MOVE_TOP | MOVE_RIGHT;
+ private static final int BOTTOM_RIGHT = MOVE_BOTTOM | MOVE_RIGHT;
+ private static final int BOTTOM_LEFT = MOVE_BOTTOM | MOVE_LEFT;
+
private static final float MIN_CROP_WIDTH_HEIGHT = 0.1f;
private static final int TOUCH_TOLERANCE = 30;
@@ -78,6 +84,104 @@ public class ImageCrop extends ImageGeometry {
borderPaint.setStrokeWidth(2f);
}
+ private boolean switchCropBounds(int moving_corner, RectF dst) {
+ RectF crop = getCropBoundsDisplayed();
+ float dx1 = 0;
+ float dy1 = 0;
+ float dx2 = 0;
+ float dy2 = 0;
+ if ((moving_corner & MOVE_RIGHT) != 0) {
+ dx1 = mCurrentX - crop.right;
+ } else if ((moving_corner & MOVE_LEFT) != 0) {
+ dx1 = mCurrentX - crop.left;
+ }
+ if ((moving_corner & MOVE_BOTTOM) != 0) {
+ dy1 = mCurrentY - crop.bottom;
+ } else if ((moving_corner & MOVE_TOP) != 0) {
+ dy1 = mCurrentY - crop.top;
+ }
+ RectF newCrop = null;
+ //Fix opposite corner in place and move sides
+ if (moving_corner == BOTTOM_RIGHT) {
+ newCrop = new RectF(crop.left, crop.top, crop.left + crop.height(), crop.top
+ + crop.width());
+ } else if (moving_corner == BOTTOM_LEFT) {
+ newCrop = new RectF(crop.right - crop.height(), crop.top, crop.right, crop.top
+ + crop.width());
+ } else if (moving_corner == TOP_LEFT) {
+ newCrop = new RectF(crop.right - crop.height(), crop.bottom - crop.width(),
+ crop.right, crop.bottom);
+ } else if (moving_corner == TOP_RIGHT) {
+ newCrop = new RectF(crop.left, crop.bottom - crop.width(), crop.left
+ + crop.height(), crop.bottom);
+ }
+ if ((moving_corner & MOVE_RIGHT) != 0) {
+ dx2 = mCurrentX - newCrop.right;
+ } else if ((moving_corner & MOVE_LEFT) != 0) {
+ dx2 = mCurrentX - newCrop.left;
+ }
+ if ((moving_corner & MOVE_BOTTOM) != 0) {
+ dy2 = mCurrentY - newCrop.bottom;
+ } else if ((moving_corner & MOVE_TOP) != 0) {
+ dy2 = mCurrentY - newCrop.top;
+ }
+ if (Math.sqrt(dx1*dx1 + dy1*dy1) > Math.sqrt(dx2*dx2 + dy2*dy2)){
+ Matrix m = getCropBoundDisplayMatrix();
+ Matrix m0 = new Matrix();
+ if (!m.invert(m0)){
+ if (LOGV)
+ Log.v(LOGTAG, "FAILED TO INVERT CROP MATRIX");
+ return false;
+ }
+ if (!m0.mapRect(newCrop)){
+ if (LOGV)
+ Log.v(LOGTAG, "FAILED TO MAP RECTANGLE TO RECTANGLE");
+ return false;
+ }
+ float temp = mAspectWidth;
+ mAspectWidth = mAspectHeight;
+ mAspectHeight = temp;
+ dst.set(newCrop);
+ return true;
+ }
+ return false;
+ }
+
+ public void apply(float w, float h){
+ mFixAspectRatio = true;
+ mAspectWidth = w;
+ mAspectHeight = h;
+ setLocalCropBounds(getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
+ getLocalStraighten()));
+ cropSetup();
+ saveAndSetPreset();
+ invalidate();
+ }
+
+ public void applyOriginal() {
+ mFixAspectRatio = true;
+ RectF photobounds = getLocalPhotoBounds();
+ float w = photobounds.width();
+ float h = photobounds.height();
+ float scale = Math.min(w, h);
+ mAspectWidth = w / scale;
+ mAspectHeight = h / scale;
+ setLocalCropBounds(getUntranslatedStraightenCropBounds(photobounds,
+ getLocalStraighten()));
+ cropSetup();
+ saveAndSetPreset();
+ invalidate();
+ }
+
+ public void applyClear() {
+ mFixAspectRatio = false;
+ setLocalCropBounds(getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
+ getLocalStraighten()));
+ cropSetup();
+ saveAndSetPreset();
+ invalidate();
+ }
+
private float getScaledMinWidthHeight() {
RectF disp = new RectF(0, 0, getWidth(), getHeight());
float scaled = Math.min(disp.width(), disp.height()) * MIN_CROP_WIDTH_HEIGHT
@@ -94,6 +198,19 @@ public class ImageCrop extends ImageGeometry {
return m;
}
+ protected Matrix getCropBoundDisplayMatrix(){
+ Matrix m = getCropRotationMatrix(getLocalRotation(), getLocalPhotoBounds());
+ if (m == null) {
+ if (LOGV)
+ Log.v(LOGTAG, "FAILED TO MAP CROP BOUNDS TO RECTANGLE");
+ m = new Matrix();
+ }
+ float zoom = computeScale(getWidth(), getHeight());
+ m.postTranslate(mXOffset, mYOffset);
+ m.postScale(zoom, zoom, mCenterX, mCenterY);
+ return m;
+ }
+
protected RectF getCropBoundsDisplayed() {
RectF bounds = getLocalCropBounds();
RectF crop = new RectF(bounds);
@@ -249,9 +366,47 @@ public class ImageCrop extends ImageGeometry {
if (cropped.contains(x, y) && (movingEdges == 0)) {
movingEdges = MOVE_BLOCK;
}
+ if (mFixAspectRatio && (movingEdges != MOVE_BLOCK)) {
+ movingEdges = fixEdgeToCorner(movingEdges);
+ }
invalidate();
}
+ private int fixEdgeToCorner(int moving_edges){
+ if (moving_edges == MOVE_LEFT) {
+ moving_edges |= MOVE_TOP;
+ }
+ if (moving_edges == MOVE_TOP) {
+ moving_edges |= MOVE_LEFT;
+ }
+ if (moving_edges == MOVE_RIGHT) {
+ moving_edges |= MOVE_BOTTOM;
+ }
+ if (moving_edges == MOVE_BOTTOM) {
+ moving_edges |= MOVE_RIGHT;
+ }
+ return moving_edges;
+ }
+
+ private RectF fixedCornerResize(RectF r, int moving_corner, float dx, float dy){
+ RectF newCrop = null;
+ //Fix opposite corner in place and move sides
+ if (moving_corner == BOTTOM_RIGHT) {
+ newCrop = new RectF(r.left, r.top, r.left + r.width() + dx, r.top + r.height()
+ + dy);
+ } else if (moving_corner == BOTTOM_LEFT) {
+ newCrop = new RectF(r.right - r.width() + dx, r.top, r.right, r.top + r.height()
+ + dy);
+ } else if (moving_corner == TOP_LEFT) {
+ newCrop = new RectF(r.right - r.width() + dx, r.bottom - r.height() + dy,
+ r.right, r.bottom);
+ } else if (moving_corner == TOP_RIGHT) {
+ newCrop = new RectF(r.left, r.bottom - r.height() + dy, r.left
+ + r.width() + dx, r.bottom);
+ }
+ return newCrop;
+ }
+
private void moveEdges(float dX, float dY) {
RectF cropped = getRotatedCropBounds();
float minWidthHeight = getScaledMinWidthHeight();
@@ -260,25 +415,22 @@ public class ImageCrop extends ImageGeometry {
float deltaY = dY / scale;
int select = movingEdges;
if (mFixAspectRatio && (select != MOVE_BLOCK)) {
- if ((select & MOVE_LEFT) != 0) {
- select &= ~MOVE_BOTTOM;
+ if (select == MOVE_LEFT) {
select |= MOVE_TOP;
- deltaY = getNewHeightForWidthAspect(deltaX, mAspectWidth, mAspectHeight);
}
- if ((select & MOVE_TOP) != 0) {
- select &= ~MOVE_RIGHT;
+ if (select == MOVE_TOP) {
select |= MOVE_LEFT;
- deltaX = getNewWidthForHeightAspect(deltaY, mAspectWidth, mAspectHeight);
}
- if ((select & MOVE_RIGHT) != 0) {
- select &= ~MOVE_TOP;
+ if (select == MOVE_RIGHT) {
select |= MOVE_BOTTOM;
- deltaY = getNewHeightForWidthAspect(deltaX, mAspectWidth, mAspectHeight);
}
- if ((select & MOVE_BOTTOM) != 0) {
- select &= ~MOVE_LEFT;
+ if (select == MOVE_BOTTOM) {
select |= MOVE_RIGHT;
- deltaX = getNewWidthForHeightAspect(deltaY, mAspectWidth, mAspectHeight);
+ }
+ RectF blank = new RectF();
+ if(switchCropBounds(select, blank)){
+ setCropBounds(blank);
+ return;
}
}
@@ -293,6 +445,7 @@ public class ImageCrop extends ImageGeometry {
} else {
float dx = 0;
float dy = 0;
+
if ((select & MOVE_LEFT) != 0) {
dx = Math.min(cropped.left + deltaX, cropped.right - minWidthHeight) - cropped.left;
}
@@ -309,26 +462,50 @@ public class ImageCrop extends ImageGeometry {
}
if (mFixAspectRatio) {
- if (dx < dy) {
- dy = getNewHeightForWidthAspect(dx, mAspectWidth, mAspectHeight);
- } else {
- dx = getNewWidthForHeightAspect(dy, mAspectWidth, mAspectHeight);
+ RectF crop = getCropBoundsDisplayed();
+ float [] l1 = {crop.left, crop.bottom};
+ float [] l2 = {crop.right, crop.top};
+ if(movingEdges == TOP_LEFT || movingEdges == BOTTOM_RIGHT){
+ l1[1] = crop.top;
+ l2[1] = crop.bottom;
+ }
+ float[] b = { l1[0] - l2[0], l1[1] - l2[1] };
+ float[] disp = {dx, dy};
+ float[] bUnit = GeometryMath.normalize(b);
+ float sp = GeometryMath.scalarProjection(disp, bUnit);
+ dx = sp * bUnit[0];
+ dy = sp * bUnit[1];
+ RectF newCrop = fixedCornerResize(crop, select, dx * scale, dy * scale);
+ Matrix m = getCropBoundDisplayMatrix();
+ Matrix m0 = new Matrix();
+ if (!m.invert(m0)){
+ if (LOGV)
+ Log.v(LOGTAG, "FAILED TO INVERT CROP MATRIX");
+ return;
+ }
+ if (!m0.mapRect(newCrop)){
+ if (LOGV)
+ Log.v(LOGTAG, "FAILED TO MAP RECTANGLE TO RECTANGLE");
+ return;
+ }
+ setCropBounds(newCrop);
+ return;
+ } else {
+ if ((select & MOVE_LEFT) != 0) {
+ cropped.left += dx;
+ }
+ if ((select & MOVE_TOP) != 0) {
+ cropped.top += dy;
+ }
+ if ((select & MOVE_RIGHT) != 0) {
+ cropped.right += dx;
+ }
+ if ((select & MOVE_BOTTOM) != 0) {
+ cropped.bottom += dy;
}
- }
-
- if ((select & MOVE_LEFT) != 0) {
- cropped.left += dx;
- }
- if ((select & MOVE_TOP) != 0) {
- cropped.top += dy;
- }
- if ((select & MOVE_RIGHT) != 0) {
- cropped.right += dx;
- }
- if ((select & MOVE_BOTTOM) != 0) {
- cropped.bottom += dy;
}
}
+ movingEdges = select;
Matrix m = getCropRotationMatrix(getLocalRotation(), getLocalPhotoBounds());
Matrix m0 = new Matrix();
if (!m.invert(m0)) {
@@ -363,9 +540,9 @@ public class ImageCrop extends ImageGeometry {
@Override
protected void setActionMove(float x, float y) {
- if (movingEdges != 0)
+ if (movingEdges != 0){
moveEdges(x - mCurrentX, y - mCurrentY);
-
+ }
super.setActionMove(x, y);
}
@@ -435,7 +612,7 @@ public class ImageCrop extends ImageGeometry {
canvas.restore();
}
- private int bitCycleLeft(int x, int times, int d){
+ private int bitCycleLeft(int x, int times, int d) {
int mask = (1 << d) - 1;
int mout = x & mask;
times %= d;
@@ -449,7 +626,7 @@ public class ImageCrop extends ImageGeometry {
protected int decoder(int movingEdges, float rotation) {
int rot = constrainedRotation(rotation);
- switch(rot){
+ switch (rot) {
case 90:
return bitCycleLeft(movingEdges, 3, 4);
case 180:
@@ -460,4 +637,4 @@ public class ImageCrop extends ImageGeometry {
return movingEdges;
}
}
-} \ No newline at end of file
+}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java b/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java
index 68df702ea..d5a7ada69 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java
@@ -31,6 +31,7 @@ import android.view.View;
import com.android.gallery3d.filtershow.imageshow.GeometryMetadata.FLIP;
import com.android.gallery3d.filtershow.presets.ImagePreset;
+import com.android.gallery3d.filtershow.imageshow.GeometryMath;
public abstract class ImageGeometry extends ImageSlave {
private boolean mVisibilityGained = false;
@@ -74,6 +75,35 @@ public abstract class ImageGeometry extends ImageSlave {
calculateLocalScalingFactorAndOffset();
}
+ protected static float angleFor(float dx, float dy) {
+ return (float) (Math.atan2(dx, dy) * 180 / Math.PI);
+ }
+
+ protected static int snappedAngle(float angle) {
+ float remainder = angle % 90;
+ int current = (int) (angle / 90); // truncates
+ if (remainder < -45) {
+ --current;
+ } else if (remainder > 45) {
+ ++current;
+ }
+ return current * 90;
+ }
+
+ protected float getCurrentTouchAngle(){
+ if (mCurrentX == mTouchCenterX && mCurrentY == mTouchCenterY) {
+ return 0;
+ }
+ float dX1 = mTouchCenterX - mCenterX;
+ float dY1 = mTouchCenterY - mCenterY;
+ float dX2 = mCurrentX - mCenterX;
+ float dY2 = mCurrentY - mCenterY;
+
+ float angleA = angleFor(dX1, dY1);
+ float angleB = angleFor(dX2, dY2);
+ return (angleB - angleA) % 360;
+ }
+
protected float computeScale(float width, float height) {
float imageWidth = mLocalGeometry.getPhotoBounds().width();
float imageHeight = mLocalGeometry.getPhotoBounds().height();
@@ -219,8 +249,8 @@ public abstract class ImageGeometry extends ImageSlave {
if (array.length < 2)
return;
for (int x = 0; x < array.length; x += 2) {
- array[x] = clamp(array[x], imageBound.left, imageBound.right);
- array[x + 1] = clamp(array[x + 1], imageBound.top, imageBound.bottom);
+ array[x] = GeometryMath.clamp(array[x], imageBound.left, imageBound.right);
+ array[x + 1] = GeometryMath.clamp(array[x + 1], imageBound.top, imageBound.bottom);
}
}
@@ -346,10 +376,6 @@ public abstract class ImageGeometry extends ImageSlave {
setImagePreset(copy);
}
- protected static float clamp(float i, float low, float high) {
- return Math.max(Math.min(i, high), low);
- }
-
public static RectF getUntranslatedStraightenCropBounds(RectF imageRect, float straightenAngle) {
float deg = straightenAngle;
if (deg < 0) {
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java b/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java
index 089e11732..775aa716b 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java
@@ -23,7 +23,6 @@ import android.graphics.Paint;
import android.util.AttributeSet;
public class ImageRotate extends ImageGeometry {
- private static final float MATH_PI = (float) Math.PI;
private float mBaseAngle = 0;
private float mAngle = 0;
@@ -39,35 +38,10 @@ public class ImageRotate extends ImageGeometry {
super(context);
}
- private float angleFor(float dx, float dy) {
- return (float) (Math.atan2(dx, dy) * 180 / MATH_PI);
- }
-
- private int snappedAngle(float angle) {
- float remainder = angle % 90;
- int current = (int) (angle / 90); // truncates
- if (remainder < -45) {
- --current;
- } else if (remainder > 45) {
- ++current;
- }
- return current * 90;
- }
-
private static final Paint gPaint = new Paint();
private void computeValue() {
- if (mCurrentX == mTouchCenterX && mCurrentY == mTouchCenterY) {
- return;
- }
- float dX1 = mTouchCenterX - mCenterX;
- float dY1 = mTouchCenterY - mCenterY;
- float dX2 = mCurrentX - mCenterX;
- float dY2 = mCurrentY - mCenterY;
-
- float angleA = angleFor(dX1, dY1);
- float angleB = angleFor(dX2, dY2);
- float angle = (angleB - angleA) % 360;
+ float angle = getCurrentTouchAngle();
mAngle = (mBaseAngle - angle) % 360;
}
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java b/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java
index 2fd6b9b35..26c9671bb 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java
@@ -24,8 +24,6 @@ import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
-import com.android.gallery3d.filtershow.imageshow.ImageGeometry.MODES;
-
public class ImageStraighten extends ImageGeometry {
private float mBaseAngle = 0;
@@ -61,22 +59,8 @@ public class ImageStraighten extends ImageGeometry {
setCropToStraighten();
}
- private float angleFor(float dx, float dy) {
- return (float) (Math.atan2(dx, dy) * 180 / Math.PI);
- }
-
private void computeValue() {
- if (mCurrentX == mTouchCenterX && mCurrentY == mTouchCenterY) {
- return;
- }
- float dX1 = mTouchCenterX - mCenterX;
- float dY1 = mTouchCenterY - mCenterY;
- float dX2 = mCurrentX - mCenterX;
- float dY2 = mCurrentY - mCenterY;
-
- float angleA = angleFor(dX1, dY1);
- float angleB = angleFor(dX2, dY2);
- float angle = (angleB - angleA) % 360;
+ float angle = getCurrentTouchAngle();
mAngle = (mBaseAngle - angle) % 360;
mAngle = Math.max(MIN_STRAIGHTEN_ANGLE, mAngle);
mAngle = Math.min(MAX_STRAIGHTEN_ANGLE, mAngle);
@@ -100,7 +84,7 @@ public class ImageStraighten extends ImageGeometry {
@Override
public void onNewValue(int value) {
- setLocalStraighten(clamp(value, MIN_STRAIGHTEN_ANGLE, MAX_STRAIGHTEN_ANGLE));
+ setLocalStraighten(GeometryMath.clamp(value, MIN_STRAIGHTEN_ANGLE, MAX_STRAIGHTEN_ANGLE));
if (getPanelController() != null) {
getPanelController().onNewValue((int) getLocalStraighten());
}
diff --git a/src/com/android/gallery3d/filtershow/ui/ImageButtonTitle.java b/src/com/android/gallery3d/filtershow/ui/ImageButtonTitle.java
index 51ed7fb20..7e12b98f9 100644
--- a/src/com/android/gallery3d/filtershow/ui/ImageButtonTitle.java
+++ b/src/com/android/gallery3d/filtershow/ui/ImageButtonTitle.java
@@ -25,6 +25,10 @@ public class ImageButtonTitle extends ImageButton {
mTextPadding = value;
}
+ public void setText(String text) {
+ mText = text;
+ }
+
public ImageButtonTitle(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = getContext().obtainStyledAttributes(