blob: c9d04f2cc6198ed227d00176f7719f60248d1d2b [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma version(1)
#pragma rs java_package_name(com.example.android.rs.sample)
#pragma rs_fp_relaxed
rs_allocation tmp;
static inline rs_allocation createVectorAllocation(rs_data_type dt, int vecSize,
int gDimX, int gDimY,
int gDimZ) {
rs_element element;
rs_type type;
if (vecSize == 1)
element = rsCreateElement(dt);
else
element = rsCreateVectorElement(dt, vecSize);
if (gDimY == 0) {
rsDebug("find_region.rs: ", __LINE__);
type = rsCreateType(element, gDimX);
} else {
type = rsCreateType(element, gDimX, gDimY, gDimZ);
}
tmp = rsCreateAllocation(type);
return tmp;
}
typedef rs_allocation AllocationF32_3;
static float3 getF32_3(AllocationF32_3 in, uint32_t x, uint32_t y) {
return rsGetElementAt_float3(in, x, y);
}
AllocationF32_3 src;
float3 __attribute__((kernel)) laplacian(uint32_t x, uint32_t y) {
float3 out = 4 * getF32_3(src, x, y);
out -= getF32_3(src, x - 1, y);
out -= getF32_3(src, x + 1, y);
out -= getF32_3(src, x, y - 1);
out -= getF32_3(src, x, y + 1);
return out;
}
rs_allocation mask; // uchar
AllocationF32_3 laplace; // float3
AllocationF32_3 dest1; // float3
AllocationF32_3 dest2; // float3
float3 __attribute__((kernel)) convert_to_f(uchar4 in) {
return convert_float3(in.xyz);
}
float3 __attribute__((kernel)) copy(float3 in) { return in; }
float3 __attribute__((kernel)) copyMasked(uchar in, uint32_t x, uint32_t y) {
return getF32_3((in > 0) ? src : dest1, x, y);
}
uchar4 __attribute__((kernel)) convert_to_uc(float3 in) {
in = clamp(in, 0.0f, 255.0f);
return convert_uchar4((float4){in.x, in.y, in.z, 0xFF});
}
uchar4 __attribute__((kernel)) alphaMask(uchar4 in, uint32_t x, uint32_t y) {
if (rsGetElementAt_uchar(mask, x, y) == 0) {
return (uchar4){0, 0, 0, 0};
}
return in;
}
float3 __attribute__((kernel)) solve1(uchar in, uint32_t x, uint32_t y) {
if (in > 0) {
float3 k = getF32_3(dest1, x - 1, y);
k += getF32_3(dest1, x + 1, y);
k += getF32_3(dest1, x, y - 1);
k += getF32_3(dest1, x, y + 1);
k += getF32_3(laplace, x, y);
k /= 4;
return k;
}
return rsGetElementAt_float3(dest1, x, y);
}
float3 __attribute__((kernel)) solve2(uchar in, uint32_t x, uint32_t y) {
if (in > 0) {
float3 k = getF32_3(dest2, x - 1, y);
k += getF32_3(dest2, x + 1, y);
k += getF32_3(dest2, x, y - 1);
k += getF32_3(dest2, x, y + 1);
k += getF32_3(laplace, x, y);
k /= 4;
return k;
}
return getF32_3(dest2, x, y);
}
rs_allocation image;
rs_allocation border; // float3
rs_allocation border_coords; // int2
int borderLength;
float3 __attribute__((kernel)) extractBorder(int2 in) {
return convert_float3(rsGetElementAt_uchar4(image, in.x, in.y).xyz);
}
float __attribute__((kernel)) bordercorrelation(uint32_t x, uint32_t y) {
float sum = 0;
for (int i = 0; i < borderLength; i++) {
int2 coord = rsGetElementAt_int2(border_coords, i);
float3 orig = convert_float3(
rsGetElementAt_uchar4(image, coord.x + x, coord.y + y).xyz);
float3 candidate = rsGetElementAt_float3(border, i).xyz;
sum += distance(orig, candidate);
}
return sum;
}
static rs_allocation tmp_ret;
static inline rs_allocation toFloat3(rs_allocation in) {
int width = rsAllocationGetDimX(in);
int height = rsAllocationGetDimY(in);
tmp_ret = createVectorAllocation(RS_TYPE_FLOAT_32, 3, width, height, 0);
rsForEach(convert_to_f, in, tmp_ret);
return tmp_ret;
}
static rs_allocation clone(rs_allocation in) {
int width = rsAllocationGetDimX(in);
int height = rsAllocationGetDimY(in);
tmp_ret = createVectorAllocation(RS_TYPE_FLOAT_32, 3, width, height, 0);
rsForEach(copy, in, tmp_ret);
return tmp_ret;
}
void heal(rs_allocation mask_image, rs_allocation src_image,
rs_allocation dest_image) {
int width = rsAllocationGetDimX(src_image);
int height = rsAllocationGetDimY(src_image);
src = toFloat3(src_image);
mask = mask_image;
laplace = createVectorAllocation(RS_TYPE_FLOAT_32, 3, width, height, 0);
dest1 = toFloat3(dest_image);
dest2 = clone(dest1);
int steps = (int)hypot((float)width, (float)height);
rsDebug("find_region.rs:steps = ", steps);
rs_script_call_t opts = {0};
opts.xStart = 1;
opts.xEnd = width - 1;
opts.yStart = 1;
opts.yEnd = height - 1;
rsForEachWithOptions(laplacian, &opts, laplace);
rsForEach(copyMasked, mask, dest1);
for (int i = 0; i < steps; i++) {
rsForEach(solve1, mask, dest2);
rsForEach(solve2, mask, dest1);
}
rsForEach(convert_to_uc, dest1, dest_image);
rsForEach(alphaMask, dest_image, dest_image);
}