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 typedef rs_allocation AllocationF32_3; 22 23 AllocationF32_3 src; 24 25 float3 __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 34 rs_allocation mask; // uchar 35 AllocationF32_3 laplace; // float3 36 AllocationF32_3 dest1; // float3 37 AllocationF32_3 dest2; // float3 38 39 float3 __attribute__((kernel)) convert_to_f(uchar4 in) { 40 return convert_float3(in.xyz); 41 } 42 float3 __attribute__((kernel)) copy(float3 in) { return in; } 43 44 float3 __attribute__((kernel)) copyMasked(uchar in, uint32_t x, uint32_t y) { 45 return rsGetElementAt_float3((in > 0) ? src : dest1, x, y); 46 } 47 48 uchar4 __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 53 uchar4 __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 61 float3 __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 74 float3 __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 87 rs_allocation image; 88 rs_allocation border; // float3 89 rs_allocation border_coords; // int2 90 int borderLength; 91 92 float3 __attribute__((kernel)) extractBorder(int2 in) { 93 return convert_float3(rsGetElementAt_uchar4(image, in.x, in.y).xyz); 94 } 95 96 float __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 108 static 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 117 static 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 125 void 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