From 8dbfbb5c87a2fa74c5e3bf829a33fc6180430e5c Mon Sep 17 00:00:00 2001 From: Benjamin Culkin Date: Thu, 26 Apr 2018 07:16:16 -0700 Subject: Add more stages --- src/bjc/imgchain/ImgPickerPanel.java | 49 ++++++++++++ src/bjc/imgchain/ImgPipeline.java | 15 ++++ src/bjc/imgchain/pipeline/stages/AddMaskStage.java | 62 +++++++++++++++ src/bjc/imgchain/pipeline/stages/RecallStage.java | 49 ++++++++++++ src/bjc/imgchain/pipeline/stages/SaveStage.java | 89 ++++++++++++++++++++++ src/bjc/imgchain/pipeline/stages/StagePicker.java | 7 +- src/bjc/imgchain/pipeline/stages/StashStage.java | 45 +++++++++++ src/bjc/imgchain/pipeline/stages/SubMaskStage.java | 62 +++++++++++++++ 8 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 src/bjc/imgchain/ImgPickerPanel.java create mode 100644 src/bjc/imgchain/pipeline/stages/AddMaskStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/RecallStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/SaveStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/StashStage.java create mode 100644 src/bjc/imgchain/pipeline/stages/SubMaskStage.java (limited to 'src') diff --git a/src/bjc/imgchain/ImgPickerPanel.java b/src/bjc/imgchain/ImgPickerPanel.java new file mode 100644 index 0000000..6db6d69 --- /dev/null +++ b/src/bjc/imgchain/ImgPickerPanel.java @@ -0,0 +1,49 @@ +package bjc.imgchain; + +import java.awt.BorderLayout; + +import javax.swing.JButton; +import javax.swing.JPanel; + +import bjc.imgchain.utils.LabeledInputPanel; + +public class ImgPickerPanel extends JPanel { + public String stashName; + public LabeledInputPanel imgField; + + public ImgPickerPanel() { + setLayout(new BorderLayout()); + + setupGUI("Image name"); + } + + public ImgPickerPanel(String lab) { + setLayout(new BorderLayout()); + + setupGUI(lab); + } + + private void setupGUI(String lab) { + imgField = new LabeledInputPanel(lab, ""); + imgField.addPropertyChangeListener("value", (ev) -> { + stashName = imgField.field.getText(); + }); + + JButton pickImg = new JButton("Pick Image"); + pickImg.addActionListener((ev) -> { + ImgPicker pick = new ImgPicker(); + + pick.pack(); + pick.setVisible(true); + + if (pick.imageName == null) { + System.out.println("WARN: picked null image"); + return; + } + + imgField.field.setText(stashName); + }); + + add(imgField, BorderLayout.CENTER); + } +} diff --git a/src/bjc/imgchain/ImgPipeline.java b/src/bjc/imgchain/ImgPipeline.java index cfef3ba..a53df0f 100644 --- a/src/bjc/imgchain/ImgPipeline.java +++ b/src/bjc/imgchain/ImgPipeline.java @@ -28,7 +28,10 @@ import bjc.imgchain.pipeline.stages.IDStage; import bjc.imgchain.pipeline.stages.LoadStage; import bjc.imgchain.pipeline.stages.NegativeStage; import bjc.imgchain.pipeline.stages.PipeStage; +import bjc.imgchain.pipeline.stages.RecallStage; +import bjc.imgchain.pipeline.stages.SaveStage; import bjc.imgchain.pipeline.stages.StagePicker; +import bjc.imgchain.pipeline.stages.StashStage; import bjc.imgchain.pipeline.stages.ThresholdStage; /** @@ -168,6 +171,18 @@ public class ImgPipeline extends JInternalFrame { stag = new LoadStage(); } break; + case "Save Image": { + stag = new SaveStage(); + } + break; + case "Stash Image": { + stag = new StashStage(); + } + break; + case "Recall Image": { + stag = new RecallStage(); + } + break; default: JOptionPane.showMessageDialog(ImgChain.chan.desktop, String .format("Attempted to add unknown stage '%s'", pick.stageName)); diff --git a/src/bjc/imgchain/pipeline/stages/AddMaskStage.java b/src/bjc/imgchain/pipeline/stages/AddMaskStage.java new file mode 100644 index 0000000..50e5a7a --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/AddMaskStage.java @@ -0,0 +1,62 @@ +package bjc.imgchain.pipeline.stages; + +import java.awt.Image; +import java.awt.image.BufferedImage; + +import javax.swing.JComponent; + +import bjc.imgchain.ImgChain; +import bjc.imgchain.ImgPickerPanel; +import bjc.imgchain.pipeline.StageType; +import bjc.imgchain.utils.Utils; + +public class AddMaskStage extends AbstractPipelineStage { + private String masqueName; + + public AddMaskStage() { + super(StageType.IMGTRANS); + } + + @Override + public Image process(Image inp) { + BufferedImage buf = (BufferedImage) inp; + BufferedImage masque = (BufferedImage) ImgChain.chan.imageRepo.get(masqueName); + + for (int y = 0; y < buf.getHeight(); y++) { + for (int x = 0; x < buf.getWidth(); x++) { + int[] pix = Utils.toARGBQuad(buf.getRGB(x, y)); + int[] msq = Utils.toARGBQuad(masque.getRGB(x, y)); + + pix[1] += msq[1]; + pix[2] += msq[2]; + pix[3] += msq[3]; + + buf.setRGB(x, y, Utils.fromARGBQuad(pix)); + } + } + + return buf; + } + + @Override + public String name() { + return "Additive Mask"; + } + + @Override + public String description() { + return "Add two images togethers"; + } + + @Override + public JComponent getEditor() { + ImgPickerPanel pan = new ImgPickerPanel("Mask name"); + + pan.imgField.addPropertyChangeListener("value", (ev) -> { + masqueName = pan.imgField.field.getText(); + }); + + return pan; + } + +} diff --git a/src/bjc/imgchain/pipeline/stages/RecallStage.java b/src/bjc/imgchain/pipeline/stages/RecallStage.java new file mode 100644 index 0000000..db5b760 --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/RecallStage.java @@ -0,0 +1,49 @@ +package bjc.imgchain.pipeline.stages; + +import java.awt.BorderLayout; +import java.awt.Image; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JPanel; + +import bjc.imgchain.ImgChain; +import bjc.imgchain.ImgPicker; +import bjc.imgchain.ImgPickerPanel; +import bjc.imgchain.pipeline.StageType; +import bjc.imgchain.utils.LabeledInputPanel; + +public class RecallStage extends AbstractPipelineStage { + private String stashName; + + public RecallStage() { + super(StageType.IMGSOURCE); + } + + @Override + public Image process(Image inp) { + return ImgChain.chan.imageRepo.get(stashName); + } + + @Override + public String name() { + return "Recall Image"; + } + + @Override + public String description() { + return "Recall image from memory"; + } + + @Override + public JComponent getEditor() { + ImgPickerPanel pan = new ImgPickerPanel(); + + pan.imgField.addPropertyChangeListener("value", (ev) -> { + stashName = pan.imgField.field.getText(); + }); + + return pan; + } + +} diff --git a/src/bjc/imgchain/pipeline/stages/SaveStage.java b/src/bjc/imgchain/pipeline/stages/SaveStage.java new file mode 100644 index 0000000..a4c3041 --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/SaveStage.java @@ -0,0 +1,89 @@ +package bjc.imgchain.pipeline.stages; + +import java.awt.BorderLayout; +import java.awt.Image; +import java.io.File; +import java.io.IOException; +import java.net.URL; + +import javax.imageio.ImageIO; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import bjc.imgchain.pipeline.StageType; +import bjc.imgchain.utils.Utils; + +public class SaveStage extends AbstractPipelineStage { + private String fileName; + + public SaveStage() { + super(StageType.IMGSINK); + } + + @Override + public Image process(Image inp) { + try { + ImageIO.write(Utils.toBuffered(inp), "PNG", new File(fileName)); + } catch (IOException e) { + String msg = String.format("Error: Could not save image %s", fileName); + + System.out.printf("%s\n", msg); + + e.printStackTrace(); + + JOptionPane.showInternalMessageDialog(null, msg, "Error saving image", + JOptionPane.ERROR_MESSAGE); + } + + return inp; + } + + @Override + public String name() { + return "Save Image"; + } + + @Override + public String description() { + return "Save an image to a file"; + } + + @Override + public JComponent getEditor() { + JPanel holder = new JPanel(); + holder.setLayout(new BorderLayout()); + + JLabel fileLabel = new JLabel("File"); + + JTextField fileField = new JTextField(80); + fileField.addPropertyChangeListener("value", (ev) -> { + fileName = fileField.getText(); + }); + + JButton fileButton = new JButton("Select File"); + fileButton.addActionListener((ev) -> { + JFileChooser jfc = new JFileChooser(); + jfc.setMultiSelectionEnabled(false); + + int res = jfc.showSaveDialog(holder); + + if (res != JFileChooser.APPROVE_OPTION) { + return; + } + + fileField.setText(jfc.getSelectedFile().getAbsolutePath()); + }); + + holder.add(fileLabel, BorderLayout.LINE_START); + holder.add(fileField, BorderLayout.CENTER); + holder.add(fileButton, BorderLayout.LINE_END); + + return holder; + } + +} diff --git a/src/bjc/imgchain/pipeline/stages/StagePicker.java b/src/bjc/imgchain/pipeline/stages/StagePicker.java index 5dd9904..e627179 100644 --- a/src/bjc/imgchain/pipeline/stages/StagePicker.java +++ b/src/bjc/imgchain/pipeline/stages/StagePicker.java @@ -39,7 +39,12 @@ public class StagePicker extends JDialog { { "Negative", "Invert your images colors" }, { "Gaussian Blur", "Blur images" }, { "Tint", "Add/remove colors" }, { "Threshold", "Convert the image to black/white" }, { "Sub-pipeline", "Execute another pipeline" }, - { "Load Image", "Load an image from a file" } }; + { "Load Image", "Load an image from a file" }, + { "Save Image", "Save an image to a file" }, + { "Stash Image", "Stash an image to memory" }, + { "Recall Image", "Recall an image from memory" }, + { "Additive Mask", "Add two images together" }, + { "Subtractive Mask", "Subtract one image from another" } }; JTable stageTable = new JTable(new ImmutableTableModel(data, columnNames)); diff --git a/src/bjc/imgchain/pipeline/stages/StashStage.java b/src/bjc/imgchain/pipeline/stages/StashStage.java new file mode 100644 index 0000000..0b7e626 --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/StashStage.java @@ -0,0 +1,45 @@ +package bjc.imgchain.pipeline.stages; + +import java.awt.Image; + +import javax.swing.JComponent; + +import bjc.imgchain.ImgChain; +import bjc.imgchain.pipeline.StageType; +import bjc.imgchain.utils.LabeledInputPanel; + +public class StashStage extends AbstractPipelineStage { + private String stashName; + + public StashStage() { + super(StageType.IMGSOURCE); + } + + @Override + public Image process(Image inp) { + ImgChain.chan.addImage(stashName, inp); + + return inp; + } + + @Override + public String name() { + return "Stash Image"; + } + + @Override + public String description() { + return "Stash image to memory"; + } + + @Override + public JComponent getEditor() { + LabeledInputPanel imgName = new LabeledInputPanel("Image name", ""); + imgName.addPropertyChangeListener("value", (ev) -> { + stashName = imgName.field.getText(); + }); + + return imgName; + } + +} diff --git a/src/bjc/imgchain/pipeline/stages/SubMaskStage.java b/src/bjc/imgchain/pipeline/stages/SubMaskStage.java new file mode 100644 index 0000000..20a58ab --- /dev/null +++ b/src/bjc/imgchain/pipeline/stages/SubMaskStage.java @@ -0,0 +1,62 @@ +package bjc.imgchain.pipeline.stages; + +import java.awt.Image; +import java.awt.image.BufferedImage; + +import javax.swing.JComponent; + +import bjc.imgchain.ImgChain; +import bjc.imgchain.ImgPickerPanel; +import bjc.imgchain.pipeline.StageType; +import bjc.imgchain.utils.Utils; + +public class SubMaskStage extends AbstractPipelineStage { + private String masqueName; + + public SubMaskStage() { + super(StageType.IMGTRANS); + } + + @Override + public Image process(Image inp) { + BufferedImage buf = (BufferedImage) inp; + BufferedImage masque = (BufferedImage) ImgChain.chan.imageRepo.get(masqueName); + + for (int y = 0; y < buf.getHeight(); y++) { + for (int x = 0; x < buf.getWidth(); x++) { + int[] pix = Utils.toARGBQuad(buf.getRGB(x, y)); + int[] msq = Utils.toARGBQuad(masque.getRGB(x, y)); + + pix[1] -= msq[1]; + pix[2] -= msq[2]; + pix[3] -= msq[3]; + + buf.setRGB(x, y, Utils.fromARGBQuad(pix)); + } + } + + return buf; + } + + @Override + public String name() { + return "Subtractive Mask"; + } + + @Override + public String description() { + return "Subtract an image from this one"; + } + + @Override + public JComponent getEditor() { + ImgPickerPanel pan = new ImgPickerPanel("Mask name"); + + pan.imgField.addPropertyChangeListener("value", (ev) -> { + masqueName = pan.imgField.field.getText(); + }); + + return pan; + } + +} -- cgit v1.2.3