1b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk/* 2b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * Copyright (C) 2012 The Android Open Source Project 3b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * 4b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 5b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * you may not use this file except in compliance with the License. 6b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * You may obtain a copy of the License at 7b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * 8b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * http://www.apache.org/licenses/LICENSE-2.0 9b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * 10b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * Unless required by applicable law or agreed to in writing, software 11b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 12b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * See the License for the specific language governing permissions and 14b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk * limitations under the License. 15b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk */ 16b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 17b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkpackage com.android.gallery3d.filtershow.imageshow; 18b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 19b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport android.graphics.Bitmap; 20b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport android.graphics.Canvas; 21b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport android.graphics.Matrix; 22b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport android.graphics.Paint; 23b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport android.graphics.Rect; 24b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport android.graphics.RectF; 25ec1f915006e5ec2db8be633b5d3d73e568951da4John Hofordimport android.util.Log; 26b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 279f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroardimport com.android.gallery3d.filtershow.cache.BitmapCache; 28b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport com.android.gallery3d.filtershow.cache.ImageLoader; 29b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport com.android.gallery3d.filtershow.filters.FilterCropRepresentation; 30b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation; 31b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation.Mirror; 32b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport com.android.gallery3d.filtershow.filters.FilterRepresentation; 33b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport com.android.gallery3d.filtershow.filters.FilterRotateRepresentation; 34b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport com.android.gallery3d.filtershow.filters.FilterRotateRepresentation.Rotation; 35b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation; 36b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport com.android.gallery3d.filtershow.pipeline.ImagePreset; 37b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 38b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport java.util.Collection; 39b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport java.util.Iterator; 40b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 41b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkpublic final class GeometryMathUtils { 42ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford private static final String TAG = "GeometryMathUtils"; 43ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford public static final float SHOW_SCALE = .9f; 44ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford 45b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk private GeometryMathUtils() {}; 46b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 47b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk // Holder class for Geometry data. 48b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static final class GeometryHolder { 49b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public Rotation rotation = FilterRotateRepresentation.getNil(); 50b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public float straighten = FilterStraightenRepresentation.getNil(); 51b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public RectF crop = FilterCropRepresentation.getNil(); 52b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public Mirror mirror = FilterMirrorRepresentation.getNil(); 53b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 54b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public void set(GeometryHolder h) { 55b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk rotation = h.rotation; 56b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk straighten = h.straighten; 57b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk crop.set(h.crop); 58b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk mirror = h.mirror; 59b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 60b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 61b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public void wipe() { 62b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk rotation = FilterRotateRepresentation.getNil(); 63b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk straighten = FilterStraightenRepresentation.getNil(); 64b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk crop = FilterCropRepresentation.getNil(); 65b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk mirror = FilterMirrorRepresentation.getNil(); 66b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 67b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 68b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public boolean isNil() { 69b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return rotation == FilterRotateRepresentation.getNil() && 70b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk straighten == FilterStraightenRepresentation.getNil() && 71b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk crop.equals(FilterCropRepresentation.getNil()) && 72b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk mirror == FilterMirrorRepresentation.getNil(); 73b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 74b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 75b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk @Override 76b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public boolean equals(Object o) { 77b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (this == o) { 78b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return true; 79b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 80b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (!(o instanceof GeometryHolder)) { 81b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return false; 82b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 83b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk GeometryHolder h = (GeometryHolder) o; 84b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return rotation == h.rotation && straighten == h.straighten && 85b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk ((crop == null && h.crop == null) || (crop != null && crop.equals(h.crop))) && 86b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk mirror == h.mirror; 87b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 88b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 89b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk @Override 90b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public String toString() { 91b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return getClass().getSimpleName() + "[" + "rotation:" + rotation.value() 92b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk + ",straighten:" + straighten + ",crop:" + crop.toString() 93b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk + ",mirror:" + mirror.value() + "]"; 94b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 95b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 96b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 97b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk // Math operations for 2d vectors 98b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static float clamp(float i, float low, float high) { 99b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return Math.max(Math.min(i, high), low); 100b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 101b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 102b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static float[] lineIntersect(float[] line1, float[] line2) { 103b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float a0 = line1[0]; 104b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float a1 = line1[1]; 105b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float b0 = line1[2]; 106b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float b1 = line1[3]; 107b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float c0 = line2[0]; 108b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float c1 = line2[1]; 109b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float d0 = line2[2]; 110b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float d1 = line2[3]; 111b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float t0 = a0 - b0; 112b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float t1 = a1 - b1; 113b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float t2 = b0 - d0; 114b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float t3 = d1 - b1; 115b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float t4 = c0 - d0; 116b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float t5 = c1 - d1; 117b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 118b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float denom = t1 * t4 - t0 * t5; 119b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (denom == 0) 120b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return null; 121b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float u = (t3 * t4 + t5 * t2) / denom; 122b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float[] intersect = { 123b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk b0 + u * t0, b1 + u * t1 124b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk }; 125b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return intersect; 126b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 127b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 128b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static float[] shortestVectorFromPointToLine(float[] point, float[] line) { 129b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float x1 = line[0]; 130b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float x2 = line[2]; 131b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float y1 = line[1]; 132b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float y2 = line[3]; 133b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float xdelt = x2 - x1; 134b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float ydelt = y2 - y1; 135b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (xdelt == 0 && ydelt == 0) 136b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return null; 137b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float u = ((point[0] - x1) * xdelt + (point[1] - y1) * ydelt) 138b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk / (xdelt * xdelt + ydelt * ydelt); 139b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float[] ret = { 140b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk (x1 + u * (x2 - x1)), (y1 + u * (y2 - y1)) 141b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk }; 142b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float[] vec = { 143b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk ret[0] - point[0], ret[1] - point[1] 144b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk }; 145b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return vec; 146b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 147b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 148b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk // A . B 149b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static float dotProduct(float[] a, float[] b) { 150b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return a[0] * b[0] + a[1] * b[1]; 151b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 152b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 153b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static float[] normalize(float[] a) { 1548a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller float length = (float) Math.hypot(a[0], a[1]); 155b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float[] b = { 156b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk a[0] / length, a[1] / length 157b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk }; 158b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return b; 159b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 160b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 161b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk // A onto B 162b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static float scalarProjection(float[] a, float[] b) { 1638a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller float length = (float) Math.hypot(b[0], b[1]); 164b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return dotProduct(a, b) / length; 165b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 166b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 167b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static float[] getVectorFromPoints(float[] point1, float[] point2) { 168b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float[] p = { 169b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk point2[0] - point1[0], point2[1] - point1[1] 170b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk }; 171b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return p; 172b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 173b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 174b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static float[] getUnitVectorFromPoints(float[] point1, float[] point2) { 175b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float[] p = { 176b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk point2[0] - point1[0], point2[1] - point1[1] 177b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk }; 1788a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller float length = (float) Math.hypot(p[0], p[1]); 179b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk p[0] = p[0] / length; 180b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk p[1] = p[1] / length; 181b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return p; 182b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 183b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 184b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static void scaleRect(RectF r, float scale) { 185b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk r.set(r.left * scale, r.top * scale, r.right * scale, r.bottom * scale); 186b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 187b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 188b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk // A - B 189b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static float[] vectorSubtract(float[] a, float[] b) { 190b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk int len = a.length; 191b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (len != b.length) 192b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return null; 193b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float[] ret = new float[len]; 194b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk for (int i = 0; i < len; i++) { 195b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk ret[i] = a[i] - b[i]; 196b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 197b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return ret; 198b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 199b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 200b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static float vectorLength(float[] a) { 2018a55d3ae7486b798e4c26eeb91993916145f3cefNeil Fuller return (float) Math.hypot(a[0], a[1]); 202b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 203b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 204b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static float scale(float oldWidth, float oldHeight, float newWidth, float newHeight) { 205b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (oldHeight == 0 || oldWidth == 0 || (oldWidth == newWidth && oldHeight == newHeight)) { 206b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return 1; 207b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 208b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return Math.min(newWidth / oldWidth, newHeight / oldHeight); 209b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 210b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 211b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static Rect roundNearest(RectF r) { 212b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Rect q = new Rect(Math.round(r.left), Math.round(r.top), Math.round(r.right), 213b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Math.round(r.bottom)); 214b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return q; 215b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 216b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 2179f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard private static void concatMirrorMatrix(Matrix m, GeometryHolder holder) { 2189f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard Mirror type = holder.mirror; 2199f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard if (type == Mirror.HORIZONTAL) { 2209f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard if (holder.rotation.value() == 90 2219f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard || holder.rotation.value() == 270) { 2229f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard type = Mirror.VERTICAL; 2239f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard } 2249f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard } else if (type == Mirror.VERTICAL) { 2259f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard if (holder.rotation.value() == 90 2269f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard || holder.rotation.value() == 270) { 2279f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard type = Mirror.HORIZONTAL; 2289f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard } 2299f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard } 230b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (type == Mirror.HORIZONTAL) { 231b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk m.postScale(-1, 1); 232b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } else if (type == Mirror.VERTICAL) { 233b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk m.postScale(1, -1); 234b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } else if (type == Mirror.BOTH) { 235b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk m.postScale(1, -1); 236b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk m.postScale(-1, 1); 237b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 238b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 239b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 240b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk private static int getRotationForOrientation(int orientation) { 241b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk switch (orientation) { 242b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk case ImageLoader.ORI_ROTATE_90: 243b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return 90; 244b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk case ImageLoader.ORI_ROTATE_180: 245b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return 180; 246b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk case ImageLoader.ORI_ROTATE_270: 247b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return 270; 248b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk default: 249b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return 0; 250b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 251b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 252b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 253b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static GeometryHolder unpackGeometry(Collection<FilterRepresentation> geometry) { 254b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk GeometryHolder holder = new GeometryHolder(); 255b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk unpackGeometry(holder, geometry); 256b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return holder; 257b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 258b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 259b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static void unpackGeometry(GeometryHolder out, 260b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Collection<FilterRepresentation> geometry) { 261b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk out.wipe(); 262b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk // Get geometry data from filters 263b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk for (FilterRepresentation r : geometry) { 264b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (r.isNil()) { 265b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk continue; 266b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 267b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (r.getSerializationName() == FilterRotateRepresentation.SERIALIZATION_NAME) { 268b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk out.rotation = ((FilterRotateRepresentation) r).getRotation(); 269b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } else if (r.getSerializationName() == 270b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk FilterStraightenRepresentation.SERIALIZATION_NAME) { 271b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk out.straighten = ((FilterStraightenRepresentation) r).getStraighten(); 272b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } else if (r.getSerializationName() == FilterCropRepresentation.SERIALIZATION_NAME) { 273b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk ((FilterCropRepresentation) r).getCrop(out.crop); 274b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } else if (r.getSerializationName() == FilterMirrorRepresentation.SERIALIZATION_NAME) { 275b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk out.mirror = ((FilterMirrorRepresentation) r).getMirror(); 276b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 277b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 278b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 279b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 280b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static void replaceInstances(Collection<FilterRepresentation> geometry, 281b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk FilterRepresentation rep) { 282b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Iterator<FilterRepresentation> iter = geometry.iterator(); 283b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk while (iter.hasNext()) { 284b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk FilterRepresentation r = iter.next(); 285b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (ImagePreset.sameSerializationName(rep, r)) { 286b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk iter.remove(); 287b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 288b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 289b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (!rep.isNil()) { 290b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk geometry.add(rep); 291b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 292b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 293b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 294b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static void initializeHolder(GeometryHolder outHolder, 295b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk FilterRepresentation currentLocal) { 296b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Collection<FilterRepresentation> geometry = MasterImage.getImage().getPreset() 297b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk .getGeometryFilters(); 298b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk replaceInstances(geometry, currentLocal); 299b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk unpackGeometry(outHolder, geometry); 300b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 301b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 30255d6abe58c3a7574a5d76c68ec5c21848848e399nicolasroard public static Rect finalGeometryRect(int width, int height, 30355d6abe58c3a7574a5d76c68ec5c21848848e399nicolasroard Collection<FilterRepresentation> geometry) { 30455d6abe58c3a7574a5d76c68ec5c21848848e399nicolasroard GeometryHolder holder = unpackGeometry(geometry); 30555d6abe58c3a7574a5d76c68ec5c21848848e399nicolasroard RectF crop = getTrueCropRect(holder, width, height); 30655d6abe58c3a7574a5d76c68ec5c21848848e399nicolasroard Rect frame = new Rect(); 30755d6abe58c3a7574a5d76c68ec5c21848848e399nicolasroard crop.roundOut(frame); 30855d6abe58c3a7574a5d76c68ec5c21848848e399nicolasroard return frame; 30955d6abe58c3a7574a5d76c68ec5c21848848e399nicolasroard } 31055d6abe58c3a7574a5d76c68ec5c21848848e399nicolasroard 311b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk private static Bitmap applyFullGeometryMatrix(Bitmap image, GeometryHolder holder) { 312b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk int width = image.getWidth(); 313b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk int height = image.getHeight(); 314b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk RectF crop = getTrueCropRect(holder, width, height); 315b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Rect frame = new Rect(); 316b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk crop.roundOut(frame); 317b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Matrix m = getCropSelectionToScreenMatrix(null, holder, width, height, frame.width(), 318b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk frame.height()); 3199f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard BitmapCache bitmapCache = MasterImage.getImage().getBitmapCache(); 320ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard Bitmap temp = bitmapCache.getBitmap(frame.width(), 321ec1e009a7faea0478e361bc2d48d856ab48a0209nicolasroard frame.height(), BitmapCache.UTIL_GEOMETRY); 322b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Canvas canvas = new Canvas(temp); 323b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Paint paint = new Paint(); 324b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk paint.setAntiAlias(true); 325b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk paint.setFilterBitmap(true); 326b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk paint.setDither(true); 327b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk canvas.drawBitmap(image, m, paint); 328b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return temp; 329b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 330b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 331b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static Matrix getImageToScreenMatrix(Collection<FilterRepresentation> geometry, 332b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk boolean reflectRotation, Rect bmapDimens, float viewWidth, float viewHeight) { 333b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk GeometryHolder h = unpackGeometry(geometry); 334b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return GeometryMathUtils.getOriginalToScreen(h, reflectRotation, bmapDimens.width(), 335b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk bmapDimens.height(), viewWidth, viewHeight); 336b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 337b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 338430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard public static Matrix getPartialToScreenMatrix(Collection<FilterRepresentation> geometry, 339430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard Rect originalBounds, float w, float h, 340430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard float pw, float ph) { 341430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard GeometryHolder holder = unpackGeometry(geometry); 342430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard RectF rCrop = new RectF(0, 0, originalBounds.width(), originalBounds.height()); 343430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard float angle = holder.straighten; 344430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard int rotation = holder.rotation.value(); 345430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard 346430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard ImageStraighten.getUntranslatedStraightenCropBounds(rCrop, angle); 347430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard float dx = (w - pw) / 2f; 348430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard float dy = (h - ph) / 2f; 349430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard Matrix compensation = new Matrix(); 350430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard compensation.postTranslate(dx, dy); 351430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard float cScale = originalBounds.width() / rCrop.width(); 352430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard if (rCrop.width() < rCrop.height()) { 353430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard cScale = originalBounds.height() / rCrop.height(); 354430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard } 355430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard float scale = w / pw; 356430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard if (w < h) { 357430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard scale = h / ph; 358430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard } 359430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard scale = scale * cScale; 360430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard float cx = w / 2f; 361430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard float cy = h / 2f; 362430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard 363430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard compensation.postScale(scale, scale, cx, cy); 364430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard compensation.postRotate(angle, cx, cy); 365430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard compensation.postRotate(rotation, cx, cy); 366430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard compensation.postTranslate(-cx, -cy); 3679f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard concatMirrorMatrix(compensation, holder); 368430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard compensation.postTranslate(cx, cy); 369430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard return compensation; 370430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard } 371430e46b06f8e7ee1ca3e7ecdcef3e0a978637c03nicolasroard 372b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static Matrix getOriginalToScreen(GeometryHolder holder, boolean rotate, 373b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float originalWidth, 374b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float originalHeight, float viewWidth, float viewHeight) { 375b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk int orientation = MasterImage.getImage().getZoomOrientation(); 376b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk int rotation = getRotationForOrientation(orientation); 377b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Rotation prev = holder.rotation; 378b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk rotation = (rotation + prev.value()) % 360; 379b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk holder.rotation = Rotation.fromValue(rotation); 380b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Matrix m = getCropSelectionToScreenMatrix(null, holder, (int) originalWidth, 381b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk (int) originalHeight, (int) viewWidth, (int) viewHeight); 382b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk holder.rotation = prev; 383b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return m; 384b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 385b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 386b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static Bitmap applyGeometryRepresentations(Collection<FilterRepresentation> res, 387b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Bitmap image) { 388b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk GeometryHolder holder = unpackGeometry(res); 389b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Bitmap bmap = image; 390b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk // If there are geometry changes, apply them to the image 391b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (!holder.isNil()) { 392b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk bmap = applyFullGeometryMatrix(bmap, holder); 3939f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard if (bmap != image) { 3949f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard BitmapCache cache = MasterImage.getImage().getBitmapCache(); 3959f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard cache.cache(image); 3969f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard } 397b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 398b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return bmap; 399b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 400b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 401b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static RectF drawTransformedCropped(GeometryHolder holder, Canvas canvas, 402b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Bitmap photo, int viewWidth, int viewHeight) { 403b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (photo == null) { 404b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return null; 405b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 406b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk RectF crop = new RectF(); 407b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Matrix m = getCropSelectionToScreenMatrix(crop, holder, photo.getWidth(), photo.getHeight(), 408b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk viewWidth, viewHeight); 409b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk canvas.save(); 410b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk canvas.clipRect(crop); 411b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Paint p = new Paint(); 412b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk p.setAntiAlias(true); 413b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk canvas.drawBitmap(photo, m, p); 414b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk canvas.restore(); 415b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return crop; 416b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 417b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 418b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static boolean needsDimensionSwap(Rotation rotation) { 419b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk switch (rotation) { 420b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk case NINETY: 421b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk case TWO_SEVENTY: 422b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return true; 423b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk default: 424b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return false; 425b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 426b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 427b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 428b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk // Gives matrix for rotated, straightened, mirrored bitmap centered at 0,0. 429b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk private static Matrix getFullGeometryMatrix(GeometryHolder holder, int bitmapWidth, 430b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk int bitmapHeight) { 431b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float centerX = bitmapWidth / 2f; 432b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float centerY = bitmapHeight / 2f; 433b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Matrix m = new Matrix(); 434b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk m.setTranslate(-centerX, -centerY); 435b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk m.postRotate(holder.straighten + holder.rotation.value()); 4369f452e09889199a28a86d9bd8f8fdaa8508ca0c1nicolasroard concatMirrorMatrix(m, holder); 437b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return m; 438b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 439b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 440b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static Matrix getFullGeometryToScreenMatrix(GeometryHolder holder, int bitmapWidth, 441b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk int bitmapHeight, int viewWidth, int viewHeight) { 442ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford int bh = bitmapHeight; 443ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford int bw = bitmapWidth; 444ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford if (GeometryMathUtils.needsDimensionSwap(holder.rotation)) { 445ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford bh = bitmapWidth; 446ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford bw = bitmapHeight; 447ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford } 448ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford float scale = GeometryMathUtils.scale(bw, bh, viewWidth, viewHeight); 449ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford scale *= SHOW_SCALE; 450ec1f915006e5ec2db8be633b5d3d73e568951da4John Hoford float s = Math.min(viewWidth / (float) bitmapWidth, viewHeight / (float) bitmapHeight); 451b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Matrix m = getFullGeometryMatrix(holder, bitmapWidth, bitmapHeight); 452b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk m.postScale(scale, scale); 453b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk m.postTranslate(viewWidth / 2f, viewHeight / 2f); 454b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return m; 455b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 456b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 457b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static RectF getTrueCropRect(GeometryHolder holder, int bitmapWidth, int bitmapHeight) { 458b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk RectF r = new RectF(holder.crop); 459b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk FilterCropRepresentation.findScaledCrop(r, bitmapWidth, bitmapHeight); 460b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float s = holder.straighten; 461b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk holder.straighten = 0; 462b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Matrix m1 = getFullGeometryMatrix(holder, bitmapWidth, bitmapHeight); 463b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk holder.straighten = s; 464b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk m1.mapRect(r); 465b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return r; 466b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 467b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 468b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static Matrix getCropSelectionToScreenMatrix(RectF outCrop, GeometryHolder holder, 469b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk int bitmapWidth, int bitmapHeight, int viewWidth, int viewHeight) { 470b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Matrix m = getFullGeometryMatrix(holder, bitmapWidth, bitmapHeight); 471b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk RectF crop = getTrueCropRect(holder, bitmapWidth, bitmapHeight); 472b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float scale = GeometryMathUtils.scale(crop.width(), crop.height(), viewWidth, viewHeight); 473b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk m.postScale(scale, scale); 474b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk GeometryMathUtils.scaleRect(crop, scale); 475b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk m.postTranslate(viewWidth / 2f - crop.centerX(), viewHeight / 2f - crop.centerY()); 476b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk if (outCrop != null) { 477b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk crop.offset(viewWidth / 2f - crop.centerX(), viewHeight / 2f - crop.centerY()); 478b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk outCrop.set(crop); 479b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 480b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return m; 481b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 482b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk 483b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk public static Matrix getCropSelectionToScreenMatrix(RectF outCrop, 484b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk Collection<FilterRepresentation> res, int bitmapWidth, int bitmapHeight, int viewWidth, 485b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk int viewHeight) { 486b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk GeometryHolder holder = unpackGeometry(res); 487b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk return getCropSelectionToScreenMatrix(outCrop, holder, bitmapWidth, bitmapHeight, 488b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk viewWidth, viewHeight); 489b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk } 490b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk} 491