Changeset 2743


Ignore:
Timestamp:
08/21/08 00:00:01 (5 years ago)
Author:
sam
Message:
  • blur.c: proper box blur implementation that runs linearly with pixel count.
File:
1 edited

Legend:

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

    r2737 r2743  
    116116} 
    117117 
    118 /* FIXME: box blur would be incredibly faster using an accumulator instead 
    119  * of a convolution filter... */ 
    120118pipi_image_t *pipi_box_blur(pipi_image_t *src, int size) 
    121119{ 
     
    123121} 
    124122 
     123/* FIXME: split this into templates for wrap-around and proper gray support */ 
    125124pipi_image_t *pipi_box_blur_ext(pipi_image_t *src, int m, int n) 
    126125{ 
    127     pipi_image_t *ret; 
    128     double *kernel; 
    129     int i; 
    130  
    131     kernel = malloc(m * n * sizeof(double)); 
    132     for(i = 0; i < m * n; i++) 
    133         kernel[i] = 1. / (m * n); 
    134  
    135     ret = pipi_convolution(src, m, n, kernel); 
    136  
    137     free(kernel); 
    138  
    139     return ret; 
    140 } 
    141  
     126    pipi_image_t *dst; 
     127    pipi_pixels_t *srcp, *dstp; 
     128    float *srcdata, *dstdata; 
     129    double *acc; 
     130    int x, y, w, h, i, j, size, gray; 
     131 
     132    w = src->w; 
     133    h = src->h; 
     134    size = (2 * m + 1) * (2 * n + 1); 
     135 
     136    gray = (src->last_modified == PIPI_PIXELS_Y_F); 
     137 
     138    srcp = gray ? pipi_getpixels(src, PIPI_PIXELS_Y_F) 
     139                : pipi_getpixels(src, PIPI_PIXELS_RGBA_F); 
     140    srcdata = (float *)srcp->pixels; 
     141 
     142    dst = pipi_new(w, h); 
     143    dstp = gray ? pipi_getpixels(dst, PIPI_PIXELS_Y_F) 
     144                : pipi_getpixels(dst, PIPI_PIXELS_RGBA_F); 
     145    dstdata = (float *)dstp->pixels; 
     146 
     147    acc = malloc(w * (gray ? 1 : 4) * sizeof(double)); 
     148 
     149    /* Step 1: fill the accumulator */ 
     150    for(x = 0; x < w; x++) 
     151    { 
     152        if(gray) 
     153        { 
     154            double t = 0.; 
     155 
     156            for(j = -n; j <= n; j++) 
     157            { 
     158                int j2 = (j < 0) ? h - 1 - ((-j - 1) % h) : j % h; 
     159                t += srcdata[j2 * w + x]; 
     160            } 
     161 
     162            acc[x] = t; 
     163        } 
     164        else 
     165        { 
     166            double r = 0., g = 0., b = 0., a = 0.; 
     167 
     168            for(j = -n; j <= n; j++) 
     169            { 
     170                int j2 = (j < 0) ? h - 1 - ((-j - 1) % h) : j % h; 
     171                r += srcdata[4 * (j2 * w + x)]; 
     172                g += srcdata[4 * (j2 * w + x) + 1]; 
     173                b += srcdata[4 * (j2 * w + x) + 2]; 
     174                a += srcdata[4 * (j2 * w + x) + 3]; 
     175            } 
     176 
     177            acc[4 * x] = r; 
     178            acc[4 * x + 1] = g; 
     179            acc[4 * x + 2] = b; 
     180            acc[4 * x + 3] = a; 
     181        } 
     182    } 
     183 
     184    /* Step 2: blur the image, line by line */ 
     185    for(y = 0; y < h; y++) 
     186    { 
     187        double r = 0., g = 0., b = 0., a = 0.; 
     188        double t = 0.; 
     189 
     190        /* 2.1: compute the first pixel */ 
     191        if(gray) 
     192        { 
     193            for(i = -m; i <= m; i++) 
     194            { 
     195                int i2 = (i < 0) ? w - 1 - ((-i - 1) % w) : i % w; 
     196                t += acc[i2]; 
     197            } 
     198        } 
     199        else 
     200        { 
     201            for(i = -m; i <= m; i++) 
     202            { 
     203                int i2 = (i < 0) ? w - 1 - ((-i - 1) % w) : i % w; 
     204                r += acc[4 * i2]; 
     205                g += acc[4 * i2 + 1]; 
     206                b += acc[4 * i2 + 2]; 
     207                a += acc[4 * i2 + 3]; 
     208            } 
     209        } 
     210 
     211        /* 2.2: iterate on the whole line */ 
     212        for(x = 0; x < w; x++) 
     213        { 
     214            int u, u2, v, v2; 
     215 
     216            if(gray) 
     217            { 
     218                dstdata[y * w + x] = t / size; 
     219            } 
     220            else 
     221            { 
     222                dstdata[4 * (y * w + x)] = r / size; 
     223                dstdata[4 * (y * w + x) + 1] = g / size; 
     224                dstdata[4 * (y * w + x) + 2] = b / size; 
     225                dstdata[4 * (y * w + x) + 3] = a / size; 
     226            } 
     227 
     228            u = x - m; 
     229            u2 = (u < 0) ? w - 1 - ((-u - 1) % w) : u % w; 
     230            v = x + m + 1; 
     231            v2 = (v < 0) ? w - 1 - ((-v - 1) % w) : v % w; 
     232            if(gray) 
     233            { 
     234                t = t - acc[u2] + acc[v2]; 
     235            } 
     236            else 
     237            { 
     238                r = r - acc[4 * u2] + acc[4 * v2]; 
     239                g = g - acc[4 * u2 + 1] + acc[4 * v2 + 1]; 
     240                b = b - acc[4 * u2 + 2] + acc[4 * v2 + 2]; 
     241                a = a - acc[4 * u2 + 3] + acc[4 * v2 + 3]; 
     242            } 
     243        } 
     244 
     245        /* 2.3: update the accumulator */ 
     246        for(x = 0; x < w; x++) 
     247        { 
     248            int u, u2, v, v2; 
     249 
     250            u = y - n; 
     251            u2 = (u < 0) ? w - 1 - ((-u - 1) % w) : u % w; 
     252            v = y + n + 1; 
     253            v2 = (v < 0) ? w - 1 - ((-v - 1) % w) : v % w; 
     254            if(gray) 
     255            { 
     256                acc[x] += srcdata[v2 * w + x] - srcdata[u2 * w + x]; 
     257            } 
     258            else 
     259            { 
     260                int uoff = 4 * (u2 * w + x); 
     261                int voff = 4 * (v2 * w + x); 
     262 
     263                acc[4 * x] += srcdata[voff] - srcdata[uoff]; 
     264                acc[4 * x + 1] += srcdata[voff + 1] - srcdata[uoff + 1]; 
     265                acc[4 * x + 2] += srcdata[voff + 2] - srcdata[uoff + 2]; 
     266                acc[4 * x + 3] += srcdata[voff + 3] - srcdata[uoff + 3]; 
     267            } 
     268        } 
     269    } 
     270 
     271    free(acc); 
     272 
     273    return dst; 
     274} 
     275 
Note: See TracChangeset for help on using the changeset viewer.