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