diff --git a/pipi/context.c b/pipi/context.c index 068fc51..9b3996c 100644 --- a/pipi/context.c +++ b/pipi/context.c @@ -91,6 +91,7 @@ pipi_command_t const *pipi_get_command_list(void) { "overlay", 0 }, { "line", 1 }, { "sine", 1 }, + { "wave", 1 }, /* End marker */ { NULL, 0 } @@ -647,9 +648,9 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) x1, y1, x2, y2, color, aa); ctx->nimages++; } - else if(!strcmp(cmd, "sine")) + else if(!strcmp(cmd, "sine") || !strcmp(cmd, "wave")) { - pipi_image_t *tmp; + pipi_image_t *src, *dst = NULL; char const *arg; va_list ap; float dw, dh, d = 0.0, a = 0.0; @@ -666,9 +667,16 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...) if(ret < 2) return -1; - tmp = ctx->images[ctx->nimages - 1]; - ctx->images[ctx->nimages - 1] = pipi_sine(tmp, dw, dh, d, a); - pipi_free(tmp); + src = ctx->images[ctx->nimages - 1]; + switch(cmd[0]) + { + case 's': dst = pipi_sine(src, dw, dh, d, a); break; + case 'w': dst = pipi_wave(src, dw, dh, d, a); break; + } + if(dst == NULL) + return -1; + pipi_free(src); + ctx->images[ctx->nimages - 1] = dst; } else { diff --git a/pipi/filter/wave.c b/pipi/filter/wave.c index 9851f4c..5e0e400 100644 --- a/pipi/filter/wave.c +++ b/pipi/filter/wave.c @@ -28,6 +28,78 @@ #define BORDER 64 +pipi_image_t *pipi_wave(pipi_image_t *src, double dw, double dh, + double d, double a) +{ + pipi_image_t *dst; + pipi_pixels_t *srcp, *dstp; + float *srcdata, *dstdata; + double sina, cosa; + int x, y, w, h, i, gray; + + w = src->w; + h = src->h; + + gray = (src->last_modified == PIPI_PIXELS_Y_F32); + + srcp = gray ? pipi_get_pixels(src, PIPI_PIXELS_Y_F32) + : pipi_get_pixels(src, PIPI_PIXELS_RGBA_F32); + srcdata = (float *)srcp->pixels; + + dst = pipi_new(w, h); + dstp = gray ? pipi_get_pixels(dst, PIPI_PIXELS_Y_F32) + : pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32); + dstdata = (float *)dstp->pixels; + + sina = sin(a); + cosa = cos(a); + + for(y = 0; y < h; y++) + { + for(x = 0; x < w; x++) + { + double angle = 2 * M_PI / dw * ((x - w / 2) * cosa + + (y - h / 2) * sina - d); + double displacement = dh * sin(angle); + double dx, dy; + int x2, y2; + + dx = cosa * displacement; + dy = sina * displacement; + + if(x < BORDER) dx = dx * x / BORDER; + if(x > w - 1 - BORDER) dx = dx * (w - 1 - x) / BORDER; + if(y < BORDER) dy = dy * y / BORDER; + if(y > h - 1 - BORDER) dy = dy * (h - 1 - y) / BORDER; + + x2 = x + dx; + y2 = y + dy; + + /* Just in case... */ + if(x2 < 0) x2 = 0; + else if(x2 >= w) x2 = w - 1; + + if(y2 < 0) y2 = 0; + else if(y2 >= h) y2 = h - 1; + + if(gray) + { + dstdata[y * w + x] = srcdata[y2 * w + x2]; + } + else + { + for(i = 0; i < 4; i++) + { + dstdata[4 * (y * w + x) + i] + = srcdata[4 * (y2 * w + x2) + i]; + } + } + } + } + + return dst; +} + pipi_image_t *pipi_sine(pipi_image_t *src, double dw, double dh, double d, double a) { diff --git a/pipi/pipi.h b/pipi/pipi.h index f2e9f8b..16ce6f9 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -201,6 +201,8 @@ __extern pipi_image_t *pipi_dilate(pipi_image_t *); __extern pipi_image_t *pipi_erode(pipi_image_t *); __extern pipi_image_t *pipi_sine(pipi_image_t *, double, double, double, double); +__extern pipi_image_t *pipi_wave(pipi_image_t *, double, double, + double, double); __extern pipi_image_t *pipi_order(pipi_image_t *);