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