@Property(description = "Wind direction", editorClass = DirectionEditor.class)
private Direction direction = Direction.RIGHT;
@Override
protected void performPixelTransformation(WFImage pImg) {
SimpleImage img = (SimpleImage) pImg;
int width = pImg.getImageWidth();
int height = pImg.getImageHeight();
int contrast = 0;
short smask[][] = new short[height][width];
int rs = 2990;
int gs = 5880;
int bs = 1130;
rs = (rs * Tools.VPREC) / 10000;
gs = (gs * Tools.VPREC) / 10000;
bs = (bs * Tools.VPREC) / 10000;
Pixel p0 = new Pixel();
Pixel p1 = new Pixel();
Tools.srand123(this.seed);
/* flip the image */
if (direction == Direction.LEFT) {
srcImg = srcImg.clone();
FlipTransformer ft = new FlipTransformer();
ft.setAxis(FlipTransformer.Axis.X);
ft.transformImage(srcImg);
ft.setAxis(FlipTransformer.Axis.X);
ft.transformImage(img);
}
/** 1st line **/
for (int i = 0; i < width; i++)
smask[0][i] = 1;
/** lines 2...(height-2) **/
for (int i = 1; i < (height - 1); i++) {
/* 1st pixel */
smask[i][0] = 1;
/* process pixels 2..width-1 */
for (int j = 1; j < (width - 1); j++) {
int dd = 0, int1;
p1.setARGBValue(srcImg.getARGBValue(j - 1, i - 1));
int1 = (rs * p1.r + gs * p1.g + bs * p1.b) >> Tools.SPREC;
dd += int1;
p1.setARGBValue(srcImg.getARGBValue(j + 1, i - 1));
int1 = (rs * p1.r + gs * p1.g + bs * p1.b) >> Tools.SPREC;
dd -= int1;
p1.setARGBValue(srcImg.getARGBValue(j - 1, i));
int1 = (rs * p1.r + gs * p1.g + bs * p1.b) >> Tools.SPREC;
dd += int1;
p1.setARGBValue(srcImg.getARGBValue(j + 1, i));
int1 = (rs * p1.r + gs * p1.g + bs * p1.b) >> Tools.SPREC;
dd -= int1;
p1.setARGBValue(srcImg.getARGBValue(j - 1, i + 1));
int1 = (rs * p1.r + gs * p1.g + bs * p1.b) >> Tools.SPREC;
dd += int1;
p1.setARGBValue(srcImg.getARGBValue(j + 1, i + 1));
int1 = (rs * p1.r + gs * p1.g + bs * p1.b) >> Tools.SPREC;
dd -= int1;
if (dd < contrast) {
smask[i][j] = 1;
}
}
/* last pixel */
smask[i][width - 1] = 1;
}
/** last line **/
for (int i = 0; i < width; i++)
smask[height - 1][i] = 1;
/** accept only "thick" lines **/
for (int i = 1; i < (height - 1); i++) {
for (int j = 1; j < (width - 1); j++) {
if (smask[i][j] == 0) {
if (smask[i][j + 1] != 0)
smask[i][j] = 1;
}
}
}
/** create "thin" lines **/
for (int i = 1; i < (height - 1); i++) {
nextLine: for (int j = (width - 2); j >= 1; j--) {
if (smask[i][j] == 0) {
int k = j - 1;
while (smask[i][k] == 0) {
smask[i][k] = 1;
k--;
if (k < 1)
continue nextLine;
}
}
}
}
/** remove isolated pixels **/
for (int i = 1; i < (height - 1); i++) {
for (int j = 1; j < (width - 1); j++) {
if (smask[i][j] == 0) {
int dd = 0;
dd += smask[i][j - 1];
dd += smask[i][j + 1];
dd += smask[i - 1][j];
dd += smask[i + 1][j];
dd += smask[i + 1][j - 1];
dd += smask[i + 1][j + 1];
dd += smask[i - 1][j - 1];
dd += smask[i - 1][j + 1];
if (dd == 8)
smask[i][j] = 1;
}
}
}
/** apply the changes **/
int intensity0 = this.intensity;
int intensity1 = intensity0 / 2;
{
double rprob = (double) ((double) 1.0 - (double) this.probability / (double) 100.0);
for (int i = 0; i < height; i++) {
cont: for (int j = (width - 1); j >= 0; j--) {
if ((smask[i][j] == 0) && (Tools.drand() >= rprob)) {
if (j < 1) {
continue cont;
}
int intensity = intensity0 + (int) (Tools.drand() * intensity1 + 0.5);
double dm = 100.0 / (double) (intensity - 1);
int kmax = intensity;
if ((j + kmax) >= width)
kmax = width - j;
for (int k = 0; k < kmax; k++) {
int mix = (int) (100.0 - (double) k * dm + 0.5);
int m1 = 100 - mix;
int m2 = mix;
p0.setARGBValue(srcImg.getARGBValue(j, i));
p1.setARGBValue(srcImg.getARGBValue(j + k, i));
int rv = ((int) ((int) p1.r * m1) + (int) p0.r * m2) / (int) 100;
int gv = ((int) ((int) p1.g * m1) + (int) p0.g * m2) / (int) 100;
int bv = ((int) ((int) p1.b * m1) + (int) p0.b * m2) / (int) 100;
img.setRGB(j + k, i, rv, gv, bv);
}
}
}
}
}