summaryrefslogtreecommitdiff
path: root/src/bjc
diff options
context:
space:
mode:
Diffstat (limited to 'src/bjc')
-rw-r--r--src/bjc/imgchain/ImgPicker.java63
-rw-r--r--src/bjc/imgchain/ImgPipeline.java20
-rw-r--r--src/bjc/imgchain/ImgViewer.java57
-rw-r--r--src/bjc/imgchain/pipeline/PipelinePicker.java4
-rw-r--r--src/bjc/imgchain/pipeline/stages/BrightnessStage.java65
-rw-r--r--src/bjc/imgchain/pipeline/stages/LoadStage.java87
-rw-r--r--src/bjc/imgchain/pipeline/stages/PipeStage.java75
-rw-r--r--src/bjc/imgchain/pipeline/stages/StagePicker.java5
-rw-r--r--src/bjc/imgchain/pipeline/stages/ThresholdStage.java103
9 files changed, 420 insertions, 59 deletions
diff --git a/src/bjc/imgchain/ImgPicker.java b/src/bjc/imgchain/ImgPicker.java
new file mode 100644
index 0000000..bc93089
--- /dev/null
+++ b/src/bjc/imgchain/ImgPicker.java
@@ -0,0 +1,63 @@
+package bjc.imgchain;
+
+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 ImgPicker extends JDialog {
+ private static final long serialVersionUID = 1L;
+
+ public String imageName;
+
+ public ImgPicker() {
+ super();
+
+ setModalityType(ModalityType.APPLICATION_MODAL);
+ setTitle("Recall an Image");
+
+ setupGUI();
+ }
+
+ private void setupGUI() {
+ setLayout(new BorderLayout());
+
+ DefaultListModel<String> imgModel = new DefaultListModel<>();
+ for (String imgName : ImgChain.chan.imageRepo.keySet()) {
+ imgModel.addElement(imgName);
+ }
+
+ JList<String> imgList = new JList<>(imgModel);
+ JScrollPane listScroll = new JScrollPane(imgList);
+
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new GridLayout(2, 1));
+
+ JButton addStage = new JButton("Recall Image");
+ addStage.addActionListener((ev) -> {
+ imageName = imgList.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/ImgPipeline.java b/src/bjc/imgchain/ImgPipeline.java
index 8dbbebf..cfef3ba 100644
--- a/src/bjc/imgchain/ImgPipeline.java
+++ b/src/bjc/imgchain/ImgPipeline.java
@@ -20,12 +20,16 @@ import javax.swing.border.TitledBorder;
import bjc.imgchain.pipeline.MutablePipeline;
import bjc.imgchain.pipeline.PipelineStage;
+import bjc.imgchain.pipeline.stages.BrightnessStage;
import bjc.imgchain.pipeline.stages.ColorSkewStage;
import bjc.imgchain.pipeline.stages.GaussStage;
import bjc.imgchain.pipeline.stages.GreyscaleStage;
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.StagePicker;
+import bjc.imgchain.pipeline.stages.ThresholdStage;
/**
* Edit an image pipeline.
@@ -148,6 +152,22 @@ public class ImgPipeline extends JInternalFrame {
stag = new GaussStage();
}
break;
+ case "Tint": {
+ stag = new BrightnessStage();
+ }
+ break;
+ case "Threshold": {
+ stag = new ThresholdStage();
+ }
+ break;
+ case "Sub-pipeline": {
+ stag = new PipeStage();
+ }
+ break;
+ case "Load Image": {
+ stag = new LoadStage();
+ }
+ break;
default:
JOptionPane.showMessageDialog(ImgChain.chan.desktop, String
.format("Attempted to add unknown stage '%s'", pick.stageName));
diff --git a/src/bjc/imgchain/ImgViewer.java b/src/bjc/imgchain/ImgViewer.java
index 06c2a1e..6876514 100644
--- a/src/bjc/imgchain/ImgViewer.java
+++ b/src/bjc/imgchain/ImgViewer.java
@@ -63,7 +63,7 @@ public class ImgViewer extends JInternalFrame {
icon.setImage(ImageIO.read(tmp));
img = tmp;
-
+
setTitle("Image Viewer - " + img.getName());
} catch (IOException e) {
String msg = String.format("Error: Could not load image %s", img.getPath());
@@ -124,16 +124,44 @@ public class ImgViewer extends JInternalFrame {
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic('F');
- JMenuItem changeImage = new JMenuItem("Change Image");
- changeImage.setMnemonic('C');
+ JMenuItem changeImage = new JMenuItem("Load Image from Disk");
+ changeImage.setMnemonic('L');
changeImage.addActionListener(new ChangeImageListener());
JMenuItem reloadImage = new JMenuItem("Reload Image");
reloadImage.setMnemonic('R');
reloadImage.addActionListener(new ReloadImageListener(img));
- JMenuItem storeImage = new JMenuItem("Store Image");
- storeImage.setMnemonic('S');
+ JMenuItem saveImage = new JMenuItem("Save Image");
+ saveImage.setMnemonic('S');
+ saveImage.addActionListener((ev) -> {
+ JFileChooser jfc = new JFileChooser();
+ jfc.setMultiSelectionEnabled(false);
+
+ int res = jfc.showSaveDialog(ImgViewer.this);
+
+ if (res != JFileChooser.APPROVE_OPTION) {
+ return;
+ }
+
+ try {
+ File tmp = jfc.getSelectedFile();
+
+ ImageIO.write(Utils.toBuffered(icon.getImage()), "PNG", tmp);
+ } catch (IOException e) {
+ String msg = String.format("Error: Could not save image %s", img.getPath());
+
+ System.out.printf("%s\n", msg);
+
+ e.printStackTrace();
+
+ JOptionPane.showInternalMessageDialog(null, msg, "Error saving image",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ });
+
+ JMenuItem storeImage = new JMenuItem("Stash Image to Memory");
+ storeImage.setMnemonic('T');
storeImage.addActionListener((ev) -> {
String inp = JOptionPane.showInternalInputDialog(this, "Enter name to store image under");
@@ -149,6 +177,25 @@ public class ImgViewer extends JInternalFrame {
desktop.addImage(inp, icon.getImage());
});
+ JMenuItem recallImage = new JMenuItem("Recall Image from Memory");
+ recallImage.setMnemonic('F');
+ recallImage.addActionListener((ev) -> {
+ ImgPicker pick = new ImgPicker();
+
+ pick.pack();
+ pick.setVisible(true);
+
+ if (pick.imageName == null) {
+ System.out.println("WARN: picked null image");
+ return;
+ }
+
+ Image imag = ImgChain.chan.imageRepo.get(pick.imageName);
+
+ icon.setImage(imag);
+ lab.repaint();
+ });
+
fileMenu.add(changeImage);
fileMenu.add(reloadImage);
fileMenu.addSeparator();
diff --git a/src/bjc/imgchain/pipeline/PipelinePicker.java b/src/bjc/imgchain/pipeline/PipelinePicker.java
index 92478a6..3539beb 100644
--- a/src/bjc/imgchain/pipeline/PipelinePicker.java
+++ b/src/bjc/imgchain/pipeline/PipelinePicker.java
@@ -21,7 +21,7 @@ public class PipelinePicker extends JDialog {
super();
setModalityType(ModalityType.APPLICATION_MODAL);
- setTitle("Add a Stage");
+ setTitle("Apply a Pipeline");
setupGUI();
}
@@ -40,7 +40,7 @@ public class PipelinePicker extends JDialog {
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(2, 1));
- JButton addStage = new JButton("Select Pipe");
+ JButton addStage = new JButton("Apply Pipe");
addStage.addActionListener((ev) -> {
pipeName = pipeList.getSelectedValue();
diff --git a/src/bjc/imgchain/pipeline/stages/BrightnessStage.java b/src/bjc/imgchain/pipeline/stages/BrightnessStage.java
index 4f0feb2..ae31dcc 100644
--- a/src/bjc/imgchain/pipeline/stages/BrightnessStage.java
+++ b/src/bjc/imgchain/pipeline/stages/BrightnessStage.java
@@ -13,38 +13,31 @@ import bjc.imgchain.utils.LabeledInputPanel;
public class BrightnessStage extends AbstractPixelStage {
public BrightnessStage() {
- this(1, 0, 0, 0, 1, 0, 0, 0, 1);
+ this(0, 0, 0);
}
- public BrightnessStage(int rr, int rg, int rb, int gr, int gg, int gb,
- int br, int bg, int bb) {
+ public BrightnessStage(int rr, int gg, 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;
+ private int rr;
+ private int gg;
+ private int 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] = pix[1] + rr;
+ ret[2] = pix[2] + gg;
+ ret[3] = 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]));
@@ -80,53 +73,23 @@ public class BrightnessStage extends AbstractPixelStage {
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);
+ LabeledInputPanel rpercRed = new LabeledInputPanel("+/- Red", rr);
+ rSkew.add(rpercRed);;
+
+ LabeledInputPanel gpercGreen = new LabeledInputPanel("+/- Green", gg);
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);
+ LabeledInputPanel bpercBlue = new LabeledInputPanel("+/- Blue", bb);
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();
});
diff --git a/src/bjc/imgchain/pipeline/stages/LoadStage.java b/src/bjc/imgchain/pipeline/stages/LoadStage.java
new file mode 100644
index 0000000..ed63a89
--- /dev/null
+++ b/src/bjc/imgchain/pipeline/stages/LoadStage.java
@@ -0,0 +1,87 @@
+package bjc.imgchain.pipeline.stages;
+
+import java.awt.BorderLayout;
+import java.awt.Image;
+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;
+
+public class LoadStage extends AbstractPipelineStage {
+ private String fileName;
+
+ public LoadStage() {
+ super(StageType.IMGSOURCE);
+ }
+
+ @Override
+ public Image process(Image inp) {
+ try {
+ return ImageIO.read(new URL("file://" + fileName));
+ } catch (IOException e) {
+ String msg = String.format("Error: Could not load image %s", fileName);
+
+ System.out.printf("%s\n", msg);
+
+ e.printStackTrace();
+
+ JOptionPane.showInternalMessageDialog(null, msg, "Error loading image",
+ JOptionPane.ERROR_MESSAGE);
+ }
+
+ return inp;
+ }
+
+ @Override
+ public String name() {
+ return "Load Image";
+ }
+
+ @Override
+ public String description() {
+ return "Load an image from 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.showOpenDialog(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/PipeStage.java b/src/bjc/imgchain/pipeline/stages/PipeStage.java
new file mode 100644
index 0000000..1472a3c
--- /dev/null
+++ b/src/bjc/imgchain/pipeline/stages/PipeStage.java
@@ -0,0 +1,75 @@
+package bjc.imgchain.pipeline.stages;
+
+import java.awt.BorderLayout;
+import java.awt.Image;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import bjc.imgchain.ImgChain;
+import bjc.imgchain.pipeline.Pipeline;
+import bjc.imgchain.pipeline.PipelinePicker;
+import bjc.imgchain.pipeline.StageType;
+
+public class PipeStage extends AbstractPipelineStage {
+ private String pipeName;
+
+ public PipeStage() {
+ super(StageType.IMGTRANS);
+ }
+
+ @Override
+ public Image process(Image inp) {
+ Pipeline pipeline = ImgChain.chan.pipelineRepo.get(pipeName);
+
+ return pipeline.process(inp);
+ }
+
+ @Override
+ public String name() {
+ return "Sub-pipeline";
+ }
+
+ @Override
+ public String description() {
+ return "Run the steps of another pipeline";
+ }
+
+ @Override
+ public JComponent getEditor() {
+ JPanel holder = new JPanel();
+ holder.setLayout(new BorderLayout());
+
+ JLabel pipeLabel = new JLabel("Pipeline");
+
+ JTextField pipeField = new JTextField(80);
+ pipeField.addPropertyChangeListener("value", (ev) -> {
+ pipeName = pipeField.getText();
+ });
+
+ JButton pipeButton = new JButton("Select Pipeline");
+ pipeButton.addActionListener((ev) -> {
+ PipelinePicker pick = new PipelinePicker();
+
+ pick.pack();
+ pick.setVisible(true);
+
+ if (pick.pipeName == null) {
+ System.out.println("WARN: picked null pipe");
+ return;
+ }
+
+ pipeField.setText(pick.pipeName);
+ });
+
+ holder.add(pipeLabel, BorderLayout.LINE_START);
+ holder.add(pipeField, BorderLayout.CENTER);
+ holder.add(pipeButton, BorderLayout.LINE_END);
+
+ return holder;
+ }
+
+}
diff --git a/src/bjc/imgchain/pipeline/stages/StagePicker.java b/src/bjc/imgchain/pipeline/stages/StagePicker.java
index 8b30ee4..5dd9904 100644
--- a/src/bjc/imgchain/pipeline/stages/StagePicker.java
+++ b/src/bjc/imgchain/pipeline/stages/StagePicker.java
@@ -36,7 +36,10 @@ public class StagePicker extends JDialog {
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" } };
+ { "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" } };
JTable stageTable = new JTable(new ImmutableTableModel(data, columnNames));
diff --git a/src/bjc/imgchain/pipeline/stages/ThresholdStage.java b/src/bjc/imgchain/pipeline/stages/ThresholdStage.java
new file mode 100644
index 0000000..5a72946
--- /dev/null
+++ b/src/bjc/imgchain/pipeline/stages/ThresholdStage.java
@@ -0,0 +1,103 @@
+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 ThresholdStage extends AbstractPixelStage {
+ public ThresholdStage() {
+ this(0, 0, 0);
+ }
+
+ public ThresholdStage(int rr, int gg, int bb) {
+ super(StageType.IMGTRANS);
+
+ this.redThreshold = rr;
+ this.greenThreshold = gg;
+ this.blueThreshold = bb;
+ }
+
+ private int redThreshold;
+ private int greenThreshold;
+ private int blueThreshold;
+
+ @Override
+ public int[] processPixel(int[] pix) {
+ int[] ret = new int[4];
+
+ ret[0] = pix[0];
+ ret[1] = pix[1] > redThreshold ? 255 : 0;
+ ret[2] = pix[2] > greenThreshold ? 255 : 0;
+ ret[3] = pix[3] > blueThreshold ? 255 : 0;
+
+ 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 Threshold"));
+
+ JPanel gSkew = new JPanel();
+ gSkew.setLayout(new GridLayout(1, 3));
+ gSkew.setBorder(new TitledBorder(new BevelBorder(BevelBorder.LOWERED), "Green Threshold"));
+
+ JPanel bSkew = new JPanel();
+ bSkew.setLayout(new GridLayout(1, 3));
+ bSkew.setBorder(new TitledBorder(new BevelBorder(BevelBorder.LOWERED), "Blue Threshold"));
+
+ LabeledInputPanel rpercRed = new LabeledInputPanel("Red", redThreshold);
+ rSkew.add(rpercRed);
+ ;
+
+ LabeledInputPanel gpercGreen = new LabeledInputPanel("Green", greenThreshold);
+ gSkew.add(gpercGreen);
+
+ LabeledInputPanel bpercBlue = new LabeledInputPanel("Blue", blueThreshold);
+ bSkew.add(bpercBlue);
+
+ rpercRed.addPropertyChangeListener("value", (ev) -> {
+ redThreshold = (Integer) rpercRed.field.getValue();
+ });
+
+ gpercGreen.addPropertyChangeListener("value", (ev) -> {
+ greenThreshold = (Integer) gpercGreen.field.getValue();
+ });
+
+ bpercBlue.addPropertyChangeListener("value", (ev) -> {
+ blueThreshold = (Integer) bpercBlue.field.getValue();
+ });
+
+ holder.add(rSkew);
+ holder.add(gSkew);
+ holder.add(bSkew);
+
+ return holder;
+ }
+
+} \ No newline at end of file