views:

62

answers:

3

Is it possible to distort an image using trigonometric functions like sine and cosine so that it comes out wavy.

If so, how.

PHP is the preferred language but it can be any...

+2  A: 

It depends a lot on how your image works. I don't speak PHP, so this is a general solution.

If we can move individual pixels, the conceptually simplest way to do this would be to say

yold = old y-position of a pixel
ynew = new y-position of the pixel
x = x-position of the pixel
L = length of the image in pixels
N = number of trigonometric cycles to apply (ie number of sin waves)

Then we just iterate through the image. For each value of x, we move the y-pixel:

ynew = yold * (1+sin(N*π*x/L)) / 2

Spencer Nelson
+2  A: 

Yes it's possible. An image is just a two dimensional array of pixels and it's possible to reorganize them freely. One easy way is to create new image and sample pixels from original image thru some distortion function.

$original = read_image_pixels(); // using GD or some other way
for ($x = 0; $x < $width; $x++) {
  for ($y = 0; $y < $height; $y++) {
    // we are adding $height and taking modulo
    // to insure that $distorted_y is positive and less then $height.
    $distorted_y = ($y + round(10*sin($x/20)) + $height) % $height;

    $distorted[$x][$y] = $original[$x][$distorted_y];
  }
}

Edit: This can be generalized even further. Many familiar effects like blur and unsharpen are convolution filters. They are pretty well explained at the GameDev article. We can think the above sin-distortion as a convolution filter with spatially variable kernel (coefficient matrix).

phadej
Toataly WORKS, with a few edits, I'll post it soon...
Mark
+2  A: 

Using phadej's answer I got a solution...

The picture is this...

alt text

The code -

<?php
    header("Content-type: image/png");
    $im = imagecreatefrompng('pic.png');
    $newim = imagecreatetruecolor(imagesx($im),imagesy($im));
    for ($x = 0; $x < imagesx($im); $x++) {
        for ($y = 0; $y < imagesy($im); $y++) {

        $rgba = imagecolorsforindex($im, imagecolorat($im, $x, $y));
        $col = imagecolorallocate($newim, $rgba["red"], $rgba["green"], $rgba["blue"]);


        $distorted_y = ($y + round(100*sin($x/50)) + imagesy($im)) % imagesy($im);
        imagesetpixel($newim, $x, $distorted_y, $col);
        }
    }

    imagepng($newim);
    ?>

The output

alt text

Mark