ImageDicer.java
//Comment out the following package statement to compile separately. //package com.javaworld.media.j2d; /** * ImageDicer provides a grab-bag of image processing operators. * This version is compliant with Java 1.2 Beta 4, Aug 1998. * Please refer to: * http://www.javaworld.com/javaworld/jw-09-1998/jw-09-media.html * * @author Jonathan Knudsen <jonathan@oreilly.com> * @author Bill Day <bill.day@javaworld.com> * @version 1.0 * @see java.awt.image.BufferedImage * @see java.awt.image.BufferedImageOp * @see java.awt.image.ConvolveOp * @see java.awt.image.LookupOp * @see java.awt.image.ThresholdOp **/ import java.awt.*; import java.awt.event.*; import java.awt.image.*; import java.util.*; public class ImageDicer extends Frame { /** * Instantiates an ImageDicer with an image file name. * If no image file name is specified on the command line, * "default" is used. **/ public static void main(String[] args) { String fileName = "penquin2.jpg"; if (args.length > 0) fileName = args[0]; new ImageDicer(fileName); } /** * kBanner holds the application title which is used * in the window title. **/ private static final String kBanner = "ImageDicer v1.0"; /** * ImageDicer's constructor creates a set of image * processing operations, creates user controls, and loads * the named image. **/ public ImageDicer(String fileName) { super(kBanner); createOps(); createUI(); loadImage(fileName); setVisible(true); } /** * A Hashtable member variable holds the image processing * operations, keyed by their names. **/ private Hashtable mOps; /** * The createOps() method creates the image processing * operations discussed in the column. **/ private void createOps() { // Create a brand new Hashtable to hold the operations. mOps = new Hashtable(); // Blurring 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))); // Edge detection float[] edgeKernel = { 0.0f, -1.0f, 0.0f, -1.0f, 4.0f, -1.0f, 0.0f, -1.0f, 0.0f }; mOps.put("Edge detector", new ConvolveOp( new Kernel(3, 3, edgeKernel))); // Sharpening float[] sharpKernel = { 0.0f, -1.0f, 0.0f, -1.0f, 5.0f, -1.0f, 0.0f, -1.0f, 0.0f }; mOps.put("Sharpen", new ConvolveOp( new Kernel(3, 3, sharpKernel), ConvolveOp.EDGE_NO_OP, null)); // Lookup table operations: posterizing and inversion. short[] posterize = new short[256]; short[] invert = new short[256]; short[] straight = new short[256]; for (int i = 0; i < 256; i++) { posterize[i] = (short)(i - (i % 32)); invert[i] = (short)(255 - i); straight[i] = (short)i; } mOps.put("Posterize", new LookupOp(new ShortLookupTable(0, posterize),null)); mOps.put("Invert", new LookupOp(new ShortLookupTable(0, invert), null)); short[][] blueInvert = new short[][] { straight, straight, invert }; mOps.put("Invert blue", new LookupOp(new ShortLookupTable(0, blueInvert), null)); // Thresholding mOps.put("Threshold 192", createThresholdOp(192, 0, 255)); mOps.put("Threshold 128", createThresholdOp(128, 0, 255)); mOps.put("Threshold 64", createThresholdOp(64, 0, 255)); } /** * createThresholdOp() uses a LookupOp to simulate a * thresholding operation. **/ private BufferedImageOp createThresholdOp(int threshold, int minimum, int maximum) { short[] thresholdArray = new short[256]; for (int i = 0; i < 256; i++) { if (i < threshold) thresholdArray[i] = (short)minimum; else thresholdArray[i] = (short)maximum; } return new LookupOp(new ShortLookupTable(0, thresholdArray), null); } /** * A member variable, mControlPanel, keeps track of the panel * that contains the user controls. This panel's size has to * be accounted for later when we size the window to fit the * image. **/ private Panel mControlPanel; /** * createUI() creates the user controls and lays out the window. * It also creates the event handlers (as inner classes) for * the user controls. **/ private void createUI() { setFont(new Font("Serif", Font.PLAIN, 12)); // Use a BorderLayout. The image will occupy most of the window, // with the user controls at the bottom. setLayout(new BorderLayout()); // Use a Label to display status messages to the user. final Label statusLabel = new Label("Welcome to " + kBanner + "."); // Create a list of operations. final Choice processChoice = new Choice(); Enumeration e = mOps.keys(); // Add all the operation names from the Hashtable. while (e.hasMoreElements()) processChoice.add((String)e.nextElement()); // Add an event listener. This is where the image processing // actually occurs. processChoice.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent ie) { if (ie.getStateChange() != ItemEvent.SELECTED) return; String key = processChoice.getSelectedItem(); statusLabel.setText("Working..."); BufferedImageOp op = (BufferedImageOp)mOps.get(key); mBufferedImage = op.filter(mBufferedImage, null); statusLabel.setText(""); repaint(); } }); // Create a Button for loading a new image. Button loadButton = new Button("Load..."); // Add a listener for the button. It pops up a file dialog // and loads the selected image file. loadButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { FileDialog fd = new FileDialog(ImageDicer.this); fd.setVisible(true); if (fd.getFile() == null) return; String path = fd.getDirectory() + fd.getFile(); loadImage(path); } }); // Add the user controls at the bottom of the window. mControlPanel = new Panel(); mControlPanel.add(loadButton); mControlPanel.add(processChoice); mControlPanel.add(statusLabel); add(mControlPanel, BorderLayout.SOUTH); // Terminate the application if the user closes the window. addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { dispose(); System.exit(0); } }); } /** * When an image is loaded, the window is resized to * accomodate the image size and the user controls. **/ private void adjustToImageSize() { if (!isDisplayable()) addNotify(); // Do this to get valid Insets. Insets insets = getInsets(); int w = mBufferedImage.getWidth() + insets.left + insets.right; int h = mBufferedImage.getHeight() + insets.top + insets.bottom; h += mControlPanel.getPreferredSize().height; setSize(w, h); } /** * Center this window in the user's desktop. **/ private void center() { Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); Dimension d = getSize(); int x = (screen.width - d.width) / 2; int y = (screen.height - d.height) / 2; setLocation(x, y); } /** * This member variable holds the currently displayed image. **/ private BufferedImage mBufferedImage; /** * loadImage() loads an image, using a MediaTracker to * ensure that the image data is fully loaded. Then it * converts the image to a BufferedImage. Finally, it * adjusts the window size and placement based on the * new image size. **/ private void loadImage(String fileName) { // Use a MediaTracker to fully load the image. Image image = Toolkit.getDefaultToolkit().getImage(fileName); MediaTracker mt = new MediaTracker(this); mt.addImage(image, 0); try { mt.waitForID(0); } catch (InterruptedException ie) { return; } if (mt.isErrorID(0)) return; // Make a BufferedImage from the Image. mBufferedImage = new BufferedImage( image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB); Graphics2D g2 = mBufferedImage.createGraphics(); g2.drawImage(image, null, null); adjustToImageSize(); center(); validate(); repaint(); setTitle(kBanner + ": " + fileName); } /** * All paint() has to do is show the current image. **/ public void paint(Graphics g) { if (mBufferedImage == null) return; Insets insets = getInsets(); g.drawImage(mBufferedImage, insets.left, insets.top, null); } }
Maintained by John Loomis, updated Thu Nov 29 12:44:22 2012