Sampler.java Source code

Java tutorial

Introduction

Here is the source code for Sampler.java

Source

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;
    }

}