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
21/**
22  This describes the algorithm that uses the code
23  This takes polygon and image to copy from(src_image) and and image to paste to(dest_image)
24
25  void __attribute__((invoke_cpu)) findBestFit(rs_allocation poly,
26                    rs_allocation src_image,
27                    rs_allocation dest_image) {
28    int width = rsAllocationGetDimX(src_image);
29    int height = rsAllocationGetDimY(src_image);
30    mask  = alloc_uchar(width, height, 0);
31    src   = alloc_float3(width height, 0);
32    dest1 = alloc_float3(width height, 0);
33    dest2 = alloc_float3(width height, 0);
34    mask = alloc_uchar(width, height, 0);
35    foreach_convert_to_f(src_image, src);
36    laplace = alloc_float3(width, height, 0);
37    LaunchOptions options;
38    options.setX(1, width-1);
39    options.setY(1, height-1);
40    forEach_laplacian(laplace, options);
41    forEach_copyMasked(mask, dest1);
42    int steps = (int) sqrt(calcMaskArea());
43    for (int i = 0; i < steps; i++) {
44            forEach_solve1(mask, dest2);
45            forEach_solve2(mask, dest1);
46    }
47    forEach_convert_to_uc(dest1, dest_image);
48    forEach_alphaMask(dest_image, dest_image);
49  }
50
51
52   int calcMaskArea(Allocation mask) {
53      int width = rsAllocationGetDimX(mask);
54      int height = rsAllocationGetDimY(mask);
55      int count = 0;
56      int val = rsGetElementAt_uchar(mask,0,0);
57      for (int y = 0; y < height; y++) {
58        for (int x = 0; x < width; x++) {
59          if (val != rsGetElementAt_uchar(mask, x, y) ) {
60              count++;
61          }
62        }
63      }
64     return count;
65   }
66
67*/
68
69typedef rs_allocation AllocationF32_3;
70
71AllocationF32_3 src;
72
73float3 __attribute__((kernel)) laplacian( uint32_t x, uint32_t y) {
74  float3 out = 4 * rsGetElementAt_float3(src, x, y);
75  out -= rsGetElementAt_float3(src, x - 1, y);
76  out -= rsGetElementAt_float3(src, x + 1, y);
77  out -= rsGetElementAt_float3(src, x, y -1 );
78  out -= rsGetElementAt_float3(src, x, y + 1);
79  return out;
80}
81
82rs_allocation mask;       // uchar
83AllocationF32_3 laplace;  // float3
84AllocationF32_3 dest1;    // float3
85AllocationF32_3 dest2;    // float3
86
87float3 __attribute__((kernel)) convert_to_f(uchar4 in) {
88  return convert_float3(in.xyz);
89}
90
91float3 __attribute__((kernel)) copyMasked(uchar in, uint32_t x, uint32_t y) {
92  return  rsGetElementAt_float3((in>0) ? src : dest1, x, y);
93}
94
95uchar4 __attribute__((kernel)) convert_to_uc(float3 in) {
96  in = clamp(in, 0.0f, 255.0f);
97  return convert_uchar4((float4){in.x, in.y, in.z, 0xFF});
98}
99
100uchar4 __attribute__((kernel)) alphaMask(uchar4 in, uint32_t x, uint32_t y) {
101  if (rsGetElementAt_uchar(mask,x,y) == 0) {
102    return (uchar4){0, 0, 0, 0};
103  }
104
105  return in;
106}
107
108float3 __attribute__((kernel)) solve1(uchar in, uint32_t x, uint32_t y) {
109  if (in > 0) {
110     float3 k = rsGetElementAt_float3(dest1, x - 1, y);
111     k += rsGetElementAt_float3(dest1, x + 1, y);
112     k += rsGetElementAt_float3(dest1, x, y - 1);
113     k += rsGetElementAt_float3(dest1, x, y + 1);
114     k += rsGetElementAt_float3(laplace, x, y);
115     k /= 4;
116     return k;
117  }
118  return rsGetElementAt_float3(dest1, x, y);;
119}
120
121
122float3 __attribute__((kernel)) solve2(uchar in, uint32_t x, uint32_t y) {
123  if (in > 0) {
124    float3 k = rsGetElementAt_float3(dest2, x - 1, y);
125    k += rsGetElementAt_float3(dest2, x + 1, y);
126    k += rsGetElementAt_float3(dest2, x, y - 1);
127    k += rsGetElementAt_float3(dest2, x, y + 1);
128       k += rsGetElementAt_float3(laplace, x, y);
129       k /= 4;
130       return k;
131  }
132  return rsGetElementAt_float3(dest2, x, y);;
133}
134
135rs_allocation image;
136rs_allocation border; // float3
137rs_allocation border_coords; //int2
138int borderLength;
139
140float3 __attribute__((kernel))extractBorder(int2 in) {
141  return convert_float3(rsGetElementAt_uchar4(image, in.x, in.y).xyz);
142}
143
144float __attribute__((kernel)) bordercorrelation(uint32_t x, uint32_t y) {
145  float sum = 0;
146  for(int i = 0 ; i < borderLength; i++) {
147    int2  coord = rsGetElementAt_int2(border_coords,i);
148    float3 orig = convert_float3(rsGetElementAt_uchar4(image, coord.x + x, coord.y + y).xyz);
149    float3 candidate = rsGetElementAt_float3(border, i).xyz;
150    sum += distance(orig, candidate);
151  }
152  return sum;
153}
154