Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 1 | #pragma version(1) |
| 2 | |
Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 3 | #include "ip.rsh" |
| 4 | |
| 5 | int height; |
| 6 | int width; |
| 7 | int radius; |
| 8 | |
| 9 | uchar4 * InPixel; |
| 10 | uchar4 * OutPixel; |
Jason Sams | 43c3142 | 2010-08-16 12:29:23 -0700 | [diff] [blame] | 11 | float4 * ScratchPixel1; |
| 12 | float4 * ScratchPixel2; |
Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 13 | |
Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 14 | rs_script vBlurScript; |
| 15 | rs_script hBlurScript; |
Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 16 | |
Jason Sams | 1796651 | 2010-07-28 11:17:53 -0700 | [diff] [blame] | 17 | const int CMD_FINISHED = 1; |
Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 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; |
Alex Sakhartchouk | ed9f210 | 2010-11-09 17:00:54 -0800 | [diff] [blame] | 49 | for (r = -radius; r <= radius; r ++) { |
Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 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; |
Alex Sakhartchouk | ed9f210 | 2010-11-09 17:00:54 -0800 | [diff] [blame] | 57 | for (r = -radius; r <= radius; r ++) { |
Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 58 | floatR = (float)r; |
| 59 | gaussian[r + radius] *= normalizeFactor; |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | |
Jason Sams | 43c3142 | 2010-08-16 12:29:23 -0700 | [diff] [blame] | 64 | static void copyInput() { |
Stephen Hines | baa19bc | 2010-11-15 17:09:02 -0800 | [diff] [blame] | 65 | rs_allocation ain; |
Stephen Hines | c32b994 | 2011-05-02 18:06:48 -0700 | [diff] [blame] | 66 | ain = rsGetAllocation(InPixel); |
Jason Sams | 43c3142 | 2010-08-16 12:29:23 -0700 | [diff] [blame] | 67 | uint32_t dimx = rsAllocationGetDimX(ain); |
| 68 | uint32_t dimy = rsAllocationGetDimY(ain); |
Alex Sakhartchouk | ed9f210 | 2010-11-09 17:00:54 -0800 | [diff] [blame] | 69 | for (uint32_t y = 0; y < dimy; y++) { |
| 70 | for (uint32_t x = 0; x < dimx; x++) { |
Jason Sams | 43c3142 | 2010-08-16 12:29:23 -0700 | [diff] [blame] | 71 | ScratchPixel1[x + y * dimx] = convert_float4(InPixel[x + y * dimx]); |
| 72 | } |
| 73 | } |
Jason Sams | 43c3142 | 2010-08-16 12:29:23 -0700 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | void filter() { |
| 77 | copyInput(); |
Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 78 | computeGaussianWeights(); |
| 79 | |
| 80 | FilterStruct fs; |
| 81 | fs.gaussian = gaussian; |
| 82 | fs.width = width; |
| 83 | fs.height = height; |
| 84 | fs.radius = radius; |
| 85 | |
Jason Sams | 43c3142 | 2010-08-16 12:29:23 -0700 | [diff] [blame] | 86 | fs.ain = rsGetAllocation(ScratchPixel1); |
| 87 | rsForEach(hBlurScript, fs.ain, rsGetAllocation(ScratchPixel2), &fs); |
Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 88 | |
Jason Sams | 43c3142 | 2010-08-16 12:29:23 -0700 | [diff] [blame] | 89 | fs.ain = rsGetAllocation(ScratchPixel2); |
Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 90 | rsForEach(vBlurScript, fs.ain, rsGetAllocation(OutPixel), &fs); |
Jason Sams | 1796651 | 2010-07-28 11:17:53 -0700 | [diff] [blame] | 91 | rsSendToClientBlocking(CMD_FINISHED); |
Jason Sams | c7f4e41 | 2010-07-20 15:09:00 -0700 | [diff] [blame] | 92 | } |
| 93 | |