1b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar/* 2b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * Copyright (C) 2016 The Android Open Source Project 3b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * 4b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * Licensed under the Apache License, Version 2.0 (the "License"); 5b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * you may not use this file except in compliance with the License. 6b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * You may obtain a copy of the License at 7b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * 8b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * http://www.apache.org/licenses/LICENSE-2.0 9b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * 10b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * Unless required by applicable law or agreed to in writing, software 11b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * distributed under the License is distributed on an "AS IS" BASIS, 12b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * See the License for the specific language governing permissions and 14b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar * limitations under the License. 15b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar */ 16b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 17b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar#include "ip.rsh" 18b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar#pragma rs_fp_relaxed 19b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 20b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainarint height; 21b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainarint width; 22b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainarstatic int radius; 23b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 24b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainarrs_allocation InPixel; 25b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainarrs_allocation ScratchPixel1; 26b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainarrs_allocation ScratchPixel2; 27b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 28b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainarconst int MAX_RADIUS = 25; 29b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 30b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar// Store our coefficients here 31b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainarstatic half gaussian[MAX_RADIUS * 2 + 1]; 32b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 33b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainarvoid setRadius(int rad) { 34b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar radius = rad; 35b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // Compute gaussian weights for the blur 36b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // e is the euler's number 37b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half e = 2.718281828459045f; 38b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half pi = 3.1415926535897932f; 39b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 ) 40b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // x is of the form [-radius .. 0 .. radius] 41b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // and sigma varies with radius. 42b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // Based on some experimental radius values and sigma's 43b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // we approximately fit sigma = f(radius) as 44b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // sigma = radius * 0.4 + 0.6 45b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // The larger the radius gets, the more our gaussian blur 46b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // will resemble a box blur since with large sigma 47b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // the gaussian curve begins to lose its shape 48b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half sigma = 0.4f * (half)radius + 0.6f; 49b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 50b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // Now compute the coefficints 51b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // We will store some redundant values to save some math during 52b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // the blur calculations 53b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // precompute some values 54b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma); 55b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half coeff2 = - 1.0f / (2.0f * sigma * sigma); 56b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 57b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half normalizeFactor = 0.0f; 58b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half halfR = 0.0f; 59b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar for (int r = -radius; r <= radius; r ++) { 60b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar halfR = (half)r; 61b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar gaussian[r + radius] = coeff1 * pow(e, halfR * halfR * coeff2); 62b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar normalizeFactor += gaussian[r + radius]; 63b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar } 64b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 65b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar //Now we need to normalize the weights because all our coefficients need to add up to one 66b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar normalizeFactor = 1.0f / normalizeFactor; 67b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar for (int r = -radius; r <= radius; r ++) { 68b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar halfR = (half)r; 69b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar gaussian[r + radius] *= normalizeFactor; 70b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar } 71b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar} 72b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 73b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainarhalf4 RS_KERNEL copyIn(uchar4 in) { 74b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar return convert_half4(in); 75b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar} 76b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 77b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainaruchar4 RS_KERNEL vert(uint32_t x, uint32_t y) { 78b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half3 blurredPixel = 0; 79b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar int gi = 0; 80b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar uchar4 out; 81b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar if ((y > radius) && (y < (height - radius))) { 82b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar for (int r = -radius; r <= radius; r ++) { 83b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half4 i = rsGetElementAt_half4(ScratchPixel2, x, y + r); 84b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar blurredPixel += i.xyz * gaussian[gi++]; 85b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar } 86b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar } else { 87b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar for (int r = -radius; r <= radius; r ++) { 88b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar int validH = clamp((int)y + r, (int)0, (int)(height - 1)); 89b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half4 i = rsGetElementAt_half4(ScratchPixel2, x, validH); 90b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar blurredPixel += i.xyz * gaussian[gi++]; 91b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar } 92b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar } 93b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 94b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar out.xyz = convert_uchar3(clamp(blurredPixel, (half) 0.f, (half) 255.f)); 95b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar out.w = 0xff; 96b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar return out; 97b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar} 98b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 99b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainarhalf4 RS_KERNEL horz(uint32_t x, uint32_t y) { 100b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half4 blurredPixel = 0; 101b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar int gi = 0; 102b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar if ((x > radius) && (x < (width - radius))) { 103b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar for (int r = -radius; r <= radius; r ++) { 104b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half4 i = rsGetElementAt_half4(ScratchPixel1, x + r, y); 105b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar blurredPixel += i * gaussian[gi++]; 106b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar } 107b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar } else { 108b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar for (int r = -radius; r <= radius; r ++) { 109b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar // Stepping left and right away from the pixel 110b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar int validX = clamp((int)x + r, (int)0, (int)(width - 1)); 111b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar half4 i = rsGetElementAt_half4(ScratchPixel1, validX, y); 112b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar blurredPixel += i * gaussian[gi++]; 113b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar } 114b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar } 115b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar 116b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar return blurredPixel; 117b4a8c2d0c147e8f7929ec048adceb340da26be22Pirama Arumuga Nainar} 118