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
21typedef rs_allocation AllocationF32_3;
22
23AllocationF32_3 src;
24
25float3 __attribute__((kernel)) laplacian(uint32_t x, uint32_t y) {
26  float3 out = 4 * rsGetElementAt_float3(src, x, y);
27  out -= rsGetElementAt_float3(src, x - 1, y);
28  out -= rsGetElementAt_float3(src, x + 1, y);
29  out -= rsGetElementAt_float3(src, x, y - 1);
30  out -= rsGetElementAt_float3(src, x, y + 1);
31  return out;
32}
33
34rs_allocation mask;       // uchar
35AllocationF32_3 laplace;  // float3
36AllocationF32_3 dest1;    // float3
37AllocationF32_3 dest2;    // float3
38
39float3 __attribute__((kernel)) convert_to_f(uchar4 in) {
40  return convert_float3(in.xyz);
41}
42float3 __attribute__((kernel)) copy(float3 in) { return in; }
43
44float3 __attribute__((kernel)) copyMasked(uchar in, uint32_t x, uint32_t y) {
45  return rsGetElementAt_float3((in > 0) ? src : dest1, x, y);
46}
47
48uchar4 __attribute__((kernel)) convert_to_uc(float3 in) {
49  in = clamp(in, 0.0f, 255.0f);
50  return convert_uchar4((float4){in.x, in.y, in.z, 0xFF});
51}
52
53uchar4 __attribute__((kernel)) alphaMask(uchar4 in, uint32_t x, uint32_t y) {
54  if (rsGetElementAt_uchar(mask, x, y) == 0) {
55    return (uchar4){0, 0, 0, 0};
56  }
57
58  return in;
59}
60
61float3 __attribute__((kernel)) solve1(uchar in, uint32_t x, uint32_t y) {
62  if (in > 0) {
63    float3 k = rsGetElementAt_float3(dest1, x - 1, y);
64    k += rsGetElementAt_float3(dest1, x + 1, y);
65    k += rsGetElementAt_float3(dest1, x, y - 1);
66    k += rsGetElementAt_float3(dest1, x, y + 1);
67    k += rsGetElementAt_float3(laplace, x, y);
68    k /= 4;
69    return k;
70  }
71  return rsGetElementAt_float3(dest1, x, y);
72}
73
74float3 __attribute__((kernel)) solve2(uchar in, uint32_t x, uint32_t y) {
75  if (in > 0) {
76    float3 k = rsGetElementAt_float3(dest2, x - 1, y);
77    k += rsGetElementAt_float3(dest2, x + 1, y);
78    k += rsGetElementAt_float3(dest2, x, y - 1);
79    k += rsGetElementAt_float3(dest2, x, y + 1);
80    k += rsGetElementAt_float3(laplace, x, y);
81    k /= 4;
82    return k;
83  }
84  return rsGetElementAt_float3(dest2, x, y);
85}
86
87rs_allocation image;
88rs_allocation border;         // float3
89rs_allocation border_coords;  // int2
90int borderLength;
91
92float3 __attribute__((kernel)) extractBorder(int2 in) {
93  return convert_float3(rsGetElementAt_uchar4(image, in.x, in.y).xyz);
94}
95
96float __attribute__((kernel)) bordercorrelation(uint32_t x, uint32_t y) {
97  float sum = 0;
98  for (int i = 0; i < borderLength; i++) {
99    int2 coord = rsGetElementAt_int2(border_coords, i);
100    float3 orig = convert_float3(
101        rsGetElementAt_uchar4(image, coord.x + x, coord.y + y).xyz);
102    float3 candidate = rsGetElementAt_float3(border, i).xyz;
103    sum += distance(orig, candidate);
104  }
105  return sum;
106}
107
108static inline rs_allocation toFloat3(rs_allocation in) {
109  int width = rsAllocationGetDimX(in);
110  int height = rsAllocationGetDimY(in);
111
112  rs_allocation tmp = rsCreateAllocation_float3(width, height);
113  rsForEach(convert_to_f, in, tmp);
114  return tmp;
115}
116
117static rs_allocation clone(rs_allocation in) {
118  int width = rsAllocationGetDimX(in);
119  int height = rsAllocationGetDimY(in);
120  rs_allocation tmp = rsCreateAllocation_float3(width, height);
121  rsForEach(copy, in, tmp);
122  return tmp;
123}
124
125void heal(rs_allocation mask_image, rs_allocation src_image,
126          rs_allocation dest_image) {
127  int width = rsAllocationGetDimX(src_image);
128  int height = rsAllocationGetDimY(src_image);
129  src = toFloat3(src_image);
130  mask = mask_image;
131  laplace = rsCreateAllocation_float3(width, height);
132  dest1 = toFloat3(dest_image);
133  dest2 = clone(dest1);
134
135  int steps = (int)hypot((float)width, (float)height);
136  rsDebug("find_region.rs:steps = ", steps);
137
138  rs_script_call_t opts = {0};
139  opts.xStart = 1;
140  opts.xEnd = width - 1;
141  opts.yStart = 1;
142  opts.yEnd = height - 1;
143  rsForEachWithOptions(laplacian, &opts, laplace);
144  rsForEach(copyMasked, mask, dest1);
145  for (int i = 0; i < steps; i++) {
146    rsForEach(solve1, mask, dest2);
147    rsForEach(solve2, mask, dest1);
148  }
149
150  rsForEach(convert_to_uc, dest1, dest_image);
151  rsForEach(alphaMask, dest_image, dest_image);
152}
153