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
17#pragma version(1)
18#pragma rs java_package_name(com.example.android.rs.sample)
19#pragma rs_fp_relaxed
20
21rs_allocation image;
22rs_allocation border_values; // float3
23rs_allocation border_coords; //int2
24
25int borderLength;
26/**
27  This describes the algorithm that uses the code
28  This takes a float2 polygon and an image and searches a best fit polygon in the image
29
30  int2  __attribute__((invoke_cpu)) findBestFit(rs_allocation poly, rs_allocation image) {
31    int search_range_width;
32    int search_range_height;
33    borderLength = rsAllocationGetDimX(poly);
34    int width = rsAllocationGetDimX(image);
35    int height = rsAllocationGetDimY(image);
36
37    border_coords = alloc_int2(borderLength, 0, 0);
38    foreach(toInt, poly , border_coords);
39    border_values = alloc_float3(borderLength, 0, 0);
40    forEach_extractBorder(border_coords , border_values);
41
42    fit = alloc_float(search_range_width, search_range_width, 0);
43    borderLength = size;
44
45    forEach_bordercorrelation(image);
46    int2 fit_pos = gfindMin(fit, cx, cy, cwidth, cheight);
47    return fit_pos;
48 }
49
50void findRegion(rs_allocation coord, rs_allocation image) {
51  borderLength = rsAllocationGetDimX(coord);
52  int width = rsAllocationGetDimX(image);
53  int height = rsAllocationGetDimY(image);
54}
55
56static int4 padRegionRect(float4 rec) {
57  int width = rec.z;
58  int height = rec.w;
59  int  mWidth = (((int) (8 + width)) & ~3); // bounding rectangle that is a power of 8 big
60  int  mHeight = (((int) (8 + height)) & ~3);
61  int4 out = {(int)(rec.x - 1 ),(int)(rec.y - 1), width, height};
62  return out;
63}
64
65
66*/
67
68
69static float4 gcalcBounds(rs_allocation xy) {
70  int len = rsAllocationGetDimX(xy);
71  float2 min_xy = rsGetElementAt_float(xy, 0);
72  float2 max_xy = min_xy;
73  for (int i = 0; i < len; i += 2) {
74    float2 v = rsGetElementAt_float2(xy, i);
75    min_xy = min(min_xy, v);
76    max_xy = max(max_xy, v);
77  }
78  max_xy-=min_xy;
79  float4 out = {min_xy.x, min_xy.y, max_xy.x, max_xy.y};
80  return out;
81}
82
83void calcBounds(rs_allocation xy, rs_allocation rect) {
84  float4 r = gcalcBounds(xy);
85  rsSetElementAt_float2(rect, r.xy, 0);
86  rsSetElementAt_float2(rect, r.zw, 1);
87}
88
89
90float3 __attribute__((kernel))extractBorder(uint2 in) {
91   return convert_float3(rsGetElementAt_uchar4(image, in.x, in.y).xyz);
92}
93
94uint2 __attribute__((kernel)) toInt(float2 in) {
95  uint2 out = {(int)in.x, (int) in.y};
96  return out;
97}
98
99
100static int2 gfindMin(rs_allocation fit, int cx, int cy, int cwidth, int cheight) {
101  int w = rsAllocationGetDimX(fit);
102  int h = rsAllocationGetDimY(fit);
103  float minFit = rsGetElementAt_float(fit, 0, 0);
104  int2 fit_pos = {0, 0};
105  int reg_minx = cx;
106  int reg_miny = cy;
107  int mWidth =  cwidth;
108  int mHeight =  cheight;
109  int reg_width = mWidth;
110  int reg_height = mHeight;
111  int reg_maxx = reg_minx + mWidth;
112  int reg_maxy = reg_miny + mHeight;
113  for (int y = 0; y < h - mHeight; y++) {
114
115    for (int x = 0; x < w - mWidth; x++) {
116      if (!(x > reg_maxx || x + reg_width < reg_minx || y > reg_maxy
117          || y + reg_height < reg_miny)) {
118        continue;
119      }
120      float v = rsGetElementAt_float(fit, x, y);
121      if (v < minFit) {
122        minFit = v;
123        fit_pos.x = x;
124        fit_pos.y = y;
125      }
126    }
127  }
128
129  return fit_pos;
130}
131
132void findMin(rs_allocation fit, rs_allocation fit_max,int cx, int cy, int cwidth, int cheight) {
133  int2 fit_pos = gfindMin(fit, cx, cy, cwidth, cheight);
134  rsSetElementAt_int2(fit_max, fit_pos, 0);
135}
136
137int imagePosX;
138int imagePosY;
139
140float __attribute__((kernel)) bordercorrelation(uint32_t x, uint32_t y) {
141  float sum = 0;
142  int dx = x-imagePosX;
143  int dy = y-imagePosY;
144  for(int i = 0 ; i < borderLength; i++) {
145    int2  coord = rsGetElementAt_int2(border_coords, i);
146    float3 orig = convert_float3(rsGetElementAt_uchar4(image, coord.x + dx, coord.y + dy).xyz);
147    float3 candidate = rsGetElementAt_float3(border_values, i).xyz;
148    sum += distance(orig, candidate);
149  }
150  return sum;
151}
152
153