import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Label;
import java.awt.MediaTracker;
import java.awt.Panel;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.color.ColorSpace;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorConvertOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.awt.image.LookupOp;
import java.awt.image.RescaleOp;
import java.awt.image.ShortLookupTable;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import javax.swing.JPanel;
import javax.swing.text.Utilities;
public class Sampler extends Frame {
private Frame mImageFrame;
private SplitImageComponent mSplitImageComponent;
private Hashtable mOps;
public static void main(String[] args) {
String imageFile = "largeJava2sLogo.jpg";
if (args.length > 0)
imageFile = args[0];
new Sampler(imageFile);
}
public Sampler(String imageFile) {
super();
createOps();
createImageFrame(imageFile);
createUI();
setVisible(true);
}
private void createOps() {
mOps = new Hashtable();
createConvolutions();
createTransformations();
createLookups();
createRescales();
createColorOps();
}
private void createConvolutions() {
float ninth = 1.0f / 9.0f;
float[] blurKernel = { ninth, ninth, ninth, ninth, ninth, ninth, ninth,
ninth, ninth };
mOps.put("Blur", new ConvolveOp(new Kernel(3, 3, blurKernel),
ConvolveOp.EDGE_NO_OP, null));
float[] edge = { 0f, -1f, 0f, -1f, 4f, -1f, 0f, -1f, 0f };
mOps.put("Edge detector", new ConvolveOp(new Kernel(3, 3, edge),
ConvolveOp.EDGE_NO_OP, null));
float[] sharp = { 0f, -1f, 0f, -1f, 5f, -1f, 0f, -1f, 0f };
mOps.put("Sharpen", new ConvolveOp(new Kernel(3, 3, sharp)));
}
private void createTransformations() {
AffineTransform at;
at = AffineTransform.getRotateInstance(Math.PI / 6, 0, 285);
mOps.put("Rotate nearest neighbor", new AffineTransformOp(at, null));
RenderingHints rh = new RenderingHints(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
mOps.put("Rotate bilinear", new AffineTransformOp(at, rh));
at = AffineTransform.getScaleInstance(.5, .5);
mOps.put("Scale .5, .5", new AffineTransformOp(at, null));
at = AffineTransform.getRotateInstance(Math.PI / 6);
mOps.put("Rotate bilinear (origin)", new AffineTransformOp(at, rh));
}
private void createLookups() {
short[] brighten = new short[256];
short[] betterBrighten = new short[256];
short[] posterize = new short[256];
short[] invert = new short[256];
short[] straight = new short[256];
short[] zero = new short[256];
for (int i = 0; i < 256; i++) {
brighten[i] = (short) (128 + i / 2);
betterBrighten[i] = (short) (Math.sqrt((double) i / 255.0) * 255.0);
posterize[i] = (short) (i - (i % 32));
invert[i] = (short) (255 - i);
straight[i] = (short) i;
zero[i] = (short) 0;
}
mOps.put("Brighten", new LookupOp(new ShortLookupTable(0, brighten),
null));
mOps.put("Better Brighten", new LookupOp(new ShortLookupTable(0,
betterBrighten), null));
mOps.put("Posterize", new LookupOp(new ShortLookupTable(0, posterize),
null));
mOps.put("Invert", new LookupOp(new ShortLookupTable(0, invert), null));
short[][] redOnly = { invert, straight, straight };
short[][] greenOnly = { straight, invert, straight };
short[][] blueOnly = { straight, straight, invert };
mOps.put("Red invert", new LookupOp(new ShortLookupTable(0, redOnly),
null));
mOps.put("Green invert", new LookupOp(
new ShortLookupTable(0, greenOnly), null));
mOps.put("Blue invert", new LookupOp(new ShortLookupTable(0, blueOnly),
null));
short[][] redRemove = { zero, straight, straight };
short[][] greenRemove = { straight, zero, straight };
short[][] blueRemove = { straight, straight, zero };
mOps.put("Red remove", new LookupOp(new ShortLookupTable(0, redRemove),
null));
mOps.put("Green remove", new LookupOp(new ShortLookupTable(0,
greenRemove), null));
mOps.put("Blue remove", new LookupOp(
new ShortLookupTable(0, blueRemove), null));
}
private void createRescales() {
mOps.put("Rescale .5, 0", new RescaleOp(.5f, 0, null));
mOps.put("Rescale .5, 64", new RescaleOp(.5f, 64, null));
mOps.put("Rescale 1.2, 0", new RescaleOp(1.2f, 0, null));
mOps.put("Rescale 1.5, 0", new RescaleOp(1.5f, 0, null));
}
private void createColorOps() {
mOps.put("Grayscale", new ColorConvertOp(ColorSpace
.getInstance(ColorSpace.CS_GRAY), null));
}
private void createImageFrame(String imageFile) {
// Create the image frame.
mSplitImageComponent = new SplitImageComponent(imageFile);
mImageFrame = new Frame(imageFile);
mImageFrame.setLayout(new BorderLayout());
mImageFrame.add(mSplitImageComponent, BorderLayout.CENTER);
// Utilities.sizeContainerToComponent(mImageFrame, mSplitImageComponent);
// Utilities.centerFrame(mImageFrame);
mImageFrame.setVisible(true);
}
private void createUI() {
setFont(new Font("Serif", Font.PLAIN, 12));
setLayout(new BorderLayout());
// Set our location to the left of the image frame.
setSize(200, 350);
Point pt = mImageFrame.getLocation();
setLocation(pt.x - getSize().width, pt.y);
final Checkbox accumulateCheckbox = new Checkbox("Accumulate", false);
final Label statusLabel = new Label("");
// Make a sorted list of the operators.
Enumeration e = mOps.keys();
Vector names = new Vector();
while (e.hasMoreElements())
names.addElement(e.nextElement());
Collections.sort(names);
final java.awt.List list = new java.awt.List();
for (int i = 0; i < names.size(); i++)
list.add((String) names.elementAt(i));
add(list, BorderLayout.CENTER);
// When an item is selected, do the corresponding transformation.
list.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent ie) {
if (ie.getStateChange() != ItemEvent.SELECTED)
return;
String key = list.getSelectedItem();
BufferedImageOp op = (BufferedImageOp) mOps.get(key);
BufferedImage source = mSplitImageComponent.getSecondImage();
boolean accumulate = accumulateCheckbox.getState();
if (source == null || accumulate == false)
source = mSplitImageComponent.getImage();
String previous = mImageFrame.getTitle() + " + ";
if (accumulate == false)
previous = "";
mImageFrame.setTitle(previous + key);
statusLabel.setText("Performing " + key + "...");
list.setEnabled(false);
accumulateCheckbox.setEnabled(false);
BufferedImage destination = op.filter(source, null);
mSplitImageComponent.setSecondImage(destination);
mSplitImageComponent.setSize(mSplitImageComponent
.getPreferredSize());
mImageFrame.setSize(mImageFrame.getPreferredSize());
list.setEnabled(true);
accumulateCheckbox.setEnabled(true);
statusLabel.setText("Performing " + key + "...done.");
}
});
Button loadButton = new Button("Load...");
loadButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
FileDialog fd = new FileDialog(Sampler.this);
fd.show();
if (fd.getFile() == null)
return;
String path = fd.getDirectory() + fd.getFile();
mSplitImageComponent.setImage(path);
mSplitImageComponent.setSecondImage(null);
// Utilities.sizeContainerToComponent(mImageFrame,
// mSplitImageComponent);
mImageFrame.validate();
mImageFrame.repaint();
}
});
Panel bottom = new Panel(new GridLayout(2, 1));
Panel topBottom = new Panel();
topBottom.add(accumulateCheckbox);
topBottom.add(loadButton);
bottom.add(topBottom);
bottom.add(statusLabel);
add(bottom, BorderLayout.SOUTH);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
mImageFrame.dispose();
dispose();
System.exit(0);
}
});
}
class SplitImageComponent extends JPanel {
private BufferedImage mImage;
private BufferedImage mSecondImage;
private int mSplitX;
public SplitImageComponent(String path) {
setImage(path);
init();
}
public SplitImageComponent(BufferedImage image) {
setImage(image);
init();
}
public void setImage(String path) {
Image image = blockingLoad(path);
mImage = makeBufferedImage(image);
}
public void setImage(BufferedImage image) {
mImage = image;
}
public void setSecondImage(BufferedImage image) {
mSecondImage = image;
repaint();
}
public BufferedImage getImage() {
return mImage;
}
public BufferedImage getSecondImage() {
return mSecondImage;
}
private void init() {
setBackground(Color.white);
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
mSplitX = me.getX();
repaint();
}
});
addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent me) {
mSplitX = me.getX();
repaint();
}
});
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
int width = getSize().width;
int height = getSize().height;
// Explicitly clear the window.
Rectangle clear = new Rectangle(0, 0, width, height);
g2.setPaint(getBackground());
g2.fill(clear);
// Clip the first image, if appropriate,
// to be on the right side of the split.
if (mSplitX != 0 && mSecondImage != null) {
Rectangle firstClip = new Rectangle(mSplitX, 0, width - mSplitX,
height);
g2.setClip(firstClip);
}
g2.drawImage(getImage(), 0, 0, null);
if (mSplitX == 0 || mSecondImage == null)
return;
Rectangle secondClip = new Rectangle(0, 0, mSplitX, height);
g2.setClip(secondClip);
g2.drawImage(mSecondImage, 0, 0, null);
Line2D splitLine = new Line2D.Float(mSplitX, 0, mSplitX, height);
g2.setClip(null);
g2.setColor(Color.white);
g2.draw(splitLine);
}
public Dimension getPreferredSize() {
int width = getImage().getWidth();
int height = getImage().getHeight();
if (mSecondImage != null) {
width = Math.max(width, mSecondImage.getWidth());
height = Math.max(height, mSecondImage.getHeight());
}
return new Dimension(width, height);
}
}
private Component sComponent = new Component() {
};
private final MediaTracker sTracker = new MediaTracker(sComponent);
private int sID = 0;
public boolean waitForImage(Image image) {
int id;
synchronized (sComponent) {
id = sID++;
}
sTracker.addImage(image, id);
try {
sTracker.waitForID(id);
} catch (InterruptedException ie) {
return false;
}
if (sTracker.isErrorID(id))
return false;
return true;
}
public Image blockingLoad(String path) {
Image image = Toolkit.getDefaultToolkit().getImage(path);
if (waitForImage(image) == false)
return null;
return image;
}
public Image blockingLoad(URL url) {
Image image = Toolkit.getDefaultToolkit().getImage(url);
if (waitForImage(image) == false)
return null;
return image;
}
public BufferedImage makeBufferedImage(Image image) {
return makeBufferedImage(image, BufferedImage.TYPE_INT_RGB);
}
public BufferedImage makeBufferedImage(Image image, int imageType) {
if (waitForImage(image) == false)
return null;
BufferedImage bufferedImage = new BufferedImage(image.getWidth(null),
image.getHeight(null), imageType);
Graphics2D g2 = bufferedImage.createGraphics();
g2.drawImage(image, null, null);
return bufferedImage;
}
}
|