119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard/*
219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard * Copyright (C) 2012 The Android Open Source Project
319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard *
419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard * Licensed under the Apache License, Version 2.0 (the "License");
519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard * you may not use this file except in compliance with the License.
619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard * You may obtain a copy of the License at
719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard *
819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard *      http://www.apache.org/licenses/LICENSE-2.0
919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard *
1019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard * Unless required by applicable law or agreed to in writing, software
1119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard * distributed under the License is distributed on an "AS IS" BASIS,
1219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard * See the License for the specific language governing permissions and
1419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard * limitations under the License.
1519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard */
1619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
1719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardpackage com.android.camera.crop;
1819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
1919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport android.graphics.Bitmap;
2019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport android.graphics.Canvas;
2119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport android.graphics.Matrix;
2219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport android.graphics.Paint;
2319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport android.graphics.Rect;
2419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport android.graphics.RectF;
2519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
2619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard/*
2719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport com.android.gallery3d.filtershow.cache.BitmapCache;
2819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport com.android.gallery3d.filtershow.cache.ImageLoader;
2919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport com.android.gallery3d.filtershow.filters.FilterCropRepresentation;
3019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation;
3119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation.Mirror;
3219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport com.android.gallery3d.filtershow.filters.FilterRepresentation;
3319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport com.android.gallery3d.filtershow.filters.FilterRotateRepresentation;
3419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport com.android.gallery3d.filtershow.filters.FilterRotateRepresentation.Rotation;
3519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation;
3619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport com.android.gallery3d.filtershow.pipeline.ImagePreset;
3719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard*/
3819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
3919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport java.util.Collection;
4019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardimport java.util.Iterator;
4119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
4219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroardpublic final class GeometryMathUtils {
4319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    private static final String TAG = "GeometryMathUtils";
4419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static final float SHOW_SCALE = .9f;
4519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
4619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    private GeometryMathUtils() {};
4719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
4819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    // Math operations for 2d vectors
4919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static float clamp(float i, float low, float high) {
5019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return Math.max(Math.min(i, high), low);
5119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
5219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
5319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static float[] lineIntersect(float[] line1, float[] line2) {
5419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float a0 = line1[0];
5519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float a1 = line1[1];
5619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float b0 = line1[2];
5719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float b1 = line1[3];
5819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float c0 = line2[0];
5919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float c1 = line2[1];
6019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float d0 = line2[2];
6119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float d1 = line2[3];
6219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float t0 = a0 - b0;
6319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float t1 = a1 - b1;
6419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float t2 = b0 - d0;
6519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float t3 = d1 - b1;
6619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float t4 = c0 - d0;
6719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float t5 = c1 - d1;
6819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
6919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float denom = t1 * t4 - t0 * t5;
7019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        if (denom == 0)
7119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard            return null;
7219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float u = (t3 * t4 + t5 * t2) / denom;
7319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float[] intersect = {
7419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                b0 + u * t0, b1 + u * t1
7519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        };
7619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return intersect;
7719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
7819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
7919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static float[] shortestVectorFromPointToLine(float[] point, float[] line) {
8019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float x1 = line[0];
8119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float x2 = line[2];
8219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float y1 = line[1];
8319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float y2 = line[3];
8419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float xdelt = x2 - x1;
8519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float ydelt = y2 - y1;
8619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        if (xdelt == 0 && ydelt == 0)
8719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard            return null;
8819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float u = ((point[0] - x1) * xdelt + (point[1] - y1) * ydelt)
8919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                / (xdelt * xdelt + ydelt * ydelt);
9019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float[] ret = {
9119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                (x1 + u * (x2 - x1)), (y1 + u * (y2 - y1))
9219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        };
9319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float[] vec = {
9419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                ret[0] - point[0], ret[1] - point[1]
9519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        };
9619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return vec;
9719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
9819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
9919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    // A . B
10019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static float dotProduct(float[] a, float[] b) {
10119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return a[0] * b[0] + a[1] * b[1];
10219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
10319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
10419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static float[] normalize(float[] a) {
10519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float length = (float) Math.sqrt(a[0] * a[0] + a[1] * a[1]);
10619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float[] b = {
10719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                a[0] / length, a[1] / length
10819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        };
10919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return b;
11019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
11119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
11219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    // A onto B
11319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static float scalarProjection(float[] a, float[] b) {
11419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float length = (float) Math.sqrt(b[0] * b[0] + b[1] * b[1]);
11519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return dotProduct(a, b) / length;
11619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
11719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
11819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static float[] getVectorFromPoints(float[] point1, float[] point2) {
11919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float[] p = {
12019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                point2[0] - point1[0], point2[1] - point1[1]
12119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        };
12219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return p;
12319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
12419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
12519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static float[] getUnitVectorFromPoints(float[] point1, float[] point2) {
12619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float[] p = {
12719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                point2[0] - point1[0], point2[1] - point1[1]
12819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        };
12919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float length = (float) Math.sqrt(p[0] * p[0] + p[1] * p[1]);
13019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        p[0] = p[0] / length;
13119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        p[1] = p[1] / length;
13219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return p;
13319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
13419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
13519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static void scaleRect(RectF r, float scale) {
13619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        r.set(r.left * scale, r.top * scale, r.right * scale, r.bottom * scale);
13719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
13819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
13919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    // A - B
14019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static float[] vectorSubtract(float[] a, float[] b) {
14119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        int len = a.length;
14219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        if (len != b.length)
14319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard            return null;
14419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        float[] ret = new float[len];
14519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        for (int i = 0; i < len; i++) {
14619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard            ret[i] = a[i] - b[i];
14719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        }
14819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return ret;
14919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
15019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
15119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static float vectorLength(float[] a) {
15219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return (float) Math.sqrt(a[0] * a[0] + a[1] * a[1]);
15319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
15419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
15519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static float scale(float oldWidth, float oldHeight, float newWidth, float newHeight) {
15619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        if (oldHeight == 0 || oldWidth == 0 || (oldWidth == newWidth && oldHeight == newHeight)) {
15719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard            return 1;
15819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        }
15919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return Math.min(newWidth / oldWidth, newHeight / oldHeight);
16019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
16119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
16219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    public static Rect roundNearest(RectF r) {
16319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        Rect q = new Rect(Math.round(r.left), Math.round(r.top), Math.round(r.right),
16419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                Math.round(r.bottom));
16519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        return q;
16619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
16719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
16819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    private static int getRotationForOrientation(int orientation) {
16919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        switch (orientation) {
17019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard            case ImageLoader.ORI_ROTATE_90:
17119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                return 90;
17219ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard            case ImageLoader.ORI_ROTATE_180:
17319ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                return 180;
17419ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard            case ImageLoader.ORI_ROTATE_270:
17519ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                return 270;
17619ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard            default:
17719ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard                return 0;
17819ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard        }
17919ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard    }
18019ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard
18119ab725a5e640a1a20b1a6def083e37d1d1c1e20nicolasroard}
182