Home | History | Annotate | Download | only in healingbrush
      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