1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package rs.example.android.com.healingbrush;
18
19import android.graphics.Bitmap;
20import android.graphics.Rect;
21import android.graphics.RectF;
22import android.renderscript.Allocation;
23import android.renderscript.Element;
24import android.renderscript.RenderScript;
25import android.renderscript.Type;
26import android.util.Log;
27
28import com.example.android.rs.sample.ScriptC_find_region;
29
30public class FindRegion {
31    private static final String TAG = "FindRegion";
32
33    Rect mRoiBounds; // bounding box of the ROI
34    float[] mPointsXY; // polygon point in original image coordnates
35
36    int mCutOffsetX; // image coords of the cut  (mPointsXY - mPasteOffX + mCutOffsetX)
37    int mCutOffsetY; // image coords of the cut (mPointsXY - mPasteOffY + mCutOffsetY)
38
39    public FindRegion(float[] xy, Bitmap img) {
40        mPointsXY = xy;
41        int imgWidth = img.getWidth();
42        int imgHeight = img.getHeight();
43        mRoiBounds = getBoundingRect(xy);
44
45        if (mRoiBounds.height() <= 2 ||
46                mRoiBounds.left < 0
47                || mRoiBounds.top < 0
48                || mRoiBounds.right >= imgWidth
49                || mRoiBounds.bottom >= imgHeight) {
50            throw new RuntimeException("ROI to close to the edge of the image");
51        }
52
53     }
54
55    public int getCutOffsetX() {
56        return mCutOffsetX;
57    }
58
59    public int getCutOffsetY() {
60        return mCutOffsetY;
61    }
62
63    public Rect getRoiBounds() {
64        return mRoiBounds;
65    }
66
67    Allocation allocFloat2(float[] p, RenderScript rs) {
68        Type.Builder builderF32_2 = new Type.Builder(rs, Element.F32_2(rs));
69        builderF32_2.setX(p.length / 2);
70        Allocation ret = Allocation.createTyped(rs, builderF32_2.create());
71        ret.copyFrom(p);
72        return ret;
73    }
74
75    public Rect findMatch(ScriptC_find_region findRegion, RenderScript mRs, Bitmap image) {
76        long time = System.nanoTime();
77
78        Allocation border_coords;
79
80        border_coords = allocFloat2(mPointsXY, mRs);
81        Allocation aImage = Allocation.createFromBitmap(mRs, image);
82        Allocation ret = Allocation.createSized(mRs, Element.I32_2(mRs), 1);
83
84        findRegion.invoke_findRegion(border_coords, aImage, image.getWidth(), image.getHeight(), ret);
85
86        int[] mina = new int[2];
87        ret.copyTo(mina);
88        mCutOffsetX = mina[0];
89        mCutOffsetY = mina[1];
90        Log.v(TAG, "New best location = " + mCutOffsetX + ", " + mCutOffsetY);
91        Log.v(TAG, "Time to find replacement= " + (System.nanoTime() - time) / 1E6f + "ms");
92
93        return mRoiBounds;
94    }
95
96    /**
97     * Computes the bounding box of the polygon
98     * then pads and sizes to multiple of 8
99     *
100     * @param xy points of polygon [x1,y1,x2,y2,...]
101     * @return rectangle
102     */
103    private static Rect getBoundingRect(float[] xy) {
104        RectF mRect = calcBounds(xy);
105        int mWidth = (((int) (8 + mRect.width())) & ~3); // bounding rectangle that is a power of 8
106        int mHeight = (((int) (8 + mRect.height())) & ~3);
107        int mPasteOffX = (int) mRect.left - 1;
108        int mPasteOffY = (int) mRect.top - 1;
109        return new Rect(mPasteOffX, mPasteOffY, mPasteOffX + mWidth, mPasteOffY + mHeight);
110    }
111
112    private static RectF calcBounds(float[] xy) {
113        float minx = xy[0], miny = xy[1];
114        float maxx = xy[0], maxy = xy[1];
115        for (int i = 0; i < xy.length; i += 2) {
116            minx = Math.min(minx, xy[i]);
117            maxx = Math.max(maxx, xy[i]);
118            miny = Math.min(miny, xy[i + 1]);
119            maxy = Math.max(maxy, xy[i + 1]);
120        }
121        RectF rect = new RectF();
122        rect.set(minx, miny, maxx, maxy);
123        return rect;
124    }
125
126
127
128}
129