Package org.jwildfire.transform

Source Code of org.jwildfire.transform.WaveTransformer$AxisEditor

/*
  JWildfire - an image and animation processor written in Java
  Copyright (C) 1995-2011 Andreas Maschke

  This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
  General Public License as published by the Free Software Foundation; either version 2.1 of the
  License, or (at your option) any later version.
  This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License along with this software;
  if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jwildfire.transform;

import org.jwildfire.base.Property;
import org.jwildfire.base.PropertyCategory;
import org.jwildfire.base.PropertyMax;
import org.jwildfire.base.PropertyMin;
import org.jwildfire.base.Tools;
import org.jwildfire.image.Pixel;
import org.jwildfire.image.SimpleImage;
import org.jwildfire.image.WFImage;

import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor;

public class WaveTransformer extends Mesh2DTransformer {

  public enum Axis {
    X, Y
  };

  @Property(description = "X-coordinate of the wave origin")
  private double centreX = 0.0;

  @Property(description = "Y-coordinate of the wave origin")
  private double centreY = 0.0;

  @Property(description = "Propagation axis of the wave", editorClass = AxisEditor.class)
  private Axis axis = Axis.X;

  @Property(description = "Number of frames to describe a complete phase", category = PropertyCategory.SECONDARY)
  @PropertyMin(1)
  private int frames = 60;

  @Property(description = "Current frames", category = PropertyCategory.SECONDARY)
  @PropertyMin(1)
  private int frame = 33;

  @Property(category = PropertyCategory.SECONDARY, description = "Global zoom factor for the whole image")
  @PropertyMin(0.01)
  @PropertyMax(100.0)
  private double zoom = 1.0;

  @Property(description = "Damping of the wave", category = PropertyCategory.SECONDARY)
  private double damping = -0.5;

  @Property(description = "Amplitude of the wave")
  @PropertyMin(0.0)
  private double amplitude = 30.0;

  @Property(description = "Wavelength of the wave")
  @PropertyMin(0.0)
  private double wavelength = 150.0;

  @Property(description = "Phase shift of the Wave", category = PropertyCategory.SECONDARY)
  private double phase = 0.0;

  // TODO unklar: was genau macht dieser Parameter?
  // @Property()
  private double shift = 0.0;

  @Property(description = "Damping on/off", category = PropertyCategory.SECONDARY)
  private boolean damp = true;

  @Property(description = "Repeat the image at the borders")
  private boolean wrap = true;

  @Override
  protected void performPixelTransformation(WFImage pImg) {
    SimpleImage img = (SimpleImage) pImg;
    if (!damp) {
      if (axis == Axis.X)
        waveX(img);
      else
        waveY(img);
    }
    else {
      if (axis == Axis.X)
        waveX_damp(img);
      else
        waveY_damp(img);
    }
  }

  private void waveY_damp(SimpleImage pImg) {
    double damping = this.damping;
    double cx = this.centreX - 0.5;
    double cy = this.centreY - 0.5;
    double zoom = 1.0 / this.zoom;
    int width = pImg.getImageWidth();
    int height = pImg.getImageHeight();
    double PI2 = 2.0 * Math.PI;
    double shift = this.shift;
    double wavelength = this.wavelength * this.zoom;
    double amplitude = 0.0 - this.amplitude * this.zoom;
    double phase = this.phase;
    double amp = amplitude;
    double t = this.frames != 0 ? (double) this.frame / (double) this.frames : 0.0;
    shift = 2.0 * shift / (double) (width - 1);
    double w1 = (double) width - 1.0;
    double h1 = (double) height - 1.0;

    Pixel pPixel = new Pixel();
    for (int pY = 0; pY < height; pY++) {
      for (int pX = 0; pX < width; pX++) {
        pPixel.setARGBValue(pImg.getARGBValue(pX, pY));

        double x0 = (double) pX - cx;
        double y0 = (double) pY - cy;
        double sangle = shift * pX;
        double dl = (y0 - sangle) / wavelength;

        double dl2 = dl - sangle;
        if (dl2 < 0)
          dl2 = 0.0 - dl2;
        amp = amplitude * Math.exp(dl2 * damping);

        double zz = amp * Math.sin((PI2 * (t - dl)) + phase);
        x0 += zz;
        double x = x0 * zoom + cx;
        double y = y0 * zoom + cy;

        /* color-wrapping */
        if (this.wrap) {
          while (x >= ((double) width - 0.5))
            x -= (double) (width - 1);
          while ((int) x < 0.5)
            x += (double) (width - 1);
          while (y >= ((double) height - 0.5))
            y -= (double) (height - 1);
          while ((int) y < 0.5)
            y += (double) (height - 1);
        }
        /* render it */
        double xi = Tools.fmod33(x);
        double yi = Tools.fmod33(y);
        if ((x < 0.0) || (x > w1) || (y < 0.0) || (y > h1)) {
          pPixel.r = pPixel.g = pPixel.b = 0;
        }
        else {
          readSrcPixels(x, y);
          pPixel.r = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.r) + xi * (srcQ.r)) + yi
              * ((1.0 - xi) * (srcR.r) + xi * (srcS.r))));
          pPixel.g = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.g) + xi * (srcQ.g)) + yi
              * ((1.0 - xi) * (srcR.g) + xi * (srcS.g))));
          pPixel.b = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.b) + xi * (srcQ.b)) + yi
              * ((1.0 - xi) * (srcR.b) + xi * (srcS.b))));
        }
        pImg.setRGB(pX, pY, pPixel.r, pPixel.g, pPixel.b);
      }
    }
  }

  private void waveX_damp(SimpleImage pImg) {
    double damping = this.damping;
    double cx = this.centreX - 0.5;
    double cy = this.centreY - 0.5;
    double zoom = 1.0 / this.zoom;
    int width = pImg.getImageWidth();
    int height = pImg.getImageHeight();
    double PI2 = 2.0 * Math.PI;
    double shift = this.shift;
    double wavelength = this.wavelength * this.zoom;
    double amplitude = 0.0 - this.amplitude * this.zoom;
    double phase = this.phase;
    double amp = amplitude;
    double t = this.frames != 0 ? (double) this.frame / (double) this.frames : 0.0;
    shift = 2.0 * shift / (double) (height - 1);
    double w1 = (double) width - 1.0;
    double h1 = (double) height - 1.0;

    Pixel pPixel = new Pixel();
    for (int pY = 0; pY < height; pY++) {
      for (int pX = 0; pX < width; pX++) {
        pPixel.setARGBValue(pImg.getARGBValue(pX, pY));
        /* transform the point */
        double x0 = (double) pX - cx;
        double y0 = (double) pY - cy;
        double sangle = shift * pY;
        double dl = (x0 - sangle) / wavelength;

        double dl2 = dl - sangle;
        if (dl2 < 0)
          dl2 = 0.0 - dl2;
        amp = amplitude * Math.exp(dl2 * damping);

        double zz = amp * Math.sin((PI2 * (t - dl)) + phase);
        y0 += zz;
        double x = x0 * zoom + cx;
        double y = y0 * zoom + cy;

        /* color-wrapping */
        if (this.wrap) {
          while (x >= ((double) width - 0.5))
            x -= (double) (width - 1);
          while ((int) x < 0.5)
            x += (double) (width - 1);
          while (y >= ((double) height - 0.5))
            y -= (double) (height - 1);
          while ((int) y < 0.5)
            y += (double) (height - 1);
        }
        /* render it */
        double xi = Tools.fmod33(x);
        double yi = Tools.fmod33(y);
        if ((x < 0.0) || (x > w1) || (y < 0.0) || (y > h1)) {
          pPixel.r = pPixel.g = pPixel.b = 0;
        }
        else {
          readSrcPixels(x, y);
          pPixel.r = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.r) + xi * (srcQ.r)) + yi
              * ((1.0 - xi) * (srcR.r) + xi * (srcS.r))));
          pPixel.g = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.g) + xi * (srcQ.g)) + yi
              * ((1.0 - xi) * (srcR.g) + xi * (srcS.g))));
          pPixel.b = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.b) + xi * (srcQ.b)) + yi
              * ((1.0 - xi) * (srcR.b) + xi * (srcS.b))));
        }
        pImg.setRGB(pX, pY, pPixel.r, pPixel.g, pPixel.b);
      }
    }
  }

  private void waveY(SimpleImage pImg) {
    double cx = this.centreX - 0.5;
    double cy = this.centreY - 0.5;
    double zoom = 1.0 / this.zoom;
    int width = pImg.getImageWidth();
    int height = pImg.getImageHeight();
    double PI2 = 2.0 * Math.PI;
    double shift = this.shift;
    double wavelength = this.wavelength * this.zoom;
    double amplitude = 0.0 - this.amplitude * this.zoom;
    double phase = this.phase;
    shift = 2.0 * shift / (double) (width - 1);
    double amp = amplitude;
    double t = this.frames != 0 ? (double) this.frame / (double) this.frames : 0.0;
    double w1 = (double) width - 1.0;
    double h1 = (double) height - 1.0;
    Pixel pPixel = new Pixel();
    for (int pY = 0; pY < height; pY++) {
      for (int pX = 0; pX < width; pX++) {
        pPixel.setARGBValue(pImg.getARGBValue(pX, pY));
        /* transform the point */
        double x0 = (double) pX - cx;
        double y0 = (double) pY - cy;
        double dl = (y0 - shift * pX) / wavelength;
        double zz = amp * Math.sin((PI2 * (t - dl)) + phase);
        x0 += zz;
        double x = x0 * zoom + cx;
        double y = y0 * zoom + cy;

        /* color-wrapping */
        if (this.wrap) {
          while (x >= ((double) width - 0.5))
            x -= (double) (width - 1);
          while ((int) x < 0.5)
            x += (double) (width - 1);
          while (y >= ((double) height - 0.5))
            y -= (double) (height - 1);
          while ((int) y < 0.5)
            y += (double) (height - 1);
        }
        /* render it */
        double xi = Tools.fmod33(x);
        double yi = Tools.fmod33(y);
        if ((x < 0.0) || (x > w1) || (y < 0.0) || (y > h1)) {
          pPixel.r = pPixel.g = pPixel.b = 0;
        }
        else {
          readSrcPixels(x, y);
          pPixel.r = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.r) + xi * (srcQ.r)) + yi
              * ((1.0 - xi) * (srcR.r) + xi * (srcS.r))));
          pPixel.g = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.g) + xi * (srcQ.g)) + yi
              * ((1.0 - xi) * (srcR.g) + xi * (srcS.g))));
          pPixel.b = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.b) + xi * (srcQ.b)) + yi
              * ((1.0 - xi) * (srcR.b) + xi * (srcS.b))));
        }
        pImg.setRGB(pX, pY, pPixel.r, pPixel.g, pPixel.b);
      }
    }
  }

  private void waveX(SimpleImage pImg) {
    double cx = this.centreX - 0.5;
    double cy = this.centreY - 0.5;
    double zoom = 1.0 / this.zoom;
    int width = pImg.getImageWidth();
    int height = pImg.getImageHeight();
    double PI2 = 2.0 * Math.PI;
    double shift = this.shift;
    double wavelength = this.wavelength * this.zoom;
    double amplitude = 0.0 - this.amplitude * this.zoom;
    double phase = this.phase;
    shift = 2.0 * shift / (double) (height - 1);
    double amp = amplitude;
    double t = this.frames != 0 ? (double) this.frame / (double) this.frames : 0.0;
    double w1 = (double) width - 1.0;
    double h1 = (double) height - 1.0;
    Pixel pPixel = new Pixel();
    for (int pY = 0; pY < height; pY++) {
      for (int pX = 0; pX < width; pX++) {
        pPixel.setARGBValue(pImg.getARGBValue(pX, pY));
        /* transform the point */
        double x0 = (double) pX - cx;
        double y0 = (double) pY - cy;
        double dl = (x0 - shift * pY) / wavelength;
        double zz = amp * Math.sin((PI2 * (t - dl)) + phase);
        y0 += zz;
        double x = x0 * zoom + cx;
        double y = y0 * zoom + cy;
        /* color-wrapping */
        if (this.wrap) {
          while (x >= ((double) width - 0.5))
            x -= (double) (width - 1);
          while ((int) x < 0.5)
            x += (double) (width - 1);
          while (y >= ((double) height - 0.5))
            y -= (double) (height - 1);
          while ((int) y < 0.5)
            y += (double) (height - 1);
        }
        /* render it */
        double xi = Tools.fmod33(x);
        double yi = Tools.fmod33(y);
        if ((x < 0.0) || (x > w1) || (y < 0.0) || (y > h1)) {
          pPixel.r = pPixel.g = pPixel.b = 0;
        }
        else {
          readSrcPixels(x, y);
          pPixel.r = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.r) + xi * (srcQ.r)) + yi
              * ((1.0 - xi) * (srcR.r) + xi * (srcS.r))));
          pPixel.g = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.g) + xi * (srcQ.g)) + yi
              * ((1.0 - xi) * (srcR.g) + xi * (srcS.g))));
          pPixel.b = roundColor(((1.0 - yi) * ((1.0 - xi) * (srcP.b) + xi * (srcQ.b)) + yi
              * ((1.0 - xi) * (srcR.b) + xi * (srcS.b))));
        }
        pImg.setRGB(pX, pY, pPixel.r, pPixel.g, pPixel.b);
      }
    }
  }

  @Override
  protected void cleanupTransformation(WFImage pImg) {
    super.cleanupTransformation(pImg);
    applySmoothing((SimpleImage) pImg, 1);
  }

  @Override
  public void initDefaultParams(WFImage pImg) {
    int width = pImg.getImageWidth();
    int height = pImg.getImageHeight();
    double rr = Math.sqrt(width * width + height * height);
    centreX = 0.10;
    centreY = -0.50;
    axis = Axis.X;
    frames = 60;
    frame = 33;
    zoom = 1.0;
    damping = -0.5;
    amplitude = Math.round(rr / 20.0);
    wavelength = Math.round(rr / 4.0);
    phase = 0.0;
    shift = 0.0;
    damp = true;
    wrap = true;
  }

  public double getCentreX() {
    return centreX;
  }

  public void setCentreX(double centreX) {
    this.centreX = centreX;
  }

  public double getCentreY() {
    return centreY;
  }

  public void setCentreY(double centreY) {
    this.centreY = centreY;
  }

  public Axis getAxis() {
    return axis;
  }

  public void setAxis(Axis axis) {
    this.axis = axis;
  }

  public int getFrames() {
    return frames;
  }

  public void setFrames(int frames) {
    this.frames = frames;
  }

  public int getFrame() {
    return frame;
  }

  public void setFrame(int frame) {
    this.frame = frame;
  }

  public double getZoom() {
    return zoom;
  }

  public void setZoom(double zoom) {
    this.zoom = zoom;
  }

  public double getDamping() {
    return damping;
  }

  public void setDamping(double damping) {
    this.damping = damping;
  }

  public double getAmplitude() {
    return amplitude;
  }

  public void setAmplitude(double amplitude) {
    this.amplitude = amplitude;
  }

  public double getWavelength() {
    return wavelength;
  }

  public void setWavelength(double wavelength) {
    this.wavelength = wavelength;
  }

  public double getPhase() {
    return phase;
  }

  public void setPhase(double phase) {
    this.phase = phase;
  }

  public double getShift() {
    return shift;
  }

  public void setShift(double shift) {
    this.shift = shift;
  }

  public boolean isDamp() {
    return damp;
  }

  public void setDamp(boolean damp) {
    this.damp = damp;
  }

  public boolean isWrap() {
    return wrap;
  }

  public void setWrap(boolean wrap) {
    this.wrap = wrap;
  }

  public static class AxisEditor extends ComboBoxPropertyEditor {
    public AxisEditor() {
      super();
      setAvailableValues(new Axis[] { Axis.X, Axis.Y });
    }
  }
}
TOP

Related Classes of org.jwildfire.transform.WaveTransformer$AxisEditor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.