diff options
| author | Benjamin Culkin <bjculkin@mix.wvu.edu> | 2018-04-26 05:48:09 -0700 |
|---|---|---|
| committer | Benjamin Culkin <bjculkin@mix.wvu.edu> | 2018-04-26 05:48:09 -0700 |
| commit | eab6df10ab8292a59a05b25d18c413dd107bb94a (patch) | |
| tree | 9b147cbb61463d4a74d1a7dbc07f3273316fc670 /src/bjc/imgchain/pipeline | |
| parent | 697bc0bae293a9f31c00f6e10f33955151228f64 (diff) | |
Initial commit
Diffstat (limited to 'src/bjc/imgchain/pipeline')
| -rw-r--r-- | src/bjc/imgchain/pipeline/MutablePipeline.java | 102 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/Pipeline.java | 37 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/PipelinePicker.java | 63 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/PipelineStage.java | 52 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/StageType.java | 21 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/stages/AbstractPipelineStage.java | 33 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/stages/AbstractPixelStage.java | 30 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/stages/BrightnessStage.java | 141 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/stages/ColorSkewStage.java | 141 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/stages/GaussStage.java | 110 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/stages/GreyscaleStage.java | 45 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/stages/IDStage.java | 44 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/stages/NegativeStage.java | 33 | ||||
| -rw-r--r-- | src/bjc/imgchain/pipeline/stages/StagePicker.java | 68 |
14 files changed, 920 insertions, 0 deletions
diff --git a/src/bjc/imgchain/pipeline/MutablePipeline.java b/src/bjc/imgchain/pipeline/MutablePipeline.java new file mode 100644 index 0000000..6272b30 --- /dev/null +++ b/src/bjc/imgchain/pipeline/MutablePipeline.java @@ -0,0 +1,102 @@ +package bjc.imgchain.pipeline;
+
+import java.awt.Image;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An editable {@link Pipeline}
+ *
+ * @author acm
+ *
+ */
+public class MutablePipeline implements Pipeline {
+ private final List<PipelineStage> stages;
+
+ private String name;
+
+ /**
+ * Create a new unnamed mutable pipeline.
+ */
+ public MutablePipeline() {
+ stages = new ArrayList<>();
+
+ name = "Unnamed Pipeline";
+ }
+
+ /**
+ * Create a new named mutable pipeline.
+ *
+ * @param name
+ * The name of the pipeline.
+ */
+ public MutablePipeline(String name) {
+ stages = new ArrayList<>();
+
+ this.name = name;
+ }
+
+ @Override
+ public Image process(Image input) {
+ Image proc = input;
+
+ for (PipelineStage stage : stages) {
+ System.out.println("Applying stage " + stage.name());
+ proc = stage.process(proc);
+ System.out.println("Applied stage " + stage.name());
+ }
+
+ return proc;
+ }
+
+ @Override
+ public List<PipelineStage> stages() {
+ return stages;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Set the name of the pipeline.
+ *
+ * @param nam
+ * The name of the pipeline.
+ */
+ public void name(String nam) {
+ name = nam;
+ }
+
+ /**
+ * Append a pipeline stage to the end of this pipeline.
+ *
+ * @param stag
+ * The stage to add.
+ */
+ public void addStage(PipelineStage stag) {
+ stages.add(stag);
+ }
+
+ /**
+ * Remove a pipeline stage.
+ *
+ * @param stag
+ * The stage to remove.
+ */
+ public void removeStage(PipelineStage stag) {
+ stages.remove(stag);
+ }
+
+ /**
+ * Remove a pipeline stage by index.
+ *
+ * @param idx
+ * The index of the stage to remove.
+ */
+ public void removeStage(int idx) {
+ stages.remove(idx);
+ }
+
+}
diff --git a/src/bjc/imgchain/pipeline/Pipeline.java b/src/bjc/imgchain/pipeline/Pipeline.java new file mode 100644 index 0000000..faba6d5 --- /dev/null +++ b/src/bjc/imgchain/pipeline/Pipeline.java @@ -0,0 +1,37 @@ +package bjc.imgchain.pipeline;
+
+import java.awt.Image;
+import java.util.List;
+
+/**
+ * Represents a pipeline for processing images.
+ *
+ * @author acm
+ *
+ */
+public interface Pipeline {
+ /**
+ * Process an image using the stages.
+ *
+ * @param input
+ * The input image, or null if no image is input.
+ * @return The output image, or null if no image is output.
+ */
+ Image process(Image input);
+
+ /**
+ * Get the stages of the pipeline.
+ *
+ * @return The stages of the pipeline.
+ */
+ List<PipelineStage> stages();
+
+ /**
+ * Get the name of the pipeline.
+ *
+ * @return The name of the pipeline.
+ */
+ default String name() {
+ return "Unnamed Pipeline";
+ }
+}
diff --git a/src/bjc/imgchain/pipeline/PipelinePicker.java b/src/bjc/imgchain/pipeline/PipelinePicker.java new file mode 100644 index 0000000..92478a6 --- /dev/null +++ b/src/bjc/imgchain/pipeline/PipelinePicker.java @@ -0,0 +1,63 @@ +package bjc.imgchain.pipeline;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import bjc.imgchain.ImgChain;
+
+public class PipelinePicker extends JDialog {
+ private static final long serialVersionUID = 1L;
+
+ public String pipeName;
+
+ public PipelinePicker() {
+ super();
+
+ setModalityType(ModalityType.APPLICATION_MODAL);
+ setTitle("Add a Stage");
+
+ setupGUI();
+ }
+
+ private void setupGUI() {
+ setLayout(new BorderLayout());
+
+ DefaultListModel<String> pipeModel = new DefaultListModel<>();
+ for (String pipeName : ImgChain.chan.pipelineRepo.keySet()) {
+ pipeModel.addElement(pipeName);
+ }
+
+ JList<String> pipeList = new JList<>(pipeModel);
+ JScrollPane listScroll = new JScrollPane(pipeList);
+
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new GridLayout(2, 1));
+
+ JButton addStage = new JButton("Select Pipe");
+ addStage.addActionListener((ev) -> {
+ pipeName = pipeList.getSelectedValue();
+
+ setVisible(false);
+ dispose();
+ });
+
+ JButton cancel = new JButton("Cancel");
+ cancel.addActionListener((ev) -> {
+ setVisible(false);
+ dispose();
+ });
+
+ buttonPanel.add(addStage);
+ buttonPanel.add(cancel);
+
+ add(listScroll, BorderLayout.CENTER);
+ add(buttonPanel, BorderLayout.PAGE_END);
+ }
+}
diff --git a/src/bjc/imgchain/pipeline/PipelineStage.java b/src/bjc/imgchain/pipeline/PipelineStage.java new file mode 100644 index 0000000..46966c3 --- /dev/null +++ b/src/bjc/imgchain/pipeline/PipelineStage.java @@ -0,0 +1,52 @@ +package bjc.imgchain.pipeline;
+
+import java.awt.Image;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+
+/**
+ * A stage in an image processing pipeline.
+ *
+ * @author acm
+ *
+ */
+public interface PipelineStage {
+ /**
+ * Get the input/output type of this stage.
+ *
+ * @return The type of the stage.
+ *
+ */
+ StageType getType();
+
+ /**
+ * Pass an image through the stage.
+ *
+ * @param inp
+ * The input image, if one is needed
+ * @return The output image, if one is provided.
+ */
+ Image process(Image inp);
+
+ /**
+ * Get the name of this stage.
+ *
+ * @return The name of this stage.
+ */
+ String name();
+
+ /**
+ * Get a brief description of what this stage does.
+ *
+ * @return A brief description of what the stage does.
+ */
+ String description();
+
+ /**
+ * Get an editor for this stage.
+ *
+ * @return
+ */
+ JComponent getEditor();
+}
diff --git a/src/bjc/imgchain/pipeline/StageType.java b/src/bjc/imgchain/pipeline/StageType.java new file mode 100644 index 0000000..f54588d --- /dev/null +++ b/src/bjc/imgchain/pipeline/StageType.java @@ -0,0 +1,21 @@ +package bjc.imgchain.pipeline;
+
+/**
+ * The type of stage a given {@link PipelineStage} is.
+ * @author acm
+ *
+ */
+public enum StageType {
+ /**
+ * No image -> Image
+ */
+ IMGSOURCE,
+ /**
+ * Image -> Image
+ */
+ IMGTRANS,
+ /**
+ * Image -> No image
+ */
+ IMGSINK
+}
diff --git a/src/bjc/imgchain/pipeline/stages/AbstractPipelineStage.java b/src/bjc/imgchain/pipeline/stages/AbstractPipelineStage.java new file mode 100644 index 0000000..4183f4f --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/AbstractPipelineStage.java @@ -0,0 +1,33 @@ +package bjc.imgchain.pipeline.stages;
+
+import bjc.imgchain.pipeline.PipelineStage;
+import bjc.imgchain.pipeline.StageType;
+
+/**
+ * Abstract base class for stages.
+ *
+ * @author acm
+ *
+ */
+public abstract class AbstractPipelineStage implements PipelineStage {
+ private final StageType type;
+
+ protected AbstractPipelineStage(StageType type) {
+ this.type = type;
+ }
+
+ @Override
+ public StageType getType() {
+ return type;
+ }
+
+ @Override
+ public String description() {
+ return name();
+ }
+
+ @Override
+ public String toString() {
+ return name();
+ }
+}
diff --git a/src/bjc/imgchain/pipeline/stages/AbstractPixelStage.java b/src/bjc/imgchain/pipeline/stages/AbstractPixelStage.java new file mode 100644 index 0000000..44e3c60 --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/AbstractPixelStage.java @@ -0,0 +1,30 @@ +package bjc.imgchain.pipeline.stages;
+
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+
+import bjc.imgchain.pipeline.StageType;
+import bjc.imgchain.utils.Utils;
+
+public abstract class AbstractPixelStage extends AbstractPipelineStage {
+
+ protected AbstractPixelStage(StageType type) {
+ super(type);
+ }
+
+ @Override
+ public Image process(Image inp) {
+ BufferedImage buf = (BufferedImage) inp;
+
+ for (int y = 0; y < buf.getHeight(); y++) {
+ for (int x = 0; x < buf.getWidth(); x++) {
+ int[] pix = Utils.toARGBQuad(buf.getRGB(x, y));
+ buf.setRGB(x, y, Utils.fromARGBQuad(pix));
+ }
+ }
+
+ return buf;
+ }
+
+ public abstract int[] processPixel(int[] pix);
+}
diff --git a/src/bjc/imgchain/pipeline/stages/BrightnessStage.java b/src/bjc/imgchain/pipeline/stages/BrightnessStage.java new file mode 100644 index 0000000..4f0feb2 --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/BrightnessStage.java @@ -0,0 +1,141 @@ +package bjc.imgchain.pipeline.stages;
+
+import java.awt.GridLayout;
+import java.awt.Image;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.border.BevelBorder;
+import javax.swing.border.TitledBorder;
+
+import bjc.imgchain.pipeline.StageType;
+import bjc.imgchain.utils.LabeledInputPanel;
+
+public class BrightnessStage extends AbstractPixelStage {
+ public BrightnessStage() {
+ this(1, 0, 0, 0, 1, 0, 0, 0, 1);
+ }
+
+ public BrightnessStage(int rr, int rg, int rb, int gr, int gg, int gb,
+ int br, int bg, int bb) {
+ super(StageType.IMGTRANS);
+
+ this.rr = rr;
+ this.rg = rg;
+ this.rb = rb;
+ this.gr = gr;
+ this.gg = gg;
+ this.gb = gb;
+ this.br = br;
+ this.bg = bg;
+ this.bb = bb;
+ }
+
+
+ private int rr, rg, rb;
+ private int gr, gg, gb;
+ private int br, bg, bb;
+
+ @Override
+ public int[] processPixel(int[] pix) {
+ int[] ret = new int[4];
+
+ ret[0] = pix[0];
+ ret[1] = (int) ((pix[1] + rr) + (pix[2] + rg) + (pix[3] + rb));
+ ret[2] = (int) ((pix[1] + gr) + (pix[2] + gg) + (pix[3] + gb));
+ ret[3] = (int) ((pix[1] + br) + (pix[2] + bg) + (pix[3] + bb));
+
+ ret[1] = Math.max(0, Math.min(255, ret[1]));
+ ret[2] = Math.max(0, Math.min(255, ret[2]));
+ ret[3] = Math.max(0, Math.min(255, ret[3]));
+
+ return ret;
+ }
+
+ @Override
+ public String name() {
+ return "Tint";
+ }
+
+ @Override
+ public String description() {
+ return "Add/remove colors";
+ }
+
+ @Override
+ public JComponent getEditor() {
+ JPanel holder = new JPanel();
+ holder.setLayout(new GridLayout(3, 1));
+
+ JPanel rSkew = new JPanel();
+ rSkew.setLayout(new GridLayout(1, 3));
+ rSkew.setBorder(new TitledBorder(new BevelBorder(BevelBorder.LOWERED), "Red Balance"));
+
+ JPanel gSkew = new JPanel();
+ gSkew.setLayout(new GridLayout(1, 3));
+ gSkew.setBorder(new TitledBorder(new BevelBorder(BevelBorder.LOWERED), "Green Balance"));
+
+ JPanel bSkew = new JPanel();
+ bSkew.setLayout(new GridLayout(1, 3));
+ bSkew.setBorder(new TitledBorder(new BevelBorder(BevelBorder.LOWERED), "Blue Balance"));
+
+
+ LabeledInputPanel rpercRed = new LabeledInputPanel("% Red", rr);
+ LabeledInputPanel rpercGreen = new LabeledInputPanel("% Green", rg);
+ LabeledInputPanel rpercBlue = new LabeledInputPanel("% Blue", rb);
+ rSkew.add(rpercRed);
+ rSkew.add(rpercGreen);
+ rSkew.add(rpercBlue);
+
+ LabeledInputPanel gpercRed = new LabeledInputPanel("% Red", gr);
+ LabeledInputPanel gpercGreen = new LabeledInputPanel("% Green", gg);
+ LabeledInputPanel gpercBlue = new LabeledInputPanel("% Blue", gb);
+ gSkew.add(gpercRed);
+ gSkew.add(gpercGreen);
+ gSkew.add(gpercBlue);
+
+ LabeledInputPanel bpercRed = new LabeledInputPanel("% Red", br);
+ LabeledInputPanel bpercGreen = new LabeledInputPanel("% Green", bg);
+ LabeledInputPanel bpercBlue = new LabeledInputPanel("% Blue", bb);
+ bSkew.add(bpercRed);
+ bSkew.add(bpercGreen);
+ bSkew.add(bpercBlue);
+
+ rpercRed.addPropertyChangeListener("value", (ev) -> {
+ rr = (Integer)rpercRed.field.getValue();
+ });
+ gpercRed.addPropertyChangeListener("value", (ev) -> {
+ gr = (Integer)gpercRed.field.getValue();
+ });
+ bpercRed.addPropertyChangeListener("value", (ev) -> {
+ br = (Integer)bpercRed.field.getValue();
+ });
+
+ rpercGreen.addPropertyChangeListener("value", (ev) -> {
+ rg = (Integer)rpercGreen.field.getValue();
+ });
+ gpercGreen.addPropertyChangeListener("value", (ev) -> {
+ gg = (Integer)gpercGreen.field.getValue();
+ });
+ bpercGreen.addPropertyChangeListener("value", (ev) -> {
+ bg = (Integer)bpercGreen.field.getValue();
+ });
+
+ rpercBlue.addPropertyChangeListener("value", (ev) -> {
+ rb = (Integer)rpercBlue.field.getValue();
+ });
+ gpercBlue.addPropertyChangeListener("value", (ev) -> {
+ gb = (Integer)gpercBlue.field.getValue();
+ });
+ bpercBlue.addPropertyChangeListener("value", (ev) -> {
+ bb = (Integer)bpercBlue.field.getValue();
+ });
+
+ holder.add(rSkew);
+ holder.add(gSkew);
+ holder.add(bSkew);
+
+ return holder;
+ }
+
+}
\ No newline at end of file diff --git a/src/bjc/imgchain/pipeline/stages/ColorSkewStage.java b/src/bjc/imgchain/pipeline/stages/ColorSkewStage.java new file mode 100644 index 0000000..ba9d127 --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/ColorSkewStage.java @@ -0,0 +1,141 @@ +package bjc.imgchain.pipeline.stages;
+
+import java.awt.GridLayout;
+import java.awt.Image;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.border.BevelBorder;
+import javax.swing.border.TitledBorder;
+
+import bjc.imgchain.pipeline.StageType;
+import bjc.imgchain.utils.LabeledInputPanel;
+
+public class ColorSkewStage extends AbstractPixelStage {
+ public ColorSkewStage() {
+ this(1, 0, 0, 0, 1, 0, 0, 0, 1);
+ }
+
+ public ColorSkewStage(double rr, double rg, double rb, double gr, double gg, double gb,
+ double br, double bg, double bb) {
+ super(StageType.IMGTRANS);
+
+ this.rr = rr;
+ this.rg = rg;
+ this.rb = rb;
+ this.gr = gr;
+ this.gg = gg;
+ this.gb = gb;
+ this.br = br;
+ this.bg = bg;
+ this.bb = bb;
+ }
+
+
+ private double rr, rg, rb;
+ private double gr, gg, gb;
+ private double br, bg, bb;
+
+ @Override
+ public int[] processPixel(int[] pix) {
+ int[] ret = new int[4];
+
+ ret[0] = pix[0];
+ ret[1] = (int) ((pix[1] * rr) + (pix[2] * rg) + (pix[3] * rb));
+ ret[2] = (int) ((pix[1] * gr) + (pix[2] * gg) + (pix[3] * gb));
+ ret[3] = (int) ((pix[1] * br) + (pix[2] * bg) + (pix[3] * bb));
+
+ ret[1] = Math.min(255, ret[1]);
+ ret[2] = Math.min(255, ret[2]);
+ ret[3] = Math.min(255, ret[3]);
+
+ return ret;
+ }
+
+ @Override
+ public String name() {
+ return "Color Skew";
+ }
+
+ @Override
+ public String description() {
+ return "Adjust color balance";
+ }
+
+ @Override
+ public JComponent getEditor() {
+ JPanel holder = new JPanel();
+ holder.setLayout(new GridLayout(3, 1));
+
+ JPanel rSkew = new JPanel();
+ rSkew.setLayout(new GridLayout(1, 3));
+ rSkew.setBorder(new TitledBorder(new BevelBorder(BevelBorder.LOWERED), "Red Balance"));
+
+ JPanel gSkew = new JPanel();
+ gSkew.setLayout(new GridLayout(1, 3));
+ gSkew.setBorder(new TitledBorder(new BevelBorder(BevelBorder.LOWERED), "Green Balance"));
+
+ JPanel bSkew = new JPanel();
+ bSkew.setLayout(new GridLayout(1, 3));
+ bSkew.setBorder(new TitledBorder(new BevelBorder(BevelBorder.LOWERED), "Blue Balance"));
+
+
+ LabeledInputPanel rpercRed = new LabeledInputPanel("% Red", rr);
+ LabeledInputPanel rpercGreen = new LabeledInputPanel("% Green", rg);
+ LabeledInputPanel rpercBlue = new LabeledInputPanel("% Blue", rb);
+ rSkew.add(rpercRed);
+ rSkew.add(rpercGreen);
+ rSkew.add(rpercBlue);
+
+ LabeledInputPanel gpercRed = new LabeledInputPanel("% Red", gr);
+ LabeledInputPanel gpercGreen = new LabeledInputPanel("% Green", gg);
+ LabeledInputPanel gpercBlue = new LabeledInputPanel("% Blue", gb);
+ gSkew.add(gpercRed);
+ gSkew.add(gpercGreen);
+ gSkew.add(gpercBlue);
+
+ LabeledInputPanel bpercRed = new LabeledInputPanel("% Red", br);
+ LabeledInputPanel bpercGreen = new LabeledInputPanel("% Green", bg);
+ LabeledInputPanel bpercBlue = new LabeledInputPanel("% Blue", bb);
+ bSkew.add(bpercRed);
+ bSkew.add(bpercGreen);
+ bSkew.add(bpercBlue);
+
+ rpercRed.addPropertyChangeListener("value", (ev) -> {
+ rr = (Double)rpercRed.field.getValue();
+ });
+ gpercRed.addPropertyChangeListener("value", (ev) -> {
+ gr = (Double)gpercRed.field.getValue();
+ });
+ bpercRed.addPropertyChangeListener("value", (ev) -> {
+ br = (Double)bpercRed.field.getValue();
+ });
+
+ rpercGreen.addPropertyChangeListener("value", (ev) -> {
+ rg = (Double)rpercGreen.field.getValue();
+ });
+ gpercGreen.addPropertyChangeListener("value", (ev) -> {
+ gg = (Double)gpercGreen.field.getValue();
+ });
+ bpercGreen.addPropertyChangeListener("value", (ev) -> {
+ bg = (Double)bpercGreen.field.getValue();
+ });
+
+ rpercBlue.addPropertyChangeListener("value", (ev) -> {
+ rb = (Double)rpercBlue.field.getValue();
+ });
+ gpercBlue.addPropertyChangeListener("value", (ev) -> {
+ gb = (Double)gpercBlue.field.getValue();
+ });
+ bpercBlue.addPropertyChangeListener("value", (ev) -> {
+ bb = (Double)bpercBlue.field.getValue();
+ });
+
+ holder.add(rSkew);
+ holder.add(gSkew);
+ holder.add(bSkew);
+
+ return holder;
+ }
+
+}
diff --git a/src/bjc/imgchain/pipeline/stages/GaussStage.java b/src/bjc/imgchain/pipeline/stages/GaussStage.java new file mode 100644 index 0000000..2b04ddf --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/GaussStage.java @@ -0,0 +1,110 @@ +package bjc.imgchain.pipeline.stages;
+
+import java.awt.GridLayout;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.ConvolveOp;
+import java.awt.image.Kernel;
+
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+
+import bjc.imgchain.pipeline.StageType;
+import bjc.imgchain.utils.LabeledInputPanel;
+
+public class GaussStage extends AbstractPipelineStage {
+ private int m;
+ private double sig, k;
+
+ public GaussStage() {
+ super(StageType.IMGTRANS);
+ }
+
+ @Override
+ public Image process(Image inp) {
+ BufferedImage buf = (BufferedImage) inp;
+
+ ConvolveOp cop = new ConvolveOp(genKern());
+
+ BufferedImage ret = cop.createCompatibleDestImage(buf, null);
+
+ cop.filter(buf, ret);
+
+ return ret;
+ }
+
+ private Kernel genKern() {
+ float[][] w = new float[m][m];
+
+ float sum = 0.0f;
+
+ for (int i = 0; i < m - 1; i++) {
+ for (int j = 0; j < m - 1; j++) {
+ double s = i - (m / 2.0);
+ double t = j - (m / 2.0);
+
+ double r2 = (s * s) + (t * t);
+
+ double frac = r2 / (2.0 * sig * sig);
+
+ double val = k * Math.exp(-frac);
+
+ int idx1 = m - i;
+ int idx2 = m - j;
+
+ float fval = (float) val;
+
+ w[idx1 - 1][idx2 - 1] = fval;
+ sum += fval;
+ }
+ }
+
+ float invsum = 1 / sum;
+
+ float[] dat = new float[m * m];
+
+ for (int i = 0; i < m; i++) {
+ for (int j = 0; j < m; j++) {
+ dat[(i * m) + j] = w[i][j] * sum;
+ }
+ }
+
+ return new Kernel(m, m, dat);
+ }
+
+ @Override
+ public String name() {
+ return "Gaussian";
+ }
+
+ @Override
+ public String description() {
+ return "Perform a gaussian blur";
+ }
+
+ @Override
+ public JComponent getEditor() {
+ JPanel holder = new JPanel();
+ holder.setLayout(new GridLayout(3, 1));
+
+ LabeledInputPanel mField = new LabeledInputPanel("Size of kernel", 3);
+ mField.addPropertyChangeListener("value", (ev) -> {
+ m = (Integer) mField.field.getValue();
+ });
+ LabeledInputPanel sigField = new LabeledInputPanel("Value for sigma", 3.0);
+ sigField.addPropertyChangeListener("value", (ev) -> {
+ sig = (Double) sigField.field.getValue();
+ });
+ LabeledInputPanel kField = new LabeledInputPanel("Value for k", 1.0);
+ kField.addPropertyChangeListener("value", (ev) -> {
+ k = (Double) kField.field.getValue();
+ });
+
+ holder.add(mField);
+ holder.add(sigField);
+ holder.add(kField);
+
+ return holder;
+ }
+
+}
diff --git a/src/bjc/imgchain/pipeline/stages/GreyscaleStage.java b/src/bjc/imgchain/pipeline/stages/GreyscaleStage.java new file mode 100644 index 0000000..71bb743 --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/GreyscaleStage.java @@ -0,0 +1,45 @@ +package bjc.imgchain.pipeline.stages;
+
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+
+import bjc.imgchain.pipeline.StageType;
+import bjc.imgchain.utils.Utils;
+
+public class GreyscaleStage extends AbstractPixelStage {
+
+ public GreyscaleStage() {
+ super(StageType.IMGTRANS);
+ }
+
+ public int[] processPixel(int[] pix) {
+ int[] ret = new int[4];
+
+ int avg = (pix[1] + pix[2] + pix[3]) / 3;
+
+ ret[0] = pix[0];
+ ret[1] = avg;
+ ret[2] = avg;
+ ret[3] = avg;
+
+ return ret;
+ }
+ @Override
+ public String name() {
+ return "Greyscale";
+ }
+
+ @Override
+ public String description() {
+ return "Convert an image into greyscale color";
+ }
+
+ @Override
+ public JComponent getEditor() {
+ return new JLabel("No configuration possible");
+ }
+
+}
diff --git a/src/bjc/imgchain/pipeline/stages/IDStage.java b/src/bjc/imgchain/pipeline/stages/IDStage.java new file mode 100644 index 0000000..93aaebd --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/IDStage.java @@ -0,0 +1,44 @@ +package bjc.imgchain.pipeline.stages;
+
+import java.awt.Image;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+
+import bjc.imgchain.pipeline.StageType;
+
+/**
+ * A pipeline stage that does nothing.
+ *
+ * @author acm
+ *
+ */
+public class IDStage extends AbstractPipelineStage {
+
+ /**
+ * Create a new identity stage.
+ */
+ public IDStage() {
+ super(StageType.IMGTRANS);
+ }
+
+ @Override
+ public String name() {
+ return "Identity";
+ }
+
+ @Override
+ public Image process(Image inp) {
+ return inp;
+ }
+
+ @Override
+ public String description() {
+ return "Passes an image straight through.";
+ }
+
+ @Override
+ public JComponent getEditor() {
+ return new JLabel("Nothing to edit");
+ }
+}
diff --git a/src/bjc/imgchain/pipeline/stages/NegativeStage.java b/src/bjc/imgchain/pipeline/stages/NegativeStage.java new file mode 100644 index 0000000..028139c --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/NegativeStage.java @@ -0,0 +1,33 @@ +package bjc.imgchain.pipeline.stages;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+
+import bjc.imgchain.pipeline.StageType;
+
+public class NegativeStage extends AbstractPixelStage {
+ public NegativeStage() {
+ super(StageType.IMGTRANS);
+ }
+
+ @Override
+ public String name() {
+ return "Negative";
+ }
+
+ @Override
+ public String description() {
+ return "Invert image colors";
+ }
+
+ @Override
+ public JComponent getEditor() {
+ return new JLabel("No configuration available");
+ }
+
+ @Override
+ public int[] processPixel(int[] pix) {
+ return new int[] { pix[0], 255 - pix[1], 255 - pix[2], 255 - pix[3] };
+ }
+
+}
diff --git a/src/bjc/imgchain/pipeline/stages/StagePicker.java b/src/bjc/imgchain/pipeline/stages/StagePicker.java new file mode 100644 index 0000000..8b30ee4 --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/StagePicker.java @@ -0,0 +1,68 @@ +package bjc.imgchain.pipeline.stages;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+
+import bjc.imgchain.utils.ImmutableTableModel;
+
+public class StagePicker extends JDialog {
+ private static final long serialVersionUID = 1L;
+
+ public String stageName;
+
+ public StagePicker() {
+ super();
+
+ setModalityType(ModalityType.APPLICATION_MODAL);
+ setTitle("Add a Stage");
+
+ setupGUI();
+ }
+
+ private void setupGUI() {
+ setLayout(new BorderLayout());
+
+ String[] columnNames = new String[] { "Stage Name", "Stage Description" };
+
+ /*
+ * :AddStage
+ */
+ String[][] data = new String[][] { { "Identity", "Pass through image unchanged" },
+ { "Greyscale", "Convert a color image into greyscale" },
+ { "Color Skew", "Adjust color balance" }, { "Sepia", "Make your image sepia toned" },
+ { "Negative", "Invert your images colors" }, { "Gaussian Blur", "Blur images" } };
+
+ JTable stageTable = new JTable(new ImmutableTableModel(data, columnNames));
+
+ JScrollPane tableScroll = new JScrollPane(stageTable);
+
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new GridLayout(2, 1));
+
+ JButton addStage = new JButton("Add Stage");
+ addStage.addActionListener((ev) -> {
+ stageName = (String) stageTable.getModel().getValueAt(stageTable.getSelectedRow(), 0);
+
+ setVisible(false);
+ dispose();
+ });
+
+ JButton cancel = new JButton("Cancel");
+ cancel.addActionListener((ev) -> {
+ setVisible(false);
+ dispose();
+ });
+
+ buttonPanel.add(addStage);
+ buttonPanel.add(cancel);
+
+ add(tableScroll, BorderLayout.CENTER);
+ add(buttonPanel, BorderLayout.PAGE_END);
+ }
+}
|
