/* CircleWaveFilter - non-solar version. * * ImageFilter waving a picture like a raindrop makes waves on water. * The image is buffered in this filter using this technique: * * ... * CircleWaveFilter // Fake filter invoking BufferFilter. * BufferFilter // Buffers image and invokes... * CircleWaveFilter // the real CircleWaveFilter performing transformation... * ... // and invokes next filter. * * See fakesection in setPixels and getFilterInstance. * * Written by Marcus Hoverby. Copyright (c) 1997 Marcus Hoverby. * You may modify and distribute this example for non-commercial * purposes. This code is provided without warranty. */ import BufferFilter; import java.awt.image.*; import java.lang.Math; /** * CircleWaveFilter waves the picture like a raindrop makes waves on water. * @author Marcus Hoverby * @version v1.0 */ public class CircleWaveFilter extends ImageFilter { private double wlen; // wavelength private double amp; // amplitude private int originx; // origin coordinates private int originy; private int width; // Picture's dimensions private int height; // private double[] radius; // precalced radius matrix private double phase=0.0; // angle in radians (0..2*PI) private boolean isfakefilter=true; // is this the real or the fake filter? /** * Constructor setting wavelength(in pixels), amplitude(=max deviation * in pixels) and wave origin coorinates. * Example: CircleWaveFilter(30.0, 5.0, 100, 100); */ public CircleWaveFilter(double wavelength, double amplitude, int x, int y, int w, int h) { wlen = wavelength / (2 * Math.PI); amp = amplitude; originx = x; originy = y; width = w; height = h; calcRadiusMatrix(); } /** * Calculates the distance(radius) from the origin pixel to each * pixel in the picture. */ private void calcRadiusMatrix() { int dx, dy, dy2; radius = new double[width * height]; for (int y=0; y < height; y++) { dy = originy - y; dy2 = dy*dy; for (int x=0; x < width; x++) { dx = originx - x; radius[y*width + x] = Math.sqrt((double)(dy2 + dx*dx)); } } } /** * Set parameter for animation (0..1) */ public void setParam(double value) { phase = (1.0 - value)*2*Math.PI; } /** * getFilterInstance - Init buffering process and create instance * of this filter. */ public ImageFilter getFilterInstance(ImageConsumer ic) { if (isfakefilter) { isfakefilter = false; // Create a BufferFilter with real CircleWave filter as consumer. // The CircleWave filter has the real consumer as consumer. consumer = (new BufferFilter()).getFilterInstance(super.getFilterInstance(ic)); isfakefilter = true; } return (super.getFilterInstance(consumer)); } /** * setPixels for images in direct format. */ public void setPixels(int x, int y, int w, int h, ColorModel cm, int[] pix, int offset, int scansize) { if (isfakefilter) { consumer.setPixels(x, y, w, h, cm, pix, offset, scansize); // fake filter return; } int index, newx, newy; double newradius, oldradius, ratio; int[] buffer = new int[w * h]; for (int yc=0; yc < h; yc++) { for (int xc=0; xc < w; xc++) { index = yc * w + xc; oldradius = radius[index]; newradius = oldradius + amp * Math.cos(oldradius / wlen + phase); //new radius ratio = newradius / oldradius; // ratio new/old radius newx = (int)((xc - originx) * ratio) + originx; newy = (int)((yc - originy) * ratio) + originy; if ((newx < 0) | (newy < 0) | (newx >= w) | (newy >= h)) { newx = xc; newy = yc; } buffer[index] = pix[newy*scansize + newx + offset]; } } consumer.setPixels(0, y, w, h, cm, buffer, 0, w); } /** * setPixels for images in indexed format. */ public void setPixels(int x, int y, int w, int h, ColorModel cm, byte[] pix, int offset, int scansize) { if (isfakefilter) { consumer.setPixels(x, y, w, h, cm, pix, offset, scansize); // fake filter return; } int index, newx, newy; double newradius, oldradius, ratio; byte[] buffer = new byte[w * h]; for (int yc=0; yc < h; yc++) { for (int xc=0; xc < w; xc++) { index = yc * w + xc; oldradius = radius[index]; newradius = oldradius + amp * Math.cos(oldradius / wlen + phase); //new radius ratio = newradius / oldradius; // ratio new/old radius newx = (int)((xc - originx) * ratio) + originx; newy = (int)((yc - originy) * ratio) + originy; if ((newx < 0) | (newy < 0) | (newx >= w) | (newy >= h)) { newx = xc; newy = yc; } buffer[index] = pix[newy*scansize + newx + offset]; } } consumer.setPixels(0, y, w, h, cm, buffer, 0, w); } } /*################# End of class CircleWaveFilter #################*/