diff --git a/pipi/context.c b/pipi/context.c index 3b5a807..f2fe391 100644 --- a/pipi/context.c +++ b/pipi/context.c @@ -131,6 +131,12 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) pipi_free(src); 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")) { if(ctx->nimages <= 0) diff --git a/pipi/filter/convolution.c b/pipi/filter/convolution.c index 2c4283b..c28a461 100644 --- a/pipi/filter/convolution.c +++ b/pipi/filter/convolution.c @@ -27,6 +27,12 @@ #include "pipi.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, int m, int n, double mat[]); 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 FUNC2 #undef PIXEL -#undef GRAY +#undef FLAGS #define FUNC1 conv_std_rgba_f #define FUNC2 conv_sep_rgba_f #define PIXEL float -#define GRAY 0 +#define FLAGS 0 #include "convolution_template.h" 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 FUNC2 #undef PIXEL -#undef GRAY +#undef FLAGS #define FUNC1 conv_std_y_f #define FUNC2 conv_sep_y_f #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" 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(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); + } else + { + if(src->wrap) + return wrap_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; 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 - 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(vvec); diff --git a/pipi/filter/convolution_template.h b/pipi/filter/convolution_template.h index fd1c81f..2dd6a62 100644 --- a/pipi/filter/convolution_template.h +++ b/pipi/filter/convolution_template.h @@ -18,7 +18,8 @@ * FUNC1 standard function name * FUNC2 separable function name * 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[]) @@ -31,20 +32,20 @@ static pipi_image_t *FUNC1(pipi_image_t *src, int m, int n, double mat[]) w = src->w; 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; 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; for(y = 0; y < h; y++) { for(x = 0; x < w; x++) { - if(GRAY) + if(FLAG_GRAY) { double Y = 0.; 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++) { 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++) { 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]; } @@ -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++) { 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++) { double f = mat[j * m + i]; 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]; G += f * srcdata[(y2 * w + x2) * 4 + 1]; @@ -114,22 +115,22 @@ static pipi_image_t *FUNC2(pipi_image_t *src, w = src->w; 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; 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; - 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(x = 0; x < w; x++) { - if(GRAY) + if(FLAG_GRAY) { double Y = 0.; int x2; @@ -137,8 +138,8 @@ static pipi_image_t *FUNC2(pipi_image_t *src, for(i = 0; i < m; i++) { 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]; } @@ -155,8 +156,8 @@ static pipi_image_t *FUNC2(pipi_image_t *src, double f = hvec[i]; 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]; 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++) { - if(GRAY) + if(FLAG_GRAY) { double Y = 0.; int y2; @@ -182,8 +183,8 @@ static pipi_image_t *FUNC2(pipi_image_t *src, for(j = 0; j < n; j++) { 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]; } @@ -200,8 +201,8 @@ static pipi_image_t *FUNC2(pipi_image_t *src, double f = vvec[j]; 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]; G += f * buffer[(y2 * w + x) * 4 + 1]; diff --git a/pipi/pipi.c b/pipi/pipi.c index 738dac0..cadc891 100644 --- a/pipi/pipi.c +++ b/pipi/pipi.c @@ -57,6 +57,10 @@ pipi_image_t *pipi_copy(pipi_image_t *src) { 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) { pipi_pixels_t *srcp, *dstp; diff --git a/pipi/pipi_internals.h b/pipi/pipi_internals.h index 40afdf8..4f917eb 100644 --- a/pipi/pipi_internals.h +++ b/pipi/pipi_internals.h @@ -25,6 +25,7 @@ struct pipi_image { int w, h, pitch; + int wrap; pipi_format_t codec_format, last_modified; /* List of all possible pixel formats */ diff --git a/src/pipi.c b/src/pipi.c index 434891f..6f63a66 100644 --- a/src/pipi.c +++ b/src/pipi.c @@ -41,6 +41,11 @@ int main(int argc, char *argv[]) if(pipi_command(ctx, "gray") != 0) 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")) { if(argv[1] == NULL)