Browse Source

* convolution.c: support for wrap-around in convolutions.

* pipi.c: add the "--wrap" flag to tell libpipi that a given image wraps
    around.

git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2703 92316355-f0b4-4df1-b90c-862c8a59935f
remotes/tiles
sam 16 years ago
parent
commit
7f3e08d021
6 changed files with 98 additions and 35 deletions
  1. +6
    -0
      pipi/context.c
  2. +52
    -6
      pipi/filter/convolution.c
  3. +30
    -29
      pipi/filter/convolution_template.h
  4. +4
    -0
      pipi/pipi.c
  5. +1
    -0
      pipi/pipi_internals.h
  6. +5
    -0
      src/pipi.c

+ 6
- 0
pipi/context.c View File

@@ -131,6 +131,12 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...)
pipi_free(src); pipi_free(src);
ctx->images[ctx->nimages - 1] = dst; ctx->images[ctx->nimages - 1] = dst;
} }
else if(!strcmp(cmd, "wrap"))
{
if(ctx->nimages <= 0)
return -1;
ctx->images[ctx->nimages - 1]->wrap = 1;
}
else if(!strcmp(cmd, "gray")) else if(!strcmp(cmd, "gray"))
{ {
if(ctx->nimages <= 0) if(ctx->nimages <= 0)


+ 52
- 6
pipi/filter/convolution.c View File

@@ -27,6 +27,12 @@
#include "pipi.h" #include "pipi.h"
#include "pipi_internals.h" #include "pipi_internals.h"


#define FLAG_GRAY ((FLAGS) & SET_FLAG_GRAY)
#define FLAG_WRAP ((FLAGS) & SET_FLAG_WRAP)

#define SET_FLAG_GRAY 0x01
#define SET_FLAG_WRAP 0x02

static pipi_image_t *conv_std_rgba_f(pipi_image_t *src, static pipi_image_t *conv_std_rgba_f(pipi_image_t *src,
int m, int n, double mat[]); int m, int n, double mat[]);
static pipi_image_t *conv_sep_rgba_f(pipi_image_t *src, static pipi_image_t *conv_sep_rgba_f(pipi_image_t *src,
@@ -35,11 +41,11 @@ static pipi_image_t *conv_sep_rgba_f(pipi_image_t *src,
#undef FUNC1 #undef FUNC1
#undef FUNC2 #undef FUNC2
#undef PIXEL #undef PIXEL
#undef GRAY
#undef FLAGS
#define FUNC1 conv_std_rgba_f #define FUNC1 conv_std_rgba_f
#define FUNC2 conv_sep_rgba_f #define FUNC2 conv_sep_rgba_f
#define PIXEL float #define PIXEL float
#define GRAY 0
#define FLAGS 0
#include "convolution_template.h" #include "convolution_template.h"


static pipi_image_t *conv_std_y_f(pipi_image_t *src, static pipi_image_t *conv_std_y_f(pipi_image_t *src,
@@ -50,11 +56,41 @@ static pipi_image_t *conv_sep_y_f(pipi_image_t *src,
#undef FUNC1 #undef FUNC1
#undef FUNC2 #undef FUNC2
#undef PIXEL #undef PIXEL
#undef GRAY
#undef FLAGS
#define FUNC1 conv_std_y_f #define FUNC1 conv_std_y_f
#define FUNC2 conv_sep_y_f #define FUNC2 conv_sep_y_f
#define PIXEL float #define PIXEL float
#define GRAY 1
#define FLAGS SET_FLAG_GRAY
#include "convolution_template.h"

static pipi_image_t *wrap_std_rgba_f(pipi_image_t *src,
int m, int n, double mat[]);
static pipi_image_t *wrap_sep_rgba_f(pipi_image_t *src,
int m, double hvec[],
int n, double vvec[]);
#undef FUNC1
#undef FUNC2
#undef PIXEL
#undef FLAGS
#define FUNC1 wrap_std_rgba_f
#define FUNC2 wrap_sep_rgba_f
#define PIXEL float
#define FLAGS SET_FLAG_WRAP
#include "convolution_template.h"

static pipi_image_t *wrap_std_y_f(pipi_image_t *src,
int m, int n, double mat[]);
static pipi_image_t *wrap_sep_y_f(pipi_image_t *src,
int m, double hvec[],
int n, double vvec[]);
#undef FUNC1
#undef FUNC2
#undef PIXEL
#undef FLAGS
#define FUNC1 wrap_std_y_f
#define FUNC2 wrap_sep_y_f
#define PIXEL float
#define FLAGS SET_FLAG_GRAY|SET_FLAG_WRAP
#include "convolution_template.h" #include "convolution_template.h"


pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[]) pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[])
@@ -97,9 +133,17 @@ pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[])
if(fabs(p - q) > 0.0001 * 0.0001) if(fabs(p - q) > 0.0001 * 0.0001)
{ {
if(src->last_modified == PIPI_PIXELS_Y_F) if(src->last_modified == PIPI_PIXELS_Y_F)
{
if(src->wrap)
return wrap_std_y_f(src, m, n, mat);
return conv_std_y_f(src, m, n, mat); return conv_std_y_f(src, m, n, mat);
}
else else
{
if(src->wrap)
return wrap_std_rgba_f(src, m, n, mat);
return conv_std_rgba_f(src, m, n, mat); return conv_std_rgba_f(src, m, n, mat);
}
} }
} }
} }
@@ -115,9 +159,11 @@ pipi_image_t *pipi_convolution(pipi_image_t *src, int m, int n, double mat[])
vvec[j] = mat[j * m + besti] / tmp; vvec[j] = mat[j * m + besti] / tmp;


if(src->last_modified == PIPI_PIXELS_Y_F) if(src->last_modified == PIPI_PIXELS_Y_F)
ret = conv_sep_y_f(src, m, hvec, n, vvec);
ret = src->wrap ? wrap_sep_y_f(src, m, hvec, n, vvec)
: conv_sep_y_f(src, m, hvec, n, vvec);
else else
ret = conv_sep_rgba_f(src, m, hvec, n, vvec);
ret = src->wrap ? wrap_sep_rgba_f(src, m, hvec, n, vvec)
: conv_sep_rgba_f(src, m, hvec, n, vvec);


free(hvec); free(hvec);
free(vvec); free(vvec);


+ 30
- 29
pipi/filter/convolution_template.h View File

@@ -18,7 +18,8 @@
* FUNC1 standard function name * FUNC1 standard function name
* FUNC2 separable function name * FUNC2 separable function name
* PIXEL pixel type * PIXEL pixel type
* GRAY 1 (grayscale) or 0 (classic RGBA)
* FLAGS 1 (grayscale)
* 2 (loop)
*/ */


static pipi_image_t *FUNC1(pipi_image_t *src, int m, int n, double mat[]) static pipi_image_t *FUNC1(pipi_image_t *src, int m, int n, double mat[])
@@ -31,20 +32,20 @@ static pipi_image_t *FUNC1(pipi_image_t *src, int m, int n, double mat[])
w = src->w; w = src->w;
h = src->h; h = src->h;


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


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


for(y = 0; y < h; y++) for(y = 0; y < h; y++)
{ {
for(x = 0; x < w; x++) for(x = 0; x < w; x++)
{ {
if(GRAY)
if(FLAG_GRAY)
{ {
double Y = 0.; double Y = 0.;
int x2, y2; int x2, y2;
@@ -52,14 +53,14 @@ static pipi_image_t *FUNC1(pipi_image_t *src, int m, int n, double mat[])
for(j = 0; j < n; j++) for(j = 0; j < n; j++)
{ {
y2 = y + j - n / 2; y2 = y + j - n / 2;
if(y2 < 0) y2 = 0;
else if(y2 >= h) y2 = h - 1;
if(y2 < 0) y2 = FLAG_WRAP ? (h - 1 - (-y2 - 1) % h) : 0;
else if(y2 >= h) y2 = FLAG_WRAP ? y2 % h : h - 1;


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


Y += mat[j * m + i] * srcdata[y2 * w + x2]; Y += mat[j * m + i] * srcdata[y2 * w + x2];
} }
@@ -75,16 +76,16 @@ static pipi_image_t *FUNC1(pipi_image_t *src, int m, int n, double mat[])
for(j = 0; j < n; j++) for(j = 0; j < n; j++)
{ {
y2 = y + j - n / 2; y2 = y + j - n / 2;
if(y2 < 0) y2 = 0;
else if(y2 >= h) y2 = h - 1;
if(y2 < 0) y2 = FLAG_WRAP ? (h - 1 - (-y2 - 1) % h) : 0;
else if(y2 >= h) y2 = FLAG_WRAP ? y2 % h : h - 1;


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


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


R += f * srcdata[(y2 * w + x2) * 4]; R += f * srcdata[(y2 * w + x2) * 4];
G += f * srcdata[(y2 * w + x2) * 4 + 1]; G += f * srcdata[(y2 * w + x2) * 4 + 1];
@@ -114,22 +115,22 @@ static pipi_image_t *FUNC2(pipi_image_t *src,
w = src->w; w = src->w;
h = src->h; h = src->h;


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


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


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


for(y = 0; y < h; y++) for(y = 0; y < h; y++)
{ {
for(x = 0; x < w; x++) for(x = 0; x < w; x++)
{ {
if(GRAY)
if(FLAG_GRAY)
{ {
double Y = 0.; double Y = 0.;
int x2; int x2;
@@ -137,8 +138,8 @@ static pipi_image_t *FUNC2(pipi_image_t *src,
for(i = 0; i < m; i++) for(i = 0; i < m; i++)
{ {
x2 = x + i - m / 2; x2 = x + i - m / 2;
if(x2 < 0) x2 = 0;
else if(x2 >= w) x2 = w - 1;
if(x2 < 0) x2 = FLAG_WRAP ? (w - 1 - (-x2 - 1) % w) : 0;
else if(x2 >= w) x2 = FLAG_WRAP ? x2 % w : w - 1;


Y += hvec[i] * srcdata[y * w + x2]; Y += hvec[i] * srcdata[y * w + x2];
} }
@@ -155,8 +156,8 @@ static pipi_image_t *FUNC2(pipi_image_t *src,
double f = hvec[i]; double f = hvec[i];


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


R += f * srcdata[(y * w + x2) * 4]; R += f * srcdata[(y * w + x2) * 4];
G += f * srcdata[(y * w + x2) * 4 + 1]; G += f * srcdata[(y * w + x2) * 4 + 1];
@@ -174,7 +175,7 @@ static pipi_image_t *FUNC2(pipi_image_t *src,
{ {
for(x = 0; x < w; x++) for(x = 0; x < w; x++)
{ {
if(GRAY)
if(FLAG_GRAY)
{ {
double Y = 0.; double Y = 0.;
int y2; int y2;
@@ -182,8 +183,8 @@ static pipi_image_t *FUNC2(pipi_image_t *src,
for(j = 0; j < n; j++) for(j = 0; j < n; j++)
{ {
y2 = y + j - n / 2; y2 = y + j - n / 2;
if(y2 < 0) y2 = 0;
else if(y2 >= h) y2 = h - 1;
if(y2 < 0) y2 = FLAG_WRAP ? (h - 1 - (-y2 - 1) % h) : 0;
else if(y2 >= h) y2 = FLAG_WRAP ? y2 % h : h - 1;


Y += vvec[j] * buffer[y2 * w + x]; Y += vvec[j] * buffer[y2 * w + x];
} }
@@ -200,8 +201,8 @@ static pipi_image_t *FUNC2(pipi_image_t *src,
double f = vvec[j]; double f = vvec[j];


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


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


+ 4
- 0
pipi/pipi.c View File

@@ -57,6 +57,10 @@ pipi_image_t *pipi_copy(pipi_image_t *src)
{ {
pipi_image_t *dst = pipi_new(src->w, src->h); pipi_image_t *dst = pipi_new(src->w, src->h);


/* Copy properties */
dst->wrap = src->wrap;

/* Copy pixels, if any */
if(src->last_modified != PIPI_PIXELS_UNINITIALISED) if(src->last_modified != PIPI_PIXELS_UNINITIALISED)
{ {
pipi_pixels_t *srcp, *dstp; pipi_pixels_t *srcp, *dstp;


+ 1
- 0
pipi/pipi_internals.h View File

@@ -25,6 +25,7 @@
struct pipi_image struct pipi_image
{ {
int w, h, pitch; int w, h, pitch;
int wrap;
pipi_format_t codec_format, last_modified; pipi_format_t codec_format, last_modified;


/* List of all possible pixel formats */ /* List of all possible pixel formats */


+ 5
- 0
src/pipi.c View File

@@ -41,6 +41,11 @@ int main(int argc, char *argv[])
if(pipi_command(ctx, "gray") != 0) if(pipi_command(ctx, "gray") != 0)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
else if(!strcmp(argv[0], "--wrap"))
{
if(pipi_command(ctx, "wrap") != 0)
return EXIT_FAILURE;
}
else if(!strcmp(argv[0], "--output") || !strcmp(argv[0], "-o")) else if(!strcmp(argv[0], "--output") || !strcmp(argv[0], "-o"))
{ {
if(argv[1] == NULL) if(argv[1] == NULL)


Loading…
Cancel
Save