Changeset 2661


Ignore:
Timestamp:
Aug 3, 2008, 5:54:56 PM (14 years ago)
Author:
Sam Hocevar
Message:
  • blur.c: remove the blurring code and use our generic convolution routine, which correctly recognises the Gaussian kernel as a separable filter. As a result, it is now 50% faster because the normalisation occurs at kernel build time.
Location:
libpipi/trunk/pipi/filter
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • libpipi/trunk/pipi/filter/blur.c

    r2643 r2661  
    4141                                     float dx, float dy)
    4242{
    43     pipi_image_t *dst;
    44     pipi_pixels_t *srcp, *dstp;
    45     float *srcdata, *dstdata;
    46     double *kernel, *buffer;
    47     double K;
    48     int x, y, i, w, h, kr, kw, gray;
     43    pipi_image_t *ret;
     44    double *kernel;
     45    double Kx, Ky, t = 0.0;
     46    int i, j, krx, kry, m, n;
    4947
    5048    if(rx < BLUR_EPSILON) rx = BLUR_EPSILON;
    5149    if(ry < BLUR_EPSILON) ry = BLUR_EPSILON;
    5250
    53     w = src->w;
    54     h = src->h;
    55 
    56     gray = (src->last_modified == PIPI_PIXELS_Y_F);
    57 
    58     srcp = gray ? pipi_getpixels(src, PIPI_PIXELS_Y_F)
    59                 : pipi_getpixels(src, PIPI_PIXELS_RGBA_F);
    60     srcdata = (float *)srcp->pixels;
    61 
    62     dst = pipi_new(w, h);
    63     dstp = gray ? pipi_getpixels(dst, PIPI_PIXELS_Y_F)
    64                 : pipi_getpixels(dst, PIPI_PIXELS_RGBA_F);
    65     dstdata = (float *)dstp->pixels;
    66 
    67     buffer = malloc(w * h * (gray ? 1 : 4) * sizeof(double));
    68 
    6951    /* FIXME: the kernel becomes far too big with large values of dx, because
    7052     * we grow both left and right. Fix the growing direction. */
    71     kr = (int)(3. * rx + .99999 + ceil(abs(dx)));
    72     kw = 2 * kr + 1;
    73     K = -1. / (2. * rx * rx);
     53    krx = (int)(3. * rx + .99999 + ceil(abs(dx)));
     54    m = 2 * krx + 1;
     55    Kx = -1. / (2. * rx * rx);
    7456
    75     kernel = malloc(kw * sizeof(double));
    76     for(i = -kr; i <= kr; i++)
    77         kernel[i + kr] = exp(K * ((double)i + dx) * ((double)i + dx));
     57    kry = (int)(3. * ry + .99999 + ceil(abs(dy)));
     58    n = 2 * kry + 1;
     59    Ky = -1. / (2. * ry * ry);
    7860
    79     for(y = 0; y < h; y++)
     61    kernel = malloc(m * n * sizeof(double));
     62
     63    for(j = -kry; j <= kry; j++)
    8064    {
    81         for(x = 0; x < w; x++)
     65        double ey = Ky * ((double)j + dy) * ((double)j + dy);
     66
     67        for(i = -krx; i <= krx; i++)
    8268        {
    83             if(gray)
    84             {
    85                 double Y = 0., t = 0.;
    86                 int x2;
     69            double ex = Kx * ((double)i + dx) * ((double)i + dx);
     70            double d = exp(ex + ey);
    8771
    88                 for(i = -kr; i <= kr; i++)
    89                 {
    90                     double f = kernel[i + kr];
    91 
    92                     x2 = x + i;
    93                     if(x2 < 0) x2 = 0;
    94                     else if(x2 >= w) x2 = w - 1;
    95 
    96                     Y += f * srcdata[y * w + x2];
    97                     t += f;
    98                 }
    99 
    100                 buffer[y * w + x] = Y / t;
    101             }
    102             else
    103             {
    104                 double R = 0., G = 0., B = 0., t = 0.;
    105                 int x2, off = 4 * (y * w + x);
    106 
    107                 for(i = -kr; i <= kr; i++)
    108                 {
    109                     double f = kernel[i + kr];
    110 
    111                     x2 = x + i;
    112                     if(x2 < 0) x2 = 0;
    113                     else if(x2 >= w) x2 = w - 1;
    114 
    115                     R += f * srcdata[(y * w + x2) * 4];
    116                     G += f * srcdata[(y * w + x2) * 4 + 1];
    117                     B += f * srcdata[(y * w + x2) * 4 + 2];
    118                     t += f;
    119                 }
    120 
    121                 buffer[off] = R / t;
    122                 buffer[off + 1] = G / t;
    123                 buffer[off + 2] = B / t;
    124             }
     72            kernel[(j + kry) * m + i + krx] = d;
     73            t += d;
    12574        }
    12675    }
    12776
     77    for(j = 0; j < n; j++)
     78        for(i = 0; i < m; i++)
     79            kernel[j * m + i] /= t;
     80
     81    ret = pipi_convolution(src, m, n, kernel);
     82
    12883    free(kernel);
    12984
    130     kr = (int)(3. * ry + .99999 + ceil(abs(dy)));
    131     kw = 2 * kr + 1;
    132     K = -1. / (2. * ry * ry);
    133 
    134     kernel = malloc(kw * sizeof(double));
    135     for(i = -kr; i <= kr; i++)
    136         kernel[i + kr] = exp(K * ((double)i + dy) * ((double)i + dy));
    137 
    138     for(y = 0; y < h; y++)
    139     {
    140         for(x = 0; x < w; x++)
    141         {
    142             if(gray)
    143             {
    144                 double Y = 0., t = 0.;
    145                 int y2;
    146 
    147                 for(i = -kr; i <= kr; i++)
    148                 {
    149                     double f = kernel[i + kr];
    150 
    151                     y2 = y + i;
    152                     if(y2 < 0) y2 = 0;
    153                     else if(y2 >= h) y2 = h - 1;
    154 
    155                     Y += f * buffer[y2 * w + x];
    156                     t += f;
    157                 }
    158 
    159                 dstdata[y * w + x] = Y / t;
    160             }
    161             else
    162             {
    163                 double R = 0., G = 0., B = 0., t = 0.;
    164                 int y2, off = 4 * (y * w + x);
    165 
    166                 for(i = -kr; i <= kr; i++)
    167                 {
    168                     double f = kernel[i + kr];
    169 
    170                     y2 = y + i;
    171                     if(y2 < 0) y2 = 0;
    172                     else if(y2 >= h) y2 = h - 1;
    173 
    174                     R += f * buffer[(y2 * w + x) * 4];
    175                     G += f * buffer[(y2 * w + x) * 4 + 1];
    176                     B += f * buffer[(y2 * w + x) * 4 + 2];
    177                     t += f;
    178                 }
    179 
    180                 dstdata[off] = R / t;
    181                 dstdata[off + 1] = G / t;
    182                 dstdata[off + 2] = B / t;
    183             }
    184         }
    185     }
    186 
    187     free(buffer);
    188     free(kernel);
    189 
    190     return dst;
     85    return ret;
    19186}
    19287
  • libpipi/trunk/pipi/filter/convolution.c

    r2660 r2661  
    7575    }
    7676
    77 printf("separabble!\n");
    78 
    7977    /* Matrix rank is 1! Separate the filter */
    8078    /* FIXME: memleak */
Note: See TracChangeset for help on using the changeset viewer.