瀏覽代碼

* convolution_template.h: split convolution routines into separate functions

for each pixel format.

git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2701 92316355-f0b4-4df1-b90c-862c8a59935f
remotes/tiles
sam 16 年之前
父節點
當前提交
ec187df115
共有 3 個文件被更改,包括 263 次插入213 次删除
  1. +2
    -1
      pipi/Makefile.am
  2. +39
    -212
      pipi/filter/convolution.c
  3. +222
    -0
      pipi/filter/convolution_template.h

+ 2
- 1
pipi/Makefile.am 查看文件

@@ -41,7 +41,8 @@ codec_sources =
filter_sources = \
filter/autocontrast.c \
filter/blur.c \
filter/convolution.c
filter/convolution.c \
filter/convolution.h

dither_sources = \
dither/floydsteinberg.c \


+ 39
- 212
pipi/filter/convolution.c 查看文件

@@ -27,11 +27,35 @@
#include "pipi.h"
#include "pipi_internals.h"

static pipi_image_t *pipi_convolution_standard(pipi_image_t *src,
int m, int n, double mat[]);
static pipi_image_t *pipi_convolution_separable(pipi_image_t *src,
int m, double hvec[],
int n, double vvec[]);
static pipi_image_t *conv_std_rgba_f(pipi_image_t *src,
int m, int n, double mat[]);
static pipi_image_t *conv_sep_rgba_f(pipi_image_t *src,
int m, double hvec[],
int n, double vvec[]);
#undef FUNC1
#undef FUNC2
#undef PIXEL
#undef GRAY
#define FUNC1 conv_std_rgba_f
#define FUNC2 conv_sep_rgba_f
#define PIXEL float
#define GRAY 0
#include "convolution_template.h"

static pipi_image_t *conv_std_y_f(pipi_image_t *src,
int m, int n, double mat[]);
static pipi_image_t *conv_sep_y_f(pipi_image_t *src,
int m, double hvec[],
int n, double vvec[]);
#undef FUNC1
#undef FUNC2
#undef PIXEL
#undef GRAY
#define FUNC1 conv_std_y_f
#define FUNC2 conv_sep_y_f
#define PIXEL float
#define GRAY 1
#include "convolution_template.h"

pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[])
{
@@ -71,7 +95,12 @@ pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[])
q = mat[bestj * m + i] * mat[j * m + besti];

if(fabs(p - q) > 0.0001 * 0.0001)
return pipi_convolution_standard(src, m, n, mat);
{
if(src->last_modified == PIPI_PIXELS_Y_F)
return conv_std_y_f(src, m, n, mat);
else
return conv_std_rgba_f(src, m, n, mat);
}
}
}

@@ -85,7 +114,10 @@ pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[])
for(j = 0; j < n; j++)
vvec[j] = mat[j * m + besti] / tmp;

ret = pipi_convolution_separable(src, m, hvec, n, vvec);
if(src->last_modified == PIPI_PIXELS_Y_F)
ret = conv_sep_y_f(src, m, hvec, n, vvec);
else
ret = conv_sep_rgba_f(src, m, hvec, n, vvec);

free(hvec);
free(vvec);
@@ -93,208 +125,3 @@ pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[])
return ret;
}

static pipi_image_t *pipi_convolution_standard(pipi_image_t *src,
int m, int n, double mat[])
{
pipi_image_t *dst;
pipi_pixels_t *srcp, *dstp;
float *srcdata, *dstdata;
int x, y, i, j, w, h, gray;

w = src->w;
h = src->h;

gray = (src->last_modified == PIPI_PIXELS_Y_F);

srcp = gray ? pipi_getpixels(src, PIPI_PIXELS_Y_F)
: pipi_getpixels(src, PIPI_PIXELS_RGBA_F);
srcdata = (float *)srcp->pixels;

dst = pipi_new(w, h);
dstp = gray ? pipi_getpixels(dst, PIPI_PIXELS_Y_F)
: pipi_getpixels(dst, PIPI_PIXELS_RGBA_F);
dstdata = (float *)dstp->pixels;

for(y = 0; y < h; y++)
{
for(x = 0; x < w; x++)
{
if(gray)
{
double Y = 0.;
int x2, y2;

for(j = 0; j < n; j++)
{
y2 = y + j - n / 2;
if(y2 < 0) y2 = 0;
else if(y2 >= h) y2 = h - 1;

for(i = 0; i < m; i++)
{
x2 = x + i - m / 2;
if(x2 < 0) x2 = 0;
else if(x2 >= w) x2 = w - 1;

Y += mat[j * m + i] * srcdata[y2 * w + x2];
}
}

dstdata[y * w + x] = Y;
}
else
{
double R = 0., G = 0., B = 0.;
int x2, y2, off = 4 * (y * w + x);

for(j = 0; j < n; j++)
{
y2 = y + j - n / 2;
if(y2 < 0) y2 = 0;
else if(y2 >= h) y2 = h - 1;

for(i = 0; i < m; i++)
{
double f = mat[j * m + i];

x2 = x + i - m / 2;
if(x2 < 0) x2 = 0;
else if(x2 >= w) x2 = w - 1;

R += f * srcdata[(y2 * w + x2) * 4];
G += f * srcdata[(y2 * w + x2) * 4 + 1];
B += f * srcdata[(y2 * w + x2) * 4 + 2];
}
}

dstdata[off] = R;
dstdata[off + 1] = G;
dstdata[off + 2] = B;
}
}
}

return dst;
}

static pipi_image_t *pipi_convolution_separable(pipi_image_t *src,
int m, double hvec[],
int n, double vvec[])
{
pipi_image_t *dst;
pipi_pixels_t *srcp, *dstp;
float *srcdata, *dstdata;
double *buffer;
int x, y, i, j, w, h, gray;

w = src->w;
h = src->h;

gray = (src->last_modified == PIPI_PIXELS_Y_F);

srcp = gray ? pipi_getpixels(src, PIPI_PIXELS_Y_F)
: pipi_getpixels(src, PIPI_PIXELS_RGBA_F);
srcdata = (float *)srcp->pixels;

dst = pipi_new(w, h);
dstp = gray ? pipi_getpixels(dst, PIPI_PIXELS_Y_F)
: pipi_getpixels(dst, PIPI_PIXELS_RGBA_F);
dstdata = (float *)dstp->pixels;

buffer = malloc(w * h * (gray ? 1 : 4) * sizeof(double));

for(y = 0; y < h; y++)
{
for(x = 0; x < w; x++)
{
if(gray)
{
double Y = 0.;
int x2;

for(i = 0; i < m; i++)
{
x2 = x + i - m / 2;
if(x2 < 0) x2 = 0;
else if(x2 >= w) x2 = w - 1;

Y += hvec[i] * srcdata[y * w + x2];
}

buffer[y * w + x] = Y;
}
else
{
double R = 0., G = 0., B = 0.;
int x2, off = 4 * (y * w + x);

for(i = 0; i < m; i++)
{
double f = hvec[i];

x2 = x + i - m / 2;
if(x2 < 0) x2 = 0;
else if(x2 >= w) x2 = w - 1;

R += f * srcdata[(y * w + x2) * 4];
G += f * srcdata[(y * w + x2) * 4 + 1];
B += f * srcdata[(y * w + x2) * 4 + 2];
}

buffer[off] = R;
buffer[off + 1] = G;
buffer[off + 2] = B;
}
}
}

for(y = 0; y < h; y++)
{
for(x = 0; x < w; x++)
{
if(gray)
{
double Y = 0.;
int y2;

for(j = 0; j < n; j++)
{
y2 = y + j - n / 2;
if(y2 < 0) y2 = 0;
else if(y2 >= h) y2 = h - 1;

Y += vvec[j] * buffer[y2 * w + x];
}

dstdata[y * w + x] = Y;
}
else
{
double R = 0., G = 0., B = 0.;
int y2, off = 4 * (y * w + x);

for(j = 0; j < n; j++)
{
double f = vvec[j];

y2 = y + j - n / 2;
if(y2 < 0) y2 = 0;
else if(y2 >= h) y2 = h - 1;

R += f * buffer[(y2 * w + x) * 4];
G += f * buffer[(y2 * w + x) * 4 + 1];
B += f * buffer[(y2 * w + x) * 4 + 2];
}

dstdata[off] = R;
dstdata[off + 1] = G;
dstdata[off + 2] = B;
}
}
}

free(buffer);

return dst;
}


+ 222
- 0
pipi/filter/convolution_template.h 查看文件

@@ -0,0 +1,222 @@
/*
* libpipi Proper image processing implementation library
* Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
* All Rights Reserved
*
* $Id$
*
* This library is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://sam.zoy.org/wtfpl/COPYING for more details.
*/

/*
* convolution_template.h: convolution templates
* required macros:
* FUNC1 standard function name
* FUNC2 separable function name
* PIXEL pixel type
* GRAY 1 (grayscale) or 0 (classic RGBA)
*/

static pipi_image_t *FUNC1(pipi_image_t *src, int m, int n, double mat[])
{
pipi_image_t *dst;
pipi_pixels_t *srcp, *dstp;
PIXEL *srcdata, *dstdata;
int x, y, i, j, w, h;

w = src->w;
h = src->h;

srcp = GRAY ? pipi_getpixels(src, PIPI_PIXELS_Y_F)
: pipi_getpixels(src, PIPI_PIXELS_RGBA_F);
srcdata = (PIXEL *)srcp->pixels;

dst = pipi_new(w, h);
dstp = GRAY ? pipi_getpixels(dst, PIPI_PIXELS_Y_F)
: pipi_getpixels(dst, PIPI_PIXELS_RGBA_F);
dstdata = (PIXEL *)dstp->pixels;

for(y = 0; y < h; y++)
{
for(x = 0; x < w; x++)
{
if(GRAY)
{
double Y = 0.;
int x2, y2;

for(j = 0; j < n; j++)
{
y2 = y + j - n / 2;
if(y2 < 0) y2 = 0;
else if(y2 >= h) y2 = h - 1;

for(i = 0; i < m; i++)
{
x2 = x + i - m / 2;
if(x2 < 0) x2 = 0;
else if(x2 >= w) x2 = w - 1;

Y += mat[j * m + i] * srcdata[y2 * w + x2];
}
}

dstdata[y * w + x] = Y;
}
else
{
double R = 0., G = 0., B = 0.;
int x2, y2, off = 4 * (y * w + x);

for(j = 0; j < n; j++)
{
y2 = y + j - n / 2;
if(y2 < 0) y2 = 0;
else if(y2 >= h) y2 = h - 1;

for(i = 0; i < m; i++)
{
double f = mat[j * m + i];

x2 = x + i - m / 2;
if(x2 < 0) x2 = 0;
else if(x2 >= w) x2 = w - 1;

R += f * srcdata[(y2 * w + x2) * 4];
G += f * srcdata[(y2 * w + x2) * 4 + 1];
B += f * srcdata[(y2 * w + x2) * 4 + 2];
}
}

dstdata[off] = R;
dstdata[off + 1] = G;
dstdata[off + 2] = B;
}
}
}

return dst;
}

static pipi_image_t *FUNC2(pipi_image_t *src,
int m, double hvec[], int n, double vvec[])
{
pipi_image_t *dst;
pipi_pixels_t *srcp, *dstp;
PIXEL *srcdata, *dstdata;
double *buffer;
int x, y, i, j, w, h;

w = src->w;
h = src->h;

srcp = GRAY ? pipi_getpixels(src, PIPI_PIXELS_Y_F)
: pipi_getpixels(src, PIPI_PIXELS_RGBA_F);
srcdata = (PIXEL *)srcp->pixels;

dst = pipi_new(w, h);
dstp = GRAY ? pipi_getpixels(dst, PIPI_PIXELS_Y_F)
: pipi_getpixels(dst, PIPI_PIXELS_RGBA_F);
dstdata = (PIXEL *)dstp->pixels;

buffer = malloc(w * h * (GRAY ? 1 : 4) * sizeof(double));

for(y = 0; y < h; y++)
{
for(x = 0; x < w; x++)
{
if(GRAY)
{
double Y = 0.;
int x2;

for(i = 0; i < m; i++)
{
x2 = x + i - m / 2;
if(x2 < 0) x2 = 0;
else if(x2 >= w) x2 = w - 1;

Y += hvec[i] * srcdata[y * w + x2];
}

buffer[y * w + x] = Y;
}
else
{
double R = 0., G = 0., B = 0.;
int x2, off = 4 * (y * w + x);

for(i = 0; i < m; i++)
{
double f = hvec[i];

x2 = x + i - m / 2;
if(x2 < 0) x2 = 0;
else if(x2 >= w) x2 = w - 1;

R += f * srcdata[(y * w + x2) * 4];
G += f * srcdata[(y * w + x2) * 4 + 1];
B += f * srcdata[(y * w + x2) * 4 + 2];
}

buffer[off] = R;
buffer[off + 1] = G;
buffer[off + 2] = B;
}
}
}

for(y = 0; y < h; y++)
{
for(x = 0; x < w; x++)
{
if(GRAY)
{
double Y = 0.;
int y2;

for(j = 0; j < n; j++)
{
y2 = y + j - n / 2;
if(y2 < 0) y2 = 0;
else if(y2 >= h) y2 = h - 1;

Y += vvec[j] * buffer[y2 * w + x];
}

dstdata[y * w + x] = Y;
}
else
{
double R = 0., G = 0., B = 0.;
int y2, off = 4 * (y * w + x);

for(j = 0; j < n; j++)
{
double f = vvec[j];

y2 = y + j - n / 2;
if(y2 < 0) y2 = 0;
else if(y2 >= h) y2 = h - 1;

R += f * buffer[(y2 * w + x) * 4];
G += f * buffer[(y2 * w + x) * 4 + 1];
B += f * buffer[(y2 * w + x) * 4 + 2];
}

dstdata[off] = R;
dstdata[off + 1] = G;
dstdata[off + 2] = B;
}
}
}

free(buffer);

return dst;
}


Loading…
取消
儲存