source: libpipi/trunk/pipi/filter/wave.c @ 3418

Last change on this file since 3418 was 3418, checked in by sam, 5 years ago

wave.c: implement pipi_wave() in addition to pipi_sine(). The effect is
not yet satisfying.

File size: 4.5 KB
Line 
1/*
2 *  libpipi       Pathetic image processing interface library
3 *  Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id$
7 *
8 *  This library is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 * wave.c: wave and other warping effects
17 */
18
19#include "config.h"
20
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <math.h>
25
26#include "pipi.h"
27#include "pipi_internals.h"
28
29#define BORDER 64
30
31pipi_image_t *pipi_wave(pipi_image_t *src, double dw, double dh,
32                        double d, double a)
33{
34    pipi_image_t *dst;
35    pipi_pixels_t *srcp, *dstp;
36    float *srcdata, *dstdata;
37    double sina, cosa;
38    int x, y, w, h, i, gray;
39
40    w = src->w;
41    h = src->h;
42
43    gray = (src->last_modified == PIPI_PIXELS_Y_F32);
44
45    srcp = gray ? pipi_get_pixels(src, PIPI_PIXELS_Y_F32)
46                : pipi_get_pixels(src, PIPI_PIXELS_RGBA_F32);
47    srcdata = (float *)srcp->pixels;
48
49    dst = pipi_new(w, h);
50    dstp = gray ? pipi_get_pixels(dst, PIPI_PIXELS_Y_F32)
51                : pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32);
52    dstdata = (float *)dstp->pixels;
53
54    sina = sin(a);
55    cosa = cos(a);
56
57    for(y = 0; y < h; y++)
58    {
59        for(x = 0; x < w; x++)
60        {
61            double angle = 2 * M_PI / dw * ((x - w / 2) * cosa
62                                             + (y - h / 2) * sina - d);
63            double displacement = dh * sin(angle);
64            double dx, dy;
65            int x2, y2;
66
67            dx = cosa * displacement;
68            dy = sina * displacement;
69
70            if(x < BORDER) dx = dx * x / BORDER;
71            if(x > w - 1 - BORDER) dx = dx * (w - 1 - x) / BORDER;
72            if(y < BORDER) dy = dy * y / BORDER;
73            if(y > h - 1 - BORDER) dy = dy * (h - 1 - y) / BORDER;
74
75            x2 = x + dx;
76            y2 = y + dy;
77
78            /* Just in case... */
79            if(x2 < 0) x2 = 0;
80            else if(x2 >= w) x2 = w - 1;
81
82            if(y2 < 0) y2 = 0;
83            else if(y2 >= h) y2 = h - 1;
84
85            if(gray)
86            {
87                dstdata[y * w + x] = srcdata[y2 * w + x2];
88            }
89            else
90            {
91                for(i = 0; i < 4; i++)
92                {
93                    dstdata[4 * (y * w + x) + i]
94                        = srcdata[4 * (y2 * w + x2) + i];
95                }
96            }
97        }
98    }
99
100    return dst;
101}
102
103pipi_image_t *pipi_sine(pipi_image_t *src, double dw, double dh,
104                        double d, double a)
105{
106    pipi_image_t *dst;
107    pipi_pixels_t *srcp, *dstp;
108    float *srcdata, *dstdata;
109    double sina, cosa;
110    int x, y, w, h, i, gray;
111
112    w = src->w;
113    h = src->h;
114
115    gray = (src->last_modified == PIPI_PIXELS_Y_F32);
116
117    srcp = gray ? pipi_get_pixels(src, PIPI_PIXELS_Y_F32)
118                : pipi_get_pixels(src, PIPI_PIXELS_RGBA_F32);
119    srcdata = (float *)srcp->pixels;
120
121    dst = pipi_new(w, h);
122    dstp = gray ? pipi_get_pixels(dst, PIPI_PIXELS_Y_F32)
123                : pipi_get_pixels(dst, PIPI_PIXELS_RGBA_F32);
124    dstdata = (float *)dstp->pixels;
125
126    sina = sin(a);
127    cosa = cos(a);
128
129    for(y = 0; y < h; y++)
130    {
131        for(x = 0; x < w; x++)
132        {
133            double angle = 2 * M_PI / dw * ((x - w / 2) * cosa
134                                             + (y - h / 2) * sina - d);
135            double displacement = dh * sin(angle);
136            double dx, dy;
137            int x2, y2;
138
139            dx = -sina * displacement;
140            dy = cosa * displacement;
141
142            if(x < BORDER) dx = dx * x / BORDER;
143            if(x > w - 1 - BORDER) dx = dx * (w - 1 - x) / BORDER;
144            if(y < BORDER) dy = dy * y / BORDER;
145            if(y > h - 1 - BORDER) dy = dy * (h - 1 - y) / BORDER;
146
147            x2 = x + dx;
148            y2 = y + dy;
149
150            /* Just in case... */
151            if(x2 < 0) x2 = 0;
152            else if(x2 >= w) x2 = w - 1;
153
154            if(y2 < 0) y2 = 0;
155            else if(y2 >= h) y2 = h - 1;
156
157            if(gray)
158            {
159                dstdata[y * w + x] = srcdata[y2 * w + x2];
160            }
161            else
162            {
163                for(i = 0; i < 4; i++)
164                {
165                    dstdata[4 * (y * w + x) + i]
166                        = srcdata[4 * (y2 * w + x2) + i];
167                }
168            }
169        }
170    }
171
172    return dst;
173}
174
Note: See TracBrowser for help on using the repository browser.