From eab6df10ab8292a59a05b25d18c413dd107bb94a Mon Sep 17 00:00:00 2001 From: Benjamin Culkin Date: Thu, 26 Apr 2018 05:48:09 -0700 Subject: Initial commit --- src/bjc/imgchain/pipeline/MutablePipeline.java | 102 +++++++++++++++ src/bjc/imgchain/pipeline/Pipeline.java | 37 ++++++ src/bjc/imgchain/pipeline/PipelinePicker.java | 63 +++++++++ src/bjc/imgchain/pipeline/PipelineStage.java | 52 ++++++++ src/bjc/imgchain/pipeline/StageType.java | 21 +++ .../pipeline/stages/AbstractPipelineStage.java | 33 +++++ .../pipeline/stages/AbstractPixelStage.java | 30 +++++ .../imgchain/pipeline/stages/BrightnessStage.java | 141 +++++++++++++++++++++ .../imgchain/pipeline/stages/ColorSkewStage.java | 141 +++++++++++++++++++++ src/bjc/imgchain/pipeline/stages/GaussStage.java | 110 ++++++++++++++++ .../imgchain/pipeline/stages/GreyscaleStage.java | 45 +++++++ src/bjc/imgchain/pipeline/stages/IDStage.java | 44 +++++++ .../imgchain/pipeline/stages/NegativeStage.java | 33 +++++ src/bjc/imgchain/pipeline/stages/StagePicker.java | 68 ++++++++++ 14 files changed, 920 insertions(+) create mode 100644 src/bjc/imgchain/pipeline/MutablePipeline.java create mode 100644 src/bjc/imgchain/pipeline/Pipeline.java create mode 100644 src/bjc/imgchain/pipeline/PipelinePicker.java create mode 100644 src/bjc/imgchain/pipeline/PipelineStage.java create mode 100644 src/bjc/imgchain/pipeline/StageType.java create mode 100644 src/bjc/imgchain/pipeline/stages/AbstractPipelineStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/AbstractPixelStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/BrightnessStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/ColorSkewStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/GaussStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/GreyscaleStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/IDStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/NegativeStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/StagePicker.java (limited to 'src/bjc/imgchain/pipeline') 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 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 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 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 pipeModel = new DefaultListModel<>(); + for (String pipeName : ImgChain.chan.pipelineRepo.keySet()) { + pipeModel.addElement(pipeName); + } + + JList 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); + } +} -- cgit v1.2.3