1dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford/*
2dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford * Copyright (C) 2015 The Android Open Source Project
3dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford *
4dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford * Licensed under the Apache License, Version 2.0 (the "License");
5dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford * you may not use this file except in compliance with the License.
6dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford * You may obtain a copy of the License at
7dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford *
8dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford *      http://www.apache.org/licenses/LICENSE-2.0
9dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford *
10dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford * Unless required by applicable law or agreed to in writing, software
11dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford * distributed under the License is distributed on an "AS IS" BASIS,
12dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford * See the License for the specific language governing permissions and
14dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford * limitations under the License.
15dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford */
16dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
17dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordpackage rs.example.android.com.healingbrush;
18dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
19dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.Bitmap;
20dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.Canvas;
21dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.Color;
22dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.ColorFilter;
23dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.Paint;
24dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.Path;
25dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.PathMeasure;
26dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.PorterDuff;
27dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.PorterDuffXfermode;
28dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.Rect;
29dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.RectF;
30dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.graphics.drawable.Drawable;
31dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.support.v8.renderscript.Allocation;
32dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.support.v8.renderscript.Element;
33dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.support.v8.renderscript.RenderScript;
34dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.support.v8.renderscript.Script;
35dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.support.v8.renderscript.Type;
36dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport android.util.Log;
37dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
38dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport com.example.android.rs.sample.ScriptC_find_region;
39dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordimport com.example.android.rs.sample.ScriptC_healing;
40dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
41dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hofordpublic class Region {
42dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    private static final String TAG = "Region";
43dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    int mCutOffsetX; // image coords of the cut  (mPointsXY - mPasteOffX + mCutOffsetX)
44dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    int mCutOffsetY; // image coords of the cut (mPointsXY - mPasteOffY + mCutOffsetY)
45dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
46dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    int[] mPaste; // contains a copy where to paste
47dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
48dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    float[] mPointsXY; // polygon point in original image coordnates
49dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    int numberOfPoints;
50dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
51dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    FindRegion mFindRegion;
52dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    private Bitmap mUndoBitmap;
53dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
54dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    /**
55dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford     * @param xy  A list of xy points that represents the polygon
56dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford     * @param img The original polygon
57dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford     */
58dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    public Region(float[] xy, Bitmap img) {
59dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        mPointsXY = xy;
60dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        mFindRegion = new FindRegion(mPointsXY, img);
61dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    }
62dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
63dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    Drawable getSourceLocation() {
64dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        final Path path = new Path();
65dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        Rect bounds = mFindRegion.getRoiBounds();
66dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        for (int i = 0; i < mPointsXY.length; i += 2) {
67dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            if (i == 0) {
68dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                path.moveTo(mPointsXY[i] - bounds.left + mCutOffsetX,
69dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                        mPointsXY[i + 1] - bounds.top + mCutOffsetY);
70dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            } else {
71dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                path.lineTo(mPointsXY[i] - bounds.left + mCutOffsetX,
72dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                        mPointsXY[i + 1] - bounds.top + mCutOffsetY);
73dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
74dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        }
75dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        path.close();
76dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        Drawable d = new Drawable() {
77dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            Paint paint1 = new Paint();
78dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            Paint paint2 = new Paint();
79dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
80dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            {
81dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                paint1.setStyle(Paint.Style.STROKE);
82dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                paint2.setStyle(Paint.Style.STROKE);
83dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                paint1.setColor(Color.BLACK);
84dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                paint1.setStrokeWidth(2);
85dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                paint2.setColor(Color.BLUE);
86dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
87dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
88dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            @Override
89dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            public void draw(Canvas canvas) {
90dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                canvas.drawPath(path, paint1);
91dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                canvas.drawPath(path, paint2);
92dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
93dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
94dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            @Override
95dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            public void setAlpha(int alpha) {
96dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
97dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
98dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            @Override
99dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            public void setColorFilter(ColorFilter cf) {
100dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
101dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
102dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            @Override
103dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            public int getOpacity() {
104dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                return 0;
105dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
106dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        };
107dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        return d;
108dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    }
109dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
110dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    public Drawable findMatch(ScriptC_find_region findRegion, RenderScript mRs, Bitmap image) {
111dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        Rect mRoiBounds = mFindRegion.findMatch(findRegion, mRs, image);
112dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        int cutOffsetX = mFindRegion.getCutOffsetX();
113dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        int cutOffsetY = mFindRegion.getCutOffsetY();
114dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        final Path path = new Path();
115dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        for (int i = 0; i < mPointsXY.length; i += 2) {
116dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            if (i == 0) {
117dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                path.moveTo(mPointsXY[i] - mRoiBounds.left + cutOffsetX,
118dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                        mPointsXY[i + 1] - mRoiBounds.top + cutOffsetY);
119dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            } else {
120dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                path.lineTo(mPointsXY[i] - mRoiBounds.left + cutOffsetX,
121dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                        mPointsXY[i + 1] - mRoiBounds.top + cutOffsetY);
122dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
123dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        }
124dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
125dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        path.close();
126dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
127dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
128dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        Drawable d = new Drawable() {
129dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            Paint paint = new Paint();
130dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
131dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            {
132dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                paint.setStyle(Paint.Style.STROKE);
133dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
134dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
135dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            @Override
136dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            public void draw(Canvas canvas) {
137dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                canvas.drawPath(path, paint);
138dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
139dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
140dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            @Override
141dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            public void setAlpha(int alpha) {
142dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
143dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
144dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            @Override
145dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            public void setColorFilter(ColorFilter cf) {
146dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
147dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
148dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            @Override
149dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            public int getOpacity() {
150dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                return 0;
151dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford            }
152dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        };
153dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        return d;
154dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    }
155dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
156dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    Bitmap createMutableBitmap(Bitmap image, int x, int y, int width, int height) {
157dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        Bitmap ret = Bitmap.createBitmap(image, x, y, width, height);
158dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        return ret.copy(Bitmap.Config.ARGB_8888, true);
159dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    }
160dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
161dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    /**
162dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford     * This function only assumes mPointsXY, mPasteOffX, mPasteOffY
163dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford     *
164dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford     * @param healing
165dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford     * @param rs
166dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford     * @param image
167dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford     */
168dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    public void heal(ScriptC_healing healing, RenderScript rs, Bitmap image, Bitmap output) {
169dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        Healing h = new Healing(
170dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                mFindRegion.getRoiBounds(),
171dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                mPointsXY,
172dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                mFindRegion.getCutOffsetX(),
173dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford                mFindRegion.getCutOffsetY());
174dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        h.heal(healing, rs, image, output);
175dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        mUndoBitmap = h.getmUndoBitmap();
176dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    }
177dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford
178dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    public void undo(Bitmap output) {
179dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        Canvas c = new Canvas(output);
180dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        Rect roi;
181dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        roi = mFindRegion.getRoiBounds();
182dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford        c.drawBitmap(mUndoBitmap, roi.left, roi.top, null);
183dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford    }
184dbf58070bd1a228fc817ea5ddb5c08fe717aecd2hoford}
185