rsdIntrinsicBlur.cpp revision 2207ab7e0f2d28382fe61ff002ddd58c4fa3fb99
1d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams/*
2d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams * Copyright (C) 2012 The Android Open Source Project
3d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams *
4d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams * Licensed under the Apache License, Version 2.0 (the "License");
5d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams * you may not use this file except in compliance with the License.
6d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams * You may obtain a copy of the License at
7d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams *
8d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams *      http://www.apache.org/licenses/LICENSE-2.0
9d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams *
10d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams * Unless required by applicable law or agreed to in writing, software
11d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams * distributed under the License is distributed on an "AS IS" BASIS,
12d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams * See the License for the specific language governing permissions and
14d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams * limitations under the License.
15d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams */
16d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
17d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
18d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams#include "rsdCore.h"
19d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams#include "rsdIntrinsics.h"
20d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams#include "rsdAllocation.h"
21d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
22d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams#include "rsdIntrinsicInlines.h"
23d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
24d85e283087ecd00760a0d8d0c9d8482cda845efcJason Samsusing namespace android;
25d85e283087ecd00760a0d8d0c9d8482cda845efcJason Samsusing namespace android::renderscript;
26d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
27d85e283087ecd00760a0d8d0c9d8482cda845efcJason Samsstruct ConvolveParams {
28d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float fp[104];
29d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    short ip[104];
30d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float radius;
31d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    int iradius;
32d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    ObjectBaseRef<Allocation> alloc;
33d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams};
34d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
35d85e283087ecd00760a0d8d0c9d8482cda845efcJason Samsstatic void ComputeGaussianWeights(ConvolveParams *cp) {
36d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // Compute gaussian weights for the blur
37d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // e is the euler's number
38d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float e = 2.718281828459045f;
39d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float pi = 3.1415926535897932f;
40d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
41d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // x is of the form [-radius .. 0 .. radius]
42d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // and sigma varies with radius.
43d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // Based on some experimental radius values and sigma's
44d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // we approximately fit sigma = f(radius) as
45d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // sigma = radius * 0.4  + 0.6
46d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // The larger the radius gets, the more our gaussian blur
47d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // will resemble a box blur since with large sigma
48d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // the gaussian curve begins to lose its shape
49d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float sigma = 0.4f * cp->radius + 0.6f;
50d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
51d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // Now compute the coefficients. We will store some redundant values to save
52d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    // some math during the blur calculations precompute some values
53d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float coeff1 = 1.0f / (sqrtf(2.0f * pi) * sigma);
54d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float coeff2 = - 1.0f / (2.0f * sigma * sigma);
55d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
56d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float normalizeFactor = 0.0f;
57d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float floatR = 0.0f;
58d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    int r;
59d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    cp->iradius = (float)ceil(cp->radius) + 0.5f;
60d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    for (r = -cp->iradius; r <= cp->iradius; r ++) {
61d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        floatR = (float)r;
62d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        cp->fp[r + cp->iradius] = coeff1 * powf(e, floatR * floatR * coeff2);
63d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        normalizeFactor += cp->fp[r + cp->iradius];
64d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    }
65d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
66d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    //Now we need to normalize the weights because all our coefficients need to add up to one
67d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    normalizeFactor = 1.0f / normalizeFactor;
68d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    for (r = -cp->iradius; r <= cp->iradius; r ++) {
69d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        cp->fp[r + cp->iradius] *= normalizeFactor;
70d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        cp->ip[r + cp->iradius] = (short)(cp->ip[r + cp->iradius] * 32768);
71d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    }
72d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams}
73d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
74d85e283087ecd00760a0d8d0c9d8482cda845efcJason Samsstatic void Blur_Bind(const Context *dc, const Script *script,
75d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams                             void * intrinsicData, uint32_t slot, Allocation *data) {
76d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    ConvolveParams *cp = (ConvolveParams *)intrinsicData;
77d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    rsAssert(slot == 1);
78d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    cp->alloc.set(data);
79d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams}
80d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
81d85e283087ecd00760a0d8d0c9d8482cda845efcJason Samsstatic void Blur_SetVar(const Context *dc, const Script *script, void * intrinsicData,
82d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams                               uint32_t slot, void *data, size_t dataLength) {
83d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    ConvolveParams *cp = (ConvolveParams *)intrinsicData;
84d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    rsAssert(slot == 0);
85d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
86d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    cp->radius = ((const float *)data)[0];
87d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    ComputeGaussianWeights(cp);
88d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams}
89d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
90d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
91d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
92d85e283087ecd00760a0d8d0c9d8482cda845efcJason Samsstatic void OneV(const RsForEachStubParamStruct *p, float4 *out, int32_t x, int32_t y,
93d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams                 const uchar *ptrIn, int iStride, const float* gPtr, int iradius) {
94d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
95d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    const uchar *pi = ptrIn + x*4;
96d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
97d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float4 blurredPixel = 0;
98d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    for (int r = -iradius; r <= iradius; r ++) {
99d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        int validY = rsMax((y + r), 0);
100d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        validY = rsMin(validY, (int)(p->dimY - 1));
101d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        const uchar4 *pvy = (const uchar4 *)&pi[validY * iStride];
102d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        float4 pf = convert_float4(pvy[0]);
103d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        blurredPixel += pf * gPtr[0];
104d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        gPtr++;
105d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    }
106d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
107d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    out->xyzw = blurredPixel;
108d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams}
109d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
110e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Samsextern "C" void rsdIntrinsicBlurVF_K(void *dst, const void *pin, int stride, const void *gptr, int rct, int x1, int x2);
111e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Samsextern "C" void rsdIntrinsicBlurHF_K(void *dst, const void *pin, const void *gptr, int rct, int x1, int x2);
112e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams
113e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Samsstatic void OneVF(float4 *out,
114e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams                  const uchar *ptrIn, int iStride, const float* gPtr, int ct,
115e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams                  int x1, int x2) {
116e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams
117e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams#if defined(ARCH_ARM_HAVE_NEON)
1182207ab7e0f2d28382fe61ff002ddd58c4fa3fb99Jason Sams    {
1192207ab7e0f2d28382fe61ff002ddd58c4fa3fb99Jason Sams        int t = (x2 - x1);
1202207ab7e0f2d28382fe61ff002ddd58c4fa3fb99Jason Sams        t &= ~1;
1212207ab7e0f2d28382fe61ff002ddd58c4fa3fb99Jason Sams        if(t) {
1222207ab7e0f2d28382fe61ff002ddd58c4fa3fb99Jason Sams            rsdIntrinsicBlurVF_K(out, ptrIn, iStride, gPtr, ct, x1, x1 + t);
1232207ab7e0f2d28382fe61ff002ddd58c4fa3fb99Jason Sams        }
1242207ab7e0f2d28382fe61ff002ddd58c4fa3fb99Jason Sams        x1 += t;
1252207ab7e0f2d28382fe61ff002ddd58c4fa3fb99Jason Sams    }
126e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams#endif
127e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams
128e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams    while(x2 > x1) {
129e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        const uchar *pi = ptrIn + x1 * 4;
130e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        float4 blurredPixel = 0;
131e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        const float* gp = gPtr;
132e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams
133e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        for (int r = 0; r < ct; r++) {
134e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams            float4 pf = convert_float4(((const uchar4 *)pi)[0]);
135e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams            blurredPixel += pf * gp[0];
136e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams            pi += iStride;
137e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams            gp++;
138e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        }
139e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        out->xyzw = blurredPixel;
140e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        x1++;
141e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        out++;
142e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams    }
143e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams}
144e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams
145d85e283087ecd00760a0d8d0c9d8482cda845efcJason Samsstatic void OneH(const RsForEachStubParamStruct *p, uchar4 *out, int32_t x,
146d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams                const float4 *ptrIn, const float* gPtr, int iradius) {
147d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
148d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float4 blurredPixel = 0;
149d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    for (int r = -iradius; r <= iradius; r ++) {
150d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        int validX = rsMax((x + r), 0);
151d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        validX = rsMin(validX, (int)(p->dimX - 1));
152d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        float4 pf = ptrIn[validX];
153d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        blurredPixel += pf * gPtr[0];
154d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        gPtr++;
155d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    }
156d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
157d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    out->xyzw = convert_uchar4(blurredPixel);
158d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams}
159d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
160d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
161d85e283087ecd00760a0d8d0c9d8482cda845efcJason Samsstatic void Blur_uchar4(const RsForEachStubParamStruct *p,
162d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams                                    uint32_t xstart, uint32_t xend,
163d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams                                    uint32_t instep, uint32_t outstep) {
164d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float buf[4 * 2048];
165d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    ConvolveParams *cp = (ConvolveParams *)p->usr;
166d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    DrvAllocation *din = (DrvAllocation *)cp->alloc->mHal.drv;
167d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    const uchar *pin = (const uchar *)din->lod[0].mallocPtr;
168d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
169d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    uchar4 *out = (uchar4 *)p->out;
170d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    uint32_t x1 = xstart;
171d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    uint32_t x2 = xend;
172d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
173d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    float4 *fout = (float4 *)buf;
174e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams    int y = p->y;
175e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams    if ((y > cp->iradius) && (y < ((int)p->dimY - cp->iradius))) {
176e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        const uchar *pi = pin + (y - cp->iradius) * din->lod[0].stride;
177e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        OneVF(fout, pi, din->lod[0].stride, cp->fp, cp->iradius * 2 + 1, x1, x2);
178e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams    } else {
179e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        while(x2 > x1) {
180e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams            OneV(p, fout, x1, y, pin, din->lod[0].stride, cp->fp, cp->iradius);
181e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams            fout++;
182e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams            x1++;
183e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        }
184d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    }
185d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
186d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    x1 = xstart;
187e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams    while ((x1 < (uint32_t)cp->iradius) && (x1 < x2)) {
188e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        OneH(p, out, x1, (float4 *)buf, cp->fp, cp->iradius);
189e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        out++;
190e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        x1++;
191e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams    }
192e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams#if defined(ARCH_ARM_HAVE_NEON)
193e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams    if ((x1 + cp->iradius) < x2) {
194e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        rsdIntrinsicBlurHF_K(out, ((float4 *)buf) - cp->iradius, cp->fp, cp->iradius * 2 + 1, x1, x2 - cp->iradius);
195e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        out += (x2 - cp->iradius) - x1;
196e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams        x1 = x2 - cp->iradius;
197e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams    }
198e78e514f3f209e594767e8ebc64f5df4be5b0b41Jason Sams#endif
199d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    while(x2 > x1) {
200d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        OneH(p, out, x1, (float4 *)buf, cp->fp, cp->iradius);
201d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        out++;
202d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams        x1++;
203d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    }
204d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
205d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams}
206d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
207d85e283087ecd00760a0d8d0c9d8482cda845efcJason Samsvoid * rsdIntrinsic_InitBlur(const android::renderscript::Context *dc,
208d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams                                    android::renderscript::Script *script,
209d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams                                    RsdIntriniscFuncs_t *funcs) {
210d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
211d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    script->mHal.info.exportedVariableCount = 2;
212d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    funcs->bind = Blur_Bind;
213d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    funcs->setVar = Blur_SetVar;
214d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    funcs->root = Blur_uchar4;
215d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
216d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    ConvolveParams *cp = (ConvolveParams *)calloc(1, sizeof(ConvolveParams));
217d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    cp->radius = 5;
218d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    ComputeGaussianWeights(cp);
219d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams    return cp;
220d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams}
221d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
222d85e283087ecd00760a0d8d0c9d8482cda845efcJason Sams
223