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