Package org.jwildfire.transform

Source Code of org.jwildfire.transform.ErodeTransformer$ShapeEditor

/*
  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 java.awt.Color;
import java.awt.Graphics;

import org.jwildfire.base.Property;
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 ErodeTransformer extends Mesh2DTransformer {
  public enum Mode {
    ERODE, DILATE, OILTRANSFER, NEON
  };

  public enum Shape {
    SQUARE, DIAMOND, DISK, PLUS, X, RANDOM
  }

  @Property(editorClass = ModeEditor.class, description = "ERODE (shrink), DILATE (grow) or OILTRANSFER (most popular color) mode")
  private Mode mode;

  @Property(editorClass = ShapeEditor.class, description = "Shape of the area to compute the darkest/brightest color")
  private Shape shape;

  @Property(description = "Size of the shape to compute the darkest/brightest color")
  private int size;

  @Property(description = "Seed for the random number generator")
  @PropertyMin(0)
  private int seed;

  @Override
  protected void performPixelTransformation(WFImage pImg) {
    if (this.size <= 1)
      return;
    SimpleImage img = (SimpleImage) pImg;
    Tools.srand123(this.seed);
    int width = pImg.getImageWidth();
    int height = pImg.getImageHeight();
    short[][] shape;
    switch (this.shape) {
      case DIAMOND:
        shape = generateDiamond(this.size);
        break;
      case DISK:
        shape = generateDisk(this.size);
        break;
      case SQUARE:
        shape = generateSquare(this.size);
        break;
      case PLUS:
        shape = generatePlus(this.size);
        break;
      case X:
        shape = generateX(this.size);
        break;
      default:
        shape = generateRandom(this.size);
        break;
    }

    SimpleImage srcGreyImg = null;
    if ((this.mode == Mode.DILATE) || (this.mode == Mode.ERODE) || (this.mode == Mode.NEON)) {
      srcGreyImg = srcImg.clone();
      ColorToGrayTransformer cT = new ColorToGrayTransformer();
      cT.setWeights(ColorToGrayTransformer.Weights.LUMINANCE);
      cT.transformImage(srcGreyImg);
    }

    switch (mode) {
      case ERODE:
        for (int i = 0; i < height; i++) {
          for (int j = 0; j < width; j++) {
            int lumMin = srcGreyImg.getRValue(j, i);
            int xLumMin = j;
            int yLumMin = i;
            for (int s = 0; s < shape.length; s++) {
              int x = j + shape[s][0];
              int y = i + shape[s][1];
              if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
                int lum = srcGreyImg.getRValue(x, y);
                if (lum < lumMin) {
                  lumMin = lum;
                  xLumMin = x;
                  yLumMin = y;
                }
              }
            }
            img.setARGB(j, i, srcImg.getARGBValue(xLumMin, yLumMin));
          }
        }
        break;
      case DILATE:
        for (int i = 0; i < height; i++) {
          for (int j = 0; j < width; j++) {
            int lumMax = srcGreyImg.getRValue(j, i);
            int xLumMax = j;
            int yLumMax = i;
            for (int s = 0; s < shape.length; s++) {
              int x = j + shape[s][0];
              int y = i + shape[s][1];
              if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
                int lum = srcGreyImg.getRValue(x, y);
                if (lum > lumMax) {
                  lumMax = lum;
                  xLumMax = x;
                  yLumMax = y;
                }
              }
            }
            img.setARGB(j, i, srcImg.getARGBValue(xLumMax, yLumMax));
          }
        }
        break;
      case NEON:
        Pixel srcPixel = new Pixel();
        Pixel currPixel = new Pixel();
        for (int i = 0; i < height; i++) {
          for (int j = 0; j < width; j++) {
            int lumMax = srcGreyImg.getRValue(j, i);
            int lum0 = lumMax;
            int xLumMax = j;
            int yLumMax = i;
            for (int s = 0; s < shape.length; s++) {
              int x = j + shape[s][0];
              int y = i + shape[s][1];
              if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
                int lum = srcGreyImg.getRValue(x, y);
                if (lum > lumMax) {
                  lumMax = lum;
                  xLumMax = x;
                  yLumMax = y;
                }
              }
            }
            int m1 = 30;
            int m2 = 100 - m1;
            srcPixel.setARGBValue(srcImg.getARGBValue(xLumMax, yLumMax));
            currPixel.setARGBValue(srcImg.getARGBValue(j, i));
            currPixel.r = (srcPixel.r * m1 + currPixel.r * m2) / 100;
            currPixel.g = (srcPixel.g * m1 + currPixel.g * m2) / 100;
            currPixel.b = (srcPixel.b * m1 + currPixel.b * m2) / 100;
            if (Math.abs(lum0 - lumMax) > 50)
              img.setRGB(j, i, 0, 128, 0);
            //pImg.setARGB(j, i, srcImg.getARGBValue(xLumMax, yLumMax));
          }
        }
        break;
      case OILTRANSFER:
        int[] colorValues = new int[shape.length];
        short[] colorUsed = new short[shape.length];
        for (int i = 0; i < height; i++) {
          for (int j = 0; j < width; j++) {
            int cCount = 0;
            for (int s = 0; s < colorUsed.length; s++)
              colorUsed[s] = 0;
            for (int s = 0; s < shape.length; s++) {
              int x = j + shape[s][0];
              int y = i + shape[s][1];
              if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
                int color = srcImg.getARGBValue(x, y);
                boolean found = false;
                for (short t = 0; t < cCount; t++) {
                  if (colorValues[t] == color) {
                    colorUsed[t]++;
                    found = true;
                    break;
                  }
                }
                if (!found) {
                  colorValues[cCount] = color;
                  colorUsed[cCount++] = 1;
                }
              }
            }
            int color = srcImg.getARGBValue(j, i);
            int usedMax = 1;
            for (int t = 0; t < cCount; t++) {
              if (colorUsed[t] > usedMax) {
                usedMax = colorUsed[t];
                color = colorValues[t];
              }
            }
            img.setARGB(j, i, color);
          }
        }
        break;
    }
  }

  @Override
  public void initDefaultParams(WFImage pImg) {
    mode = Mode.ERODE;
    shape = Shape.DISK;
    size = 5;
  }

  public Mode getMode() {
    return mode;
  }

  public void setMode(Mode mode) {
    this.mode = mode;
  }

  public static class ModeEditor extends ComboBoxPropertyEditor {
    public ModeEditor() {
      super();
      setAvailableValues(new Mode[] { Mode.ERODE, Mode.DILATE, Mode.OILTRANSFER /*, Mode.NEON */});
    }
  }

  public static class ShapeEditor extends ComboBoxPropertyEditor {
    public ShapeEditor() {
      super();
      setAvailableValues(new Shape[] { Shape.DISK, Shape.SQUARE, Shape.DIAMOND, Shape.PLUS,
          Shape.X, Shape.RANDOM });
    }
  }

  public Shape getShape() {
    return shape;
  }

  public void setShape(Shape shape) {
    this.shape = shape;
  }

  public int getSize() {
    return size;
  }

  public void setSize(int size) {
    this.size = size;
  }

  public int getSeed() {
    return seed;
  }

  public void setSeed(int seed) {
    this.seed = seed;
  }

  // xxx {-1,-1} { 0,-1} { 1,-1}
  // xxx {-1, 0} { 0, 0} { 1, 0}
  // xxx {-1, 1} { 0, 1} { 1, 1}
  private short[][] generateSquare(int pSize) {
    short s = (short) pSize;
    if ((s < 3) || (s % 2 == 0))
      throw new IllegalArgumentException(String.valueOf(pSize));
    short s2 = (short) (s / 2);
    short[][] res = new short[s * s][2];
    int idx = 0;
    for (short i = 0; i < s; i++) {
      for (short j = 0; j < s; j++) {
        res[idx][0] = (short) (j - s2);
        res[idx++][1] = (short) (i - s2);
      }
    }
    return res;
  }

  //    x                   { 0,-2}
  //   xxx          {-1,-1} { 0,-1} { 1,-1}
  //  xxxxx {-2, 0} {-1, 0} { 0, 0} { 1, 0} { 2, 0}
  //   xxx          {-1, 1} { 0, 1} { 1, 1}
  //    x                   { 0, 2}
  private short[][] generateDiamond(int pSize) {
    short s = (short) pSize;
    if ((s < 3) || (s % 2 == 0))
      throw new IllegalArgumentException(String.valueOf(pSize));
    short s2 = (short) (s / 2);
    int cnt = s;
    for (short i = 0; i < s2; i++)
      cnt += 2 * (1 + 2 * i);
    short[][] res = new short[cnt][2];
    int idx = 0;
    for (short i = (short) -s2; i <= s2; i++) {
      int k = s2 - (i > 0 ? i : -i);
      for (short j = (short) -k; j <= k; j++) {
        res[idx][0] = j;
        res[idx++][1] = i;
      }
    }
    return res;
  }

  public static void printShape(short[][] pShape) {
    int idx = 0;
    while (idx < pShape.length) {
      System.out.print("{");
      if (pShape[idx][0] >= 0)
        System.out.print(" ");
      System.out.print(pShape[idx][0] + ",");
      if (pShape[idx][1] >= 0)
        System.out.print(" ");
      System.out.print(pShape[idx][1] + "} ");
      idx++;
      if (idx % 3 == 0)
        System.out.println("");
    }
  }

  //   xxx          {-1,-2} { 0,-2} { 1,-2}
  //  xxxxx {-2,-1} {-1,-1} { 0,-1} { 1,-1} { 2,-1}
  //  xxxxx {-2, 0} {-1, 0} { 0, 0} { 1, 0} { 2, 0}
  //  xxxxx {-2, 1} {-1, 1} { 0, 1} { 1, 1} { 2, 1}
  //   xxx          {-1, 2} { 0, 2} { 1, 2}
  private short[][] generateDisk(int pSize) {
    short s = (short) pSize;
    if ((s < 3) || (s % 2 == 0))
      throw new IllegalArgumentException(String.valueOf(pSize));
    short s2 = (short) (s / 2);
    SimpleImage img = new SimpleImage(s + 120, s + 120);
    Graphics g = img.getGraphics();
    g.setColor(new Color(255, 0, 0));
    // fillOval gave strange effects at low scales, but drawOval seems to work
    g.drawOval(0, 0, s - 1, s - 1);

    // fill it manually
    for (short i = 0; i < s; i++) {
      nextLine: for (short j = 0; j <= s2; j++) {
        if (img.getRValue(j, i) == 255) {
          g.drawLine(j, i, s - j - 1, i);
          continue nextLine;
        }
      }
    }
    int cnt = 0;
    for (short i = 0; i < s; i++) {
      for (short j = 0; j < s; j++) {
        if (img.getRValue(j, i) == 255)
          cnt++;
      }
    }
    int idx = 0;
    short[][] res = new short[cnt][2];
    for (short i = 0; i < s; i++) {
      for (short j = 0; j < s; j++) {
        if (img.getRValue(j, i) == 255) {
          res[idx][0] = (short) (j - s2);
          res[idx++][1] = (short) (i - s2);
        }
      }
    }
    /*   
        try {
          new ImageSaver().saveAsPNG(img, "D:\\TMP\\_z.png");
        }
        catch (Exception e) {
          e.printStackTrace();
        }
    */
    return res;
  }

  private short[][] generateRandom(int pSize) {
    short[][] res = new short[pSize * pSize][2];
    int s2 = pSize / 2;
    for (int i = 0; i < pSize; i++) {
      for (int j = 0; j < pSize; j++) {
        int idx = i * pSize + j;
        if (Tools.drand() > 0.33) {
          res[idx][0] = (short) ((double) (j - s2) * Tools.drand() + 0.5);
          res[idx][1] = (short) ((double) (i - s2) * Tools.drand() + 0.5);
        }
        else {
          res[idx][0] = 0;
          res[idx][1] = 0;
        }
      }
    }
    return res;
  }

  //  x          { 0,-1} 
  // xxx {-1, 0} { 0, 0} { 1, 0}
  //  x          { 0, 1}
  private short[][] generatePlus(int pSize) {
    short s = (short) pSize;
    if ((s < 3) || (s % 2 == 0))
      throw new IllegalArgumentException(String.valueOf(pSize));
    short s2 = (short) (s / 2);

    short[][] res = new short[2 * s - 1][2];
    int idx = 0;
    for (short i = 0; i < s; i++) {
      short jMin = (i == s2) ? 0 : s2;
      short jMax = (i == s2) ? s : (short) (s2 + 1);
      System.out.println(i + ": " + jMin + "..." + jMax);
      for (short j = jMin; j < jMax; j++) {
        res[idx][0] = (short) (j - s2);
        res[idx++][1] = (short) (i - s2);
      }
    }
    return res;
  }

  // x x {-1,-1}         { 1,-1}
  //  x          { 0, 0}
  // x x {-1, 1}         { 1, 1}
  private short[][] generateX(int pSize) {
    short s = (short) pSize;
    if ((s < 3) || (s % 2 == 0))
      throw new IllegalArgumentException(String.valueOf(pSize));
    short s2 = (short) (s / 2);
    short[][] res = new short[2 * s - 1][2];
    int idx = 0;
    for (short i = 0; i < s; i++) {
      if (i == s2) {
        res[idx][0] = 0;
        res[idx++][1] = (short) (i - s2);
      }
      else {
        short x = (short) (s2 - i);
        if (i > s2)
          x = (short) -x;
        res[idx][0] = (short) -x;
        res[idx++][1] = (short) (i - s2);
        res[idx][0] = (short) x;
        res[idx++][1] = (short) (i - s2);
      }
    }
    return res;
  }
  /*
    public static void main(String[] args) {
      ErodeTransformer t = new ErodeTransformer();
      // short[][] shape = t.generateSquare(5);
      // short[][] shape = t.generateDiamond(5);
      // short[][] shape = t.generateDisk(13);
      // short[][] shape = t.generatePlus(5);
      short[][] shape = t.generateX(5);
      t.printShape(shape);
    }
  */
TOP

Related Classes of org.jwildfire.transform.ErodeTransformer$ShapeEditor

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.