1 #pragma version(1) 2 3 #include "ip.rsh" 4 5 int height; 6 int width; 7 int radius; 8 9 uchar4 * InPixel; 10 uchar4 * OutPixel; 11 float4 * ScratchPixel1; 12 float4 * ScratchPixel2; 13 14 rs_script vBlurScript; 15 rs_script hBlurScript; 16 17 const int CMD_FINISHED = 1; 18 19 // Store our coefficients here 20 static float gaussian[MAX_RADIUS * 2 + 1]; 21 22 23 static void computeGaussianWeights() { 24 // Compute gaussian weights for the blur 25 // e is the euler's number 26 float e = 2.718281828459045f; 27 float pi = 3.1415926535897932f; 28 // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 ) 29 // x is of the form [-radius .. 0 .. radius] 30 // and sigma varies with radius. 31 // Based on some experimental radius values and sigma's 32 // we approximately fit sigma = f(radius) as 33 // sigma = radius * 0.4 + 0.6 34 // The larger the radius gets, the more our gaussian blur 35 // will resemble a box blur since with large sigma 36 // the gaussian curve begins to lose its shape 37 float sigma = 0.4f * (float)radius + 0.6f; 38 39 // Now compute the coefficints 40 // We will store some redundant values to save some math during 41 // the blur calculations 42 // precompute some values 43 float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma); 44 float coeff2 = - 1.0f / (2.0f * sigma * sigma); 45 46 float normalizeFactor = 0.0f; 47 float floatR = 0.0f; 48 int r; 49 for (r = -radius; r <= radius; r ++) { 50 floatR = (float)r; 51 gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2); 52 normalizeFactor += gaussian[r + radius]; 53 } 54 55 //Now we need to normalize the weights because all our coefficients need to add up to one 56 normalizeFactor = 1.0f / normalizeFactor; 57 for (r = -radius; r <= radius; r ++) { 58 floatR = (float)r; 59 gaussian[r + radius] *= normalizeFactor; 60 } 61 } 62 63 64 static void copyInput() { 65 rs_allocation ain; 66 ain = rsGetAllocation(InPixel); 67 uint32_t dimx = rsAllocationGetDimX(ain); 68 uint32_t dimy = rsAllocationGetDimY(ain); 69 for (uint32_t y = 0; y < dimy; y++) { 70 for (uint32_t x = 0; x < dimx; x++) { 71 ScratchPixel1[x + y * dimx] = convert_float4(InPixel[x + y * dimx]); 72 } 73 } 74 } 75 76 void filter() { 77 copyInput(); 78 computeGaussianWeights(); 79 80 FilterStruct fs; 81 fs.gaussian = gaussian; 82 fs.width = width; 83 fs.height = height; 84 fs.radius = radius; 85 86 fs.ain = rsGetAllocation(ScratchPixel1); 87 rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs, sizeof(fs)); 88 89 fs.ain = rsGetAllocation(ScratchPixel2); 90 rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs, sizeof(fs)); 91 rsSendToClientBlocking(CMD_FINISHED); 92 } 93 94