1#pragma version(1) 2#pragma rs java_package_name(com.android.rs.image) 3#pragma rs_fp_relaxed 4 5 6int height; 7int width; 8static int radius; 9 10rs_allocation InPixel; 11rs_allocation ScratchPixel1; 12rs_allocation ScratchPixel2; 13 14const int MAX_RADIUS = 25; 15 16// Store our coefficients here 17static float gaussian[MAX_RADIUS * 2 + 1]; 18 19void setRadius(int rad) { 20 radius = rad; 21 // Compute gaussian weights for the blur 22 // e is the euler's number 23 float e = 2.718281828459045f; 24 float pi = 3.1415926535897932f; 25 // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 ) 26 // x is of the form [-radius .. 0 .. radius] 27 // and sigma varies with radius. 28 // Based on some experimental radius values and sigma's 29 // we approximately fit sigma = f(radius) as 30 // sigma = radius * 0.4 + 0.6 31 // The larger the radius gets, the more our gaussian blur 32 // will resemble a box blur since with large sigma 33 // the gaussian curve begins to lose its shape 34 float sigma = 0.4f * (float)radius + 0.6f; 35 36 // Now compute the coefficints 37 // We will store some redundant values to save some math during 38 // the blur calculations 39 // precompute some values 40 float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma); 41 float coeff2 = - 1.0f / (2.0f * sigma * sigma); 42 43 float normalizeFactor = 0.0f; 44 float floatR = 0.0f; 45 for (int r = -radius; r <= radius; r ++) { 46 floatR = (float)r; 47 gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2); 48 normalizeFactor += gaussian[r + radius]; 49 } 50 51 //Now we need to normalize the weights because all our coefficients need to add up to one 52 normalizeFactor = 1.0f / normalizeFactor; 53 for (int r = -radius; r <= radius; r ++) { 54 floatR = (float)r; 55 gaussian[r + radius] *= normalizeFactor; 56 } 57} 58 59float4 __attribute__((kernel)) copyIn(uchar4 in) { 60 return convert_float4(in); 61} 62 63uchar4 __attribute__((kernel)) vert(uint32_t x, uint32_t y) { 64 float3 blurredPixel = 0; 65 int gi = 0; 66 uchar4 out; 67 if ((y > radius) && (y < (height - radius))) { 68 for (int r = -radius; r <= radius; r ++) { 69 float4 i = rsGetElementAt_float4(ScratchPixel2, x, y + r); 70 blurredPixel += i.xyz * gaussian[gi++]; 71 } 72 } else { 73 for (int r = -radius; r <= radius; r ++) { 74 int validH = rsClamp((int)y + r, (int)0, (int)(height - 1)); 75 float4 i = rsGetElementAt_float4(ScratchPixel2, x, validH); 76 blurredPixel += i.xyz * gaussian[gi++]; 77 } 78 } 79 80 out.xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f)); 81 out.w = 0xff; 82 return out; 83} 84 85float4 __attribute__((kernel)) horz(uint32_t x, uint32_t y) { 86 float4 blurredPixel = 0; 87 int gi = 0; 88 if ((x > radius) && (x < (width - radius))) { 89 for (int r = -radius; r <= radius; r ++) { 90 float4 i = rsGetElementAt_float4(ScratchPixel1, x + r, y); 91 blurredPixel += i * gaussian[gi++]; 92 } 93 } else { 94 for (int r = -radius; r <= radius; r ++) { 95 // Stepping left and right away from the pixel 96 int validX = rsClamp((int)x + r, (int)0, (int)(width - 1)); 97 float4 i = rsGetElementAt_float4(ScratchPixel1, validX, y); 98 blurredPixel += i * gaussian[gi++]; 99 } 100 } 101 102 return blurredPixel; 103} 104 105