From 2ff222affbf27e44e985f22ae3af9f3744ccd7ef Mon Sep 17 00:00:00 2001
From: sam <sam@92316355-f0b4-4df1-b90c-862c8a59935f>
Date: Sat, 21 Feb 2009 14:26:01 +0000
Subject: [PATCH] Add a wave filter for crappy sine effects.

git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@3397 92316355-f0b4-4df1-b90c-862c8a59935f
---
 pipi/Makefile.am   |  3 +-
 pipi/context.c     | 26 ++++++++++++++
 pipi/filter/wave.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++
 pipi/pipi.h        |  2 ++
 4 files changed, 120 insertions(+), 1 deletion(-)
 create mode 100644 pipi/filter/wave.c

diff --git a/pipi/Makefile.am b/pipi/Makefile.am
index 3c277f3..444f1a1 100644
--- a/pipi/Makefile.am
+++ b/pipi/Makefile.am
@@ -72,7 +72,8 @@ filter_sources = \
 	filter/color.c \
 	filter/transform.c \
 	filter/median.c \
-	filter/dilate.c
+	filter/dilate.c \
+	filter/wave.c
 
 quantize_sources = \
 	quantize/reduce.c
diff --git a/pipi/context.c b/pipi/context.c
index a1c8e3b..efe366c 100644
--- a/pipi/context.c
+++ b/pipi/context.c
@@ -88,6 +88,7 @@ pipi_command_t const *pipi_get_command_list(void)
         { "screen", 0 },
         { "overlay", 0 },
         { "line", 1 },
+        { "wave", 1 },
 
         /* End marker */
         { NULL, 0 }
@@ -772,6 +773,31 @@ int pipi_command(pipi_context_t *ctx, char const *cmd, ...)
                        x1,  y1,  x2,  y2, color, aa);
         ctx->nimages++;
     }
+    else if(!strcmp(cmd, "wave"))
+    {
+        pipi_image_t *tmp;
+        char const *arg;
+        va_list ap;
+        float freq, phase, theta, ampx, ampy;
+        int ret;
+
+        if(ctx->nimages < 1)
+            return -1;
+
+        va_start(ap, cmd);
+        arg = va_arg(ap, char const *);
+        va_end(ap);
+
+        ret = sscanf(arg, "%g,%g,%g,%gx%g",
+                     &freq, &phase, &theta, &ampx, &ampy);
+        if(ret < 5)
+            return -1;
+
+        tmp = ctx->images[ctx->nimages - 1];
+        ctx->images[ctx->nimages - 1] = pipi_wave(tmp, freq, phase,
+                                                  theta, ampx, ampy);
+        pipi_free(tmp);
+    }
     else
     {
         return -1;
diff --git a/pipi/filter/wave.c b/pipi/filter/wave.c
new file mode 100644
index 0000000..68d069b
--- /dev/null
+++ b/pipi/filter/wave.c
@@ -0,0 +1,90 @@
+/*
+ *  libpipi       Pathetic image processing interface 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.
+ */
+
+/*
+ * wave.c: wave and warping effects
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "pipi.h"
+#include "pipi_internals.h"
+
+pipi_image_t *pipi_wave(pipi_image_t *src, double freq, double phase,
+                        double theta, double xamp, double yamp)
+{
+    pipi_image_t *dst;
+    pipi_pixels_t *srcp, *dstp;
+    float *srcdata, *dstdata;
+    double sint, cost;
+    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;
+
+    sint = sin(theta);
+    cost = cos(theta);
+
+    for(y = 0; y < h; y++)
+    {
+        for(x = 0; x < w; x++)
+        {
+            double t = cost * (x - w / 2) + sint * (y - h / 2);
+            double step = sin(t * freq + phase);
+            double dx = xamp * step;
+            double dy = yamp * step;
+
+            int x2 = x + dx;
+            int y2 = y + dy;
+
+            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;
+}
+
diff --git a/pipi/pipi.h b/pipi/pipi.h
index f44ebc1..0a8d627 100644
--- a/pipi/pipi.h
+++ b/pipi/pipi.h
@@ -197,6 +197,8 @@ __extern pipi_image_t *pipi_median(pipi_image_t *, int);
 __extern pipi_image_t *pipi_median_ext(pipi_image_t *, int, int);
 __extern pipi_image_t *pipi_dilate(pipi_image_t *);
 __extern pipi_image_t *pipi_erode(pipi_image_t *);
+__extern pipi_image_t *pipi_wave(pipi_image_t *, double, double,
+                                 double, double, double);
 
 __extern pipi_image_t *pipi_order(pipi_image_t *);