diff options
author | Ruben Brunk <rubenbrunk@google.com> | 2013-04-04 17:20:42 -0700 |
---|---|---|
committer | Ruben Brunk <rubenbrunk@google.com> | 2013-04-09 15:57:57 -0700 |
commit | 1a664450bed2737660057def2d25b0c6b49b3ba8 (patch) | |
tree | ff83702fc2dfd6de0608865d6d2a2d7b9e58fb04 /src/com/android/gallery3d/filtershow/imageshow | |
parent | ca13834b449c4586292ca9cc1853fd8e65884edd (diff) | |
download | android_packages_apps_Snap-1a664450bed2737660057def2d25b0c6b49b3ba8.tar.gz android_packages_apps_Snap-1a664450bed2737660057def2d25b0c6b49b3ba8.tar.bz2 android_packages_apps_Snap-1a664450bed2737660057def2d25b0c6b49b3ba8.zip |
Moving crop to a separate activity. Refactoring.
Bug: 8526929
Change-Id: I8acf6d46de069dd84c31afea6b4a7ae8e1c2fcce
Diffstat (limited to 'src/com/android/gallery3d/filtershow/imageshow')
4 files changed, 4 insertions, 533 deletions
diff --git a/src/com/android/gallery3d/filtershow/imageshow/BoundedRect.java b/src/com/android/gallery3d/filtershow/imageshow/BoundedRect.java deleted file mode 100644 index e94d1ed9e..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/BoundedRect.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.filtershow.imageshow; - -import android.graphics.Matrix; -import android.graphics.RectF; - -import java.util.Arrays; - -/** - * Maintains invariant that inner rectangle is constrained to be within the - * outer, rotated rectangle. - */ -public class BoundedRect { - private float rot; - private RectF outer; - private RectF inner; - private float[] innerRotated; - - public BoundedRect() { - rot = 0; - outer = new RectF(); - inner = new RectF(); - innerRotated = new float[8]; - } - - public BoundedRect(float rotation, RectF outerRect, RectF innerRect) { - rot = rotation; - outer = new RectF(outerRect); - inner = new RectF(innerRect); - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - /** - * Sets inner, and re-constrains it to fit within the rotated bounding rect. - */ - public void setInner(RectF newInner) { - if (inner.equals(newInner)) - return; - inner = newInner; - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - /** - * Sets rotation, and re-constrains inner to fit within the rotated bounding rect. - */ - public void setRotation(float rotation) { - if (rotation == rot) - return; - rot = rotation; - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - public RectF getInner() { - return new RectF(inner); - } - - /** - * Tries to move the inner rectangle by (dx, dy). If this would cause it to leave - * the bounding rectangle, snaps the inner rectangle to the edge of the bounding - * rectangle. - */ - public void moveInner(float dx, float dy) { - Matrix m0 = getInverseRotMatrix(); - - RectF translatedInner = new RectF(inner); - translatedInner.offset(dx, dy); - - float[] translatedInnerCorners = CropMath.getCornersFromRect(translatedInner); - float[] outerCorners = CropMath.getCornersFromRect(outer); - - m0.mapPoints(translatedInnerCorners); - float[] correction = { - 0, 0 - }; - - // find correction vectors for corners that have moved out of bounds - for (int i = 0; i < translatedInnerCorners.length; i += 2) { - float correctedInnerX = translatedInnerCorners[i] + correction[0]; - float correctedInnerY = translatedInnerCorners[i + 1] + correction[1]; - if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) { - float[] badCorner = { - correctedInnerX, correctedInnerY - }; - float[] nearestSide = CropMath.closestSide(badCorner, outerCorners); - float[] correctionVec = - GeometryMath.shortestVectorFromPointToLine(badCorner, nearestSide); - correction[0] += correctionVec[0]; - correction[1] += correctionVec[1]; - } - } - - for (int i = 0; i < translatedInnerCorners.length; i += 2) { - float correctedInnerX = translatedInnerCorners[i] + correction[0]; - float correctedInnerY = translatedInnerCorners[i + 1] + correction[1]; - if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) { - float[] correctionVec = { - correctedInnerX, correctedInnerY - }; - CropMath.getEdgePoints(outer, correctionVec); - correctionVec[0] -= correctedInnerX; - correctionVec[1] -= correctedInnerY; - correction[0] += correctionVec[0]; - correction[1] += correctionVec[1]; - } - } - - // Set correction - for (int i = 0; i < translatedInnerCorners.length; i += 2) { - float correctedInnerX = translatedInnerCorners[i] + correction[0]; - float correctedInnerY = translatedInnerCorners[i + 1] + correction[1]; - // update translated corners with correction vectors - translatedInnerCorners[i] = correctedInnerX; - translatedInnerCorners[i + 1] = correctedInnerY; - } - - innerRotated = translatedInnerCorners; - // reconstrain to update inner - reconstrain(); - } - - /** - * Attempts to resize the inner rectangle. If this would cause it to leave - * the bounding rect, clips the inner rectangle to fit. - */ - public void resizeInner(RectF newInner) { - Matrix m = getRotMatrix(); - Matrix m0 = getInverseRotMatrix(); - - float[] outerCorners = CropMath.getCornersFromRect(outer); - m.mapPoints(outerCorners); - float[] oldInnerCorners = CropMath.getCornersFromRect(inner); - float[] newInnerCorners = CropMath.getCornersFromRect(newInner); - RectF ret = new RectF(newInner); - - for (int i = 0; i < newInnerCorners.length; i += 2) { - float[] c = { - newInnerCorners[i], newInnerCorners[i + 1] - }; - float[] c0 = Arrays.copyOf(c, 2); - m0.mapPoints(c0); - if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) { - float[] outerSide = CropMath.closestSide(c, outerCorners); - float[] pathOfCorner = { - newInnerCorners[i], newInnerCorners[i + 1], - oldInnerCorners[i], oldInnerCorners[i + 1] - }; - float[] p = GeometryMath.lineIntersect(pathOfCorner, outerSide); - if (p == null) { - // lines are parallel or not well defined, so don't resize - p = new float[2]; - p[0] = oldInnerCorners[i]; - p[1] = oldInnerCorners[i + 1]; - } - // relies on corners being in same order as method - // getCornersFromRect - switch (i) { - case 0: - case 1: - ret.left = (p[0] > ret.left) ? p[0] : ret.left; - ret.top = (p[1] > ret.top) ? p[1] : ret.top; - break; - case 2: - case 3: - ret.right = (p[0] < ret.right) ? p[0] : ret.right; - ret.top = (p[1] > ret.top) ? p[1] : ret.top; - break; - case 4: - case 5: - ret.right = (p[0] < ret.right) ? p[0] : ret.right; - ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom; - break; - case 6: - case 7: - ret.left = (p[0] > ret.left) ? p[0] : ret.left; - ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom; - break; - default: - break; - } - } - } - float[] retCorners = CropMath.getCornersFromRect(ret); - m0.mapPoints(retCorners); - innerRotated = retCorners; - // reconstrain to update inner - reconstrain(); - } - - /** - * Attempts to resize the inner rectangle. If this would cause it to leave - * the bounding rect, clips the inner rectangle to fit while maintaining - * aspect ratio. - */ - public void fixedAspectResizeInner(RectF newInner) { - Matrix m = getRotMatrix(); - Matrix m0 = getInverseRotMatrix(); - - float aspectW = inner.width(); - float aspectH = inner.height(); - float aspRatio = aspectW / aspectH; - float[] corners = CropMath.getCornersFromRect(outer); - - m.mapPoints(corners); - float[] oldInnerCorners = CropMath.getCornersFromRect(inner); - float[] newInnerCorners = CropMath.getCornersFromRect(newInner); - - // find fixed corner - int fixed = -1; - if (inner.top == newInner.top) { - if (inner.left == newInner.left) - fixed = 0; // top left - else if (inner.right == newInner.right) - fixed = 2; // top right - } else if (inner.bottom == newInner.bottom) { - if (inner.right == newInner.right) - fixed = 4; // bottom right - else if (inner.left == newInner.left) - fixed = 6; // bottom left - } - // no fixed corner, return without update - if (fixed == -1) - return; - float widthSoFar = newInner.width(); - int moved = -1; - for (int i = 0; i < newInnerCorners.length; i += 2) { - float[] c = { - newInnerCorners[i], newInnerCorners[i + 1] - }; - float[] c0 = Arrays.copyOf(c, 2); - m0.mapPoints(c0); - if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) { - moved = i; - if (moved == fixed) - continue; - float[] l2 = CropMath.closestSide(c, corners); - float[] l1 = { - newInnerCorners[i], newInnerCorners[i + 1], - oldInnerCorners[i], oldInnerCorners[i + 1] - }; - float[] p = GeometryMath.lineIntersect(l1, l2); - if (p == null) { - // lines are parallel or not well defined, so set to old - // corner - p = new float[2]; - p[0] = oldInnerCorners[i]; - p[1] = oldInnerCorners[i + 1]; - } - // relies on corners being in same order as method - // getCornersFromRect - float fixed_x = oldInnerCorners[fixed]; - float fixed_y = oldInnerCorners[fixed + 1]; - float newWidth = Math.abs(fixed_x - p[0]); - float newHeight = Math.abs(fixed_y - p[1]); - newWidth = Math.max(newWidth, aspRatio * newHeight); - if (newWidth < widthSoFar) - widthSoFar = newWidth; - } - } - - float heightSoFar = widthSoFar / aspRatio; - RectF ret = new RectF(inner); - if (fixed == 0) { - ret.right = ret.left + widthSoFar; - ret.bottom = ret.top + heightSoFar; - } else if (fixed == 2) { - ret.left = ret.right - widthSoFar; - ret.bottom = ret.top + heightSoFar; - } else if (fixed == 4) { - ret.left = ret.right - widthSoFar; - ret.top = ret.bottom - heightSoFar; - } else if (fixed == 6) { - ret.right = ret.left + widthSoFar; - ret.top = ret.bottom - heightSoFar; - } - float[] retCorners = CropMath.getCornersFromRect(ret); - m0.mapPoints(retCorners); - innerRotated = retCorners; - // reconstrain to update inner - reconstrain(); - } - - // internal methods - - private boolean isConstrained() { - for (int i = 0; i < 8; i += 2) { - if (!CropMath.inclusiveContains(outer, innerRotated[i], innerRotated[i + 1])) - return false; - } - return true; - } - - private void reconstrain() { - // innerRotated has been changed to have incorrect values - CropMath.getEdgePoints(outer, innerRotated); - Matrix m = getRotMatrix(); - float[] unrotated = Arrays.copyOf(innerRotated, 8); - m.mapPoints(unrotated); - inner = CropMath.trapToRect(unrotated); - } - - private void rotateInner() { - Matrix m = getInverseRotMatrix(); - m.mapPoints(innerRotated); - } - - private Matrix getRotMatrix() { - Matrix m = new Matrix(); - m.setRotate(rot, outer.centerX(), outer.centerY()); - return m; - } - - private Matrix getInverseRotMatrix() { - Matrix m = new Matrix(); - m.setRotate(-rot, outer.centerX(), outer.centerY()); - return m; - } -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/CropMath.java b/src/com/android/gallery3d/filtershow/imageshow/CropMath.java deleted file mode 100644 index 9037ca043..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/CropMath.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.graphics.Matrix; -import android.graphics.RectF; - -import java.util.Arrays; - -public class CropMath { - - /** - * Gets a float array of the 2D coordinates representing a rectangles - * corners. - * The order of the corners in the float array is: - * 0------->1 - * ^ | - * | v - * 3<-------2 - * - * @param r the rectangle to get the corners of - * @return the float array of corners (8 floats) - */ - - public static float[] getCornersFromRect(RectF r) { - float[] corners = { - r.left, r.top, - r.right, r.top, - r.right, r.bottom, - r.left, r.bottom - }; - return corners; - } - - /** - * Returns true iff point (x, y) is within or on the rectangle's bounds. - * RectF's "contains" function treats points on the bottom and right bound - * as not being contained. - * - * @param r the rectangle - * @param x the x value of the point - * @param y the y value of the point - * @return - */ - public static boolean inclusiveContains(RectF r, float x, float y) { - return !(x > r.right || x < r.left || y > r.bottom || y < r.top); - } - - /** - * Takes an array of 2D coordinates representing corners and returns the - * smallest rectangle containing those coordinates. - * - * @param array array of 2D coordinates - * @return smallest rectangle containing coordinates - */ - public static RectF trapToRect(float[] array) { - RectF r = new RectF(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, - Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY); - for (int i = 1; i < array.length; i += 2) { - float x = array[i - 1]; - float y = array[i]; - r.left = (x < r.left) ? x : r.left; - r.top = (y < r.top) ? y : r.top; - r.right = (x > r.right) ? x : r.right; - r.bottom = (y > r.bottom) ? y : r.bottom; - } - r.sort(); - return r; - } - - /** - * If edge point [x, y] in array [x0, y0, x1, y1, ...] is outside of the - * image bound rectangle, clamps it to the edge of the rectangle. - * - * @param imageBound the rectangle to clamp edge points to. - * @param array an array of points to clamp to the rectangle, gets set to - * the clamped values. - */ - public static void getEdgePoints(RectF imageBound, float[] array) { - if (array.length < 2) - return; - for (int x = 0; x < array.length; x += 2) { - array[x] = GeometryMath.clamp(array[x], imageBound.left, imageBound.right); - array[x + 1] = GeometryMath.clamp(array[x + 1], imageBound.top, imageBound.bottom); - } - } - - /** - * Takes a point and the corners of a rectangle and returns the two corners - * representing the side of the rectangle closest to the point. - * - * @param point the point which is being checked - * @param corners the corners of the rectangle - * @return two corners representing the side of the rectangle - */ - public static float[] closestSide(float[] point, float[] corners) { - int len = corners.length; - float oldMag = Float.POSITIVE_INFINITY; - float[] bestLine = null; - for (int i = 0; i < len; i += 2) { - float[] line = { - corners[i], corners[(i + 1) % len], - corners[(i + 2) % len], corners[(i + 3) % len] - }; - float mag = GeometryMath.vectorLength( - GeometryMath.shortestVectorFromPointToLine(point, line)); - if (mag < oldMag) { - oldMag = mag; - bestLine = line; - } - } - return bestLine; - } - - /** - * Checks if a given point is within a rotated rectangle. - * - * @param point 2D point to check - * @param bound rectangle to rotate - * @param rot angle of rotation about rectangle center - * @return true if point is within rotated rectangle - */ - public static boolean pointInRotatedRect(float[] point, RectF bound, float rot) { - Matrix m = new Matrix(); - float[] p = Arrays.copyOf(point, 2); - m.setRotate(rot, bound.centerX(), bound.centerY()); - Matrix m0 = new Matrix(); - if (!m.invert(m0)) - return false; - m0.mapPoints(p); - return inclusiveContains(bound, p[0], p[1]); - } - - /** - * Checks if a given point is within a rotated rectangle. - * - * @param point 2D point to check - * @param rotatedRect corners of a rotated rectangle - * @param center center of the rotated rectangle - * @return true if point is within rotated rectangle - */ - public static boolean pointInRotatedRect(float[] point, float[] rotatedRect, float[] center) { - RectF unrotated = new RectF(); - float angle = getUnrotated(rotatedRect, center, unrotated); - return pointInRotatedRect(point, unrotated, angle); - } - - /** - * Resizes rectangle to have a certain aspect ratio (center remains - * stationary). - * - * @param r rectangle to resize - * @param w new width aspect - * @param h new height aspect - */ - public static void fixAspectRatio(RectF r, float w, float h) { - float scale = Math.min(r.width() / w, r.height() / h); - float centX = r.centerX(); - float centY = r.centerY(); - float hw = scale * w / 2; - float hh = scale * h / 2; - r.set(centX - hw, centY - hh, centX + hw, centY + hh); - } - - private static float getUnrotated(float[] rotatedRect, float[] center, RectF unrotated) { - float dy = rotatedRect[1] - rotatedRect[3]; - float dx = rotatedRect[0] - rotatedRect[2]; - float angle = (float) (Math.atan(dy / dx) * 180 / Math.PI); - Matrix m = new Matrix(); - m.setRotate(-angle, center[0], center[1]); - float[] unrotatedRect = new float[rotatedRect.length]; - m.mapPoints(unrotatedRect, rotatedRect); - unrotated.set(trapToRect(unrotatedRect)); - return angle; - } - -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java index ad2152ab1..898fdf021 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java +++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java @@ -21,8 +21,8 @@ import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.RectF; -import com.android.gallery3d.filtershow.CropExtras; import com.android.gallery3d.filtershow.cache.ImageLoader; +import com.android.gallery3d.filtershow.crop.CropExtras; import com.android.gallery3d.filtershow.editors.EditorCrop; import com.android.gallery3d.filtershow.editors.EditorFlip; import com.android.gallery3d.filtershow.editors.EditorRotate; diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java index 2ea6f6a42..6d62bbd1d 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java +++ b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java @@ -33,7 +33,9 @@ import android.widget.LinearLayout; import android.widget.PopupMenu; import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.CropExtras; +import com.android.gallery3d.filtershow.crop.BoundedRect; +import com.android.gallery3d.filtershow.crop.CropExtras; +import com.android.gallery3d.filtershow.crop.CropMath; import com.android.gallery3d.filtershow.editors.EditorCrop; import com.android.gallery3d.filtershow.ui.FramedTextButton; |