|
| 1 | +#include <Halide.h> |
| 2 | + |
| 3 | +using namespace Halide; |
| 4 | + |
| 5 | +class IirBlur : public Generator<IirBlur> { |
| 6 | +public: |
| 7 | + // The input is a 3D single precision float buffer, the first two |
| 8 | + // dimensions are the pixels, and the third is the color channel. |
| 9 | + ImageParam input{Float(32), 3, "input"}; |
| 10 | + // This parameter is the strength of the blur. |
| 11 | + Param<float> A{"A"}; |
| 12 | + |
| 13 | + // Declare our free variables. |
| 14 | + Var x, y, c; |
| 15 | + |
| 16 | + Func blur_transpose(Func f, Expr height) { |
| 17 | + // Define the blur: first, just copy f to blur. |
| 18 | + Func blur; |
| 19 | + blur(x, y, c) = f(x, y, c); |
| 20 | + |
| 21 | + // Blur down the columns. |
| 22 | + RDom ry(1, height - 1); |
| 23 | + blur(x, ry, c) = A*blur(x, ry, c) + (1 - A)*blur(x, ry - 1, c); |
| 24 | + |
| 25 | + // And back up the columns. |
| 26 | + Expr flip_ry = height - ry - 1; |
| 27 | + blur(x, flip_ry, c) = |
| 28 | + A*blur(x, flip_ry, c) + (1 - A)*blur(x, flip_ry + 1, c); |
| 29 | + |
| 30 | + // Transpose the resulting blurred image. |
| 31 | + Func transpose; |
| 32 | + transpose(x, y, c) = blur(y, x, c); |
| 33 | + |
| 34 | + // Schedule. |
| 35 | + // First, split transpose into groups of 8 rows of pixels. |
| 36 | + Var yo, yi; |
| 37 | + transpose.compute_root().split(y, yo, yi, 8); |
| 38 | + |
| 39 | + // Parallelize the groups of rows. |
| 40 | + transpose.parallel(yo); |
| 41 | + |
| 42 | + // Compute the blur at each strip of rows (columns before the |
| 43 | + // transpose). |
| 44 | + blur.compute_at(transpose, yo); |
| 45 | + |
| 46 | + // Vectorize across x for all steps of blur. |
| 47 | + blur.vectorize(x, 8); |
| 48 | + blur.update(0).vectorize(x, 8); |
| 49 | + blur.update(1).vectorize(x, 8); |
| 50 | + |
| 51 | + return transpose; |
| 52 | + } |
| 53 | + |
| 54 | + Func build() { |
| 55 | + // Wrap the input image in a func. |
| 56 | + Func input_func; |
| 57 | + input_func(x, y, c) = input(x, y, c); |
| 58 | + |
| 59 | + // Blur down the columns and transpose. |
| 60 | + Func blur_y = blur_transpose(input_func, input.height()); |
| 61 | + |
| 62 | + // Blur down the columns again (rows after the transpose |
| 63 | + // above), and then transpose back to the original |
| 64 | + // orientation. |
| 65 | + Func blur = blur_transpose(blur_y, input.width()); |
| 66 | + |
| 67 | + return blur; |
| 68 | + } |
| 69 | +}; |
| 70 | + |
| 71 | +auto gen = RegisterGenerator<IirBlur>("IirBlur"); |
0 commit comments