/*
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.PropertyMax;
import org.jwildfire.base.PropertyMin;
import org.jwildfire.base.Tools;
import org.jwildfire.image.SimpleImage;
import org.jwildfire.image.WFImage;
import com.l2fprod.common.beans.editor.ComboBoxPropertyEditor;
public class ShiftLinesTransformer extends Mesh2DTransformer {
public enum Jitter {
ON, POSITIVE, NEGATIVE, OFF
}
public enum Axis {
X, Y
}
@Property(description = "Shift probability")
@PropertyMin(0)
@PropertyMax(100)
private int probability = 100;
@Property(description = "Seed for the random number generator")
@PropertyMin(0)
private int seed = 123;
@Property(description = "Shift amount")
private int shiftAmount = 24;
@Property(description = "Jitter amount")
private int jitterAmount = 12;
@Property(description = "Jitter effect", editorClass = JitterEditor.class)
private Jitter jitter = Jitter.ON;
@Property(description = "Shift axis", editorClass = AxisEditor.class)
private Axis axis = Axis.X;
@Override
protected void performPixelTransformation(WFImage pImg) {
SimpleImage img = (SimpleImage) pImg;
int dx = this.shiftAmount;
Tools.srand123(this.seed);
double rprob = (double) ((double) 1.0 - (double) (this.probability) / (double) 100.0);
double fdx = (double) this.jitterAmount;
if (axis == Axis.Y) {
srcImg = srcImg.clone();
TurnTransformer tT = new TurnTransformer();
tT.setAngle(TurnTransformer.Angle._90);
tT.setDirection(TurnTransformer.Direction.RIGHT);
tT.transformImage(srcImg);
tT.setAngle(TurnTransformer.Angle._90);
tT.setDirection(TurnTransformer.Direction.RIGHT);
tT.transformImage(img);
}
shiftLines: {
int width = pImg.getImageWidth();
int height = pImg.getImageHeight();
int line[] = new int[width];
if (this.jitter == Jitter.OFF) {
if (dx == 0) {
break shiftLines;
}
int adx2 = dx;
if (adx2 < 0)
adx2 = 0 - adx2;
if (adx2 >= width) {
img.fillBackground(0, 0, 0);
break shiftLines;
}
int dx2 = dx;
int sx = width - adx2;
for (int i = 0; i < height; i++) {
clearLine(line);
if (dx2 > 0) {
copyLine(line, adx2, srcImg.getLine(i), 0, sx);
}
else {
copyLine(line, 0, srcImg.getLine(i), adx2, sx);
}
img.setLine(i, line);
dx2 = 0 - dx2;
}
}
else {
for (int i = 0; i < height; i++) {
int dx3;
if ((probability >= 100) || (Tools.drand() >= rprob)) {
dx3 = (int) (Tools.drand() * fdx + 0.5);
if (this.jitter == Jitter.POSITIVE) {
if (dx3 < 0)
dx3 = 0 - dx3;
}
else if (this.jitter == Jitter.NEGATIVE) {
if (dx3 > 0)
dx3 = 0 - dx3;
}
else {
if (Tools.drand() > 0.5)
dx3 = 0 - dx3;
}
}
else
dx3 = 0;
dx3 += this.shiftAmount;
if (dx3 != 0) {
int adx2 = dx3;
if (adx2 < 0)
adx2 = 0 - adx2;
int dx2 = dx3;
int sx = width - adx2;
clearLine(line);
if (adx2 < width) {
if (dx2 > 0) {
copyLine(line, adx2, srcImg.getLine(i), 0, sx);
}
else {
copyLine(line, 0, srcImg.getLine(i), adx2, sx);
}
}
img.setLine(i, line);
}
}
}
}
if (axis == Axis.Y) {
TurnTransformer tT = new TurnTransformer();
tT.setAngle(TurnTransformer.Angle._90);
tT.setDirection(TurnTransformer.Direction.LEFT);
tT.transformImage(img);
}
}
private void clearLine(int line[]) {
for (int i = 0; i < line.length; i++)
line[i] = 0;
}
private void copyLine(int[] dst, int dstOff, int[] src, int srcOff, int size) {
for (int i = 0; i < size; i++) {
dst[i + dstOff] = src[i + srcOff];
}
}
@Override
public void initDefaultParams(WFImage pImg) {
probability = 100;
seed = 123;
shiftAmount = 24;
jitterAmount = 12;
jitter = Jitter.ON;
axis = Axis.X;
}
public static class AxisEditor extends ComboBoxPropertyEditor {
public AxisEditor() {
super();
setAvailableValues(new Axis[] { Axis.X, Axis.Y });
}
}
public static class JitterEditor extends ComboBoxPropertyEditor {
public JitterEditor() {
super();
setAvailableValues(new Jitter[] { Jitter.ON, Jitter.POSITIVE, Jitter.NEGATIVE, Jitter.OFF });
}
}
public int getProbability() {
return probability;
}
public void setProbability(int probability) {
this.probability = probability;
}
public int getSeed() {
return seed;
}
public void setSeed(int seed) {
this.seed = seed;
}
public int getShiftAmount() {
return shiftAmount;
}
public void setShiftAmount(int shiftAmount) {
this.shiftAmount = shiftAmount;
}
public int getJitterAmount() {
return jitterAmount;
}
public void setJitterAmount(int jitterAmount) {
this.jitterAmount = jitterAmount;
}
public Jitter getJitter() {
return jitter;
}
public void setJitter(Jitter jitter) {
this.jitter = jitter;
}
public Axis getAxis() {
return axis;
}
public void setAxis(Axis axis) {
this.axis = axis;
}
}