package com.macmillan.nmeyers; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import java.util.*; import java.io.*; import javax.swing.*; import java.awt.event.*; public class SlideShow extends JFrame { /* * SlideShow: View a collection of graphical images * * Author: Nathan Meyers, nmeyers@javalinux.net * $Id: SlideShow.java,v 1.5 1999/11/07 22:23:50 nathanm Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * with this program. If not, the license is available from the * GNU project, at http://www.gnu.org. */ // // SlideShow: View a collection of graphical images (gif, jpeg, etc.) // specified in stdin. Optionally scales the images to the window // size, and optionally sharpens the images. // // Supported image types are determined by the Java environment itself; // if we can read the image with Toolkit.createImage, we can view it. // // Usage: SlideShow [ width height ] // // SlideShow reads the entire list of images from stdin before beginning. // LinkedList slides; int slideIndex = 0; Slide slide; JButton firstButton; JButton leftButton; JToggleButton rescale, sharpen; JButton rightButton; JButton lastButton; public SlideShow(LinkedList inputFiles, int width, int height) { slides = inputFiles; Box box1 = Box.createVerticalBox(); getContentPane().add(box1); Box box2 = Box.createHorizontalBox(); box1.add(box2); box1.add(slide = new Slide(width, height)); box2.add(Box.createHorizontalGlue()); firstButton = new JButton("First"); firstButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (slideIndex > 0) { slideIndex = 0; slide.showSlide((String)slides.get(0)); leftButton.setEnabled(slideIndex > 0); rightButton.setEnabled(slideIndex < slides.size() - 1); } } }); box2.add(firstButton); box2.add(Box.createHorizontalGlue()); leftButton = new JButton("Previous"); leftButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (slideIndex > 0) { slide.showSlide((String)slides.get(--slideIndex)); leftButton.setEnabled(slideIndex > 0); rightButton.setEnabled(slideIndex < slides.size() - 1); } } }); box2.add(leftButton); box2.add(Box.createHorizontalGlue()); rescale = new JToggleButton("Rescale"); rescale.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { slide.reshowSlide(); } }); box2.add(rescale); box2.add(Box.createHorizontalGlue()); sharpen = new JToggleButton("Sharpen"); sharpen.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { slide.reshowSlide(); } }); box2.add(sharpen); box2.add(Box.createHorizontalGlue()); rightButton = new JButton("Next"); rightButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (slideIndex < slides.size() - 1) { slide.showSlide((String)slides.get(++slideIndex)); leftButton.setEnabled(slideIndex > 0); rightButton.setEnabled(slideIndex < slides.size() - 1); } } }); box2.add(rightButton); box2.add(Box.createHorizontalGlue()); lastButton = new JButton("Last"); lastButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (slideIndex < slides.size() - 1) { slideIndex = slides.size() - 1; slide.showSlide((String)slides.get(slideIndex)); leftButton.setEnabled(slideIndex > 0); rightButton.setEnabled(slideIndex < slides.size() - 1); } } }); box2.add(lastButton); box2.add(Box.createHorizontalGlue()); if (slides.size() > 0) slide.showSlide((String)slides.get(0)); else { firstButton.setEnabled(false); lastButton.setEnabled(false); } leftButton.setEnabled(false); rightButton.setEnabled(slides.size() > 1); } public class Slide extends JComponent implements ImageObserver { int width, height; Image slide = null, transformedSlide; int imageWidth, imageHeight; boolean abort = false; public Slide(int w, int h) { width = w; height = h; addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { Dimension d = getSize(); width = d.width; height = d.height; reshowSlide(); } }); } private Dimension getSlideDimension() { abort = false; imageWidth = slide.getWidth(this); imageHeight = slide.getHeight(this); while (!abort && (imageWidth == -1 || imageHeight == -1)) { // Dimensions not available yet. Wait for other thread to // finish loading the image synchronized(this) { try { wait(); } catch (InterruptedException e) {} imageWidth = slide.getWidth(this); imageHeight = slide.getHeight(this); } } return new Dimension(imageWidth, imageHeight); } public boolean imageUpdate(Image img, int infoflags, int x, int y, int wid, int ht) { // We hang out here waiting for the width and height to // become available if ((infoflags & (ImageObserver.ABORT | ImageObserver.ERROR)) != 0) abort= true; boolean result = super.imageUpdate(img, infoflags, x, y, wid, ht); synchronized(this) { notifyAll(); } return result; } public Dimension getPreferredSize() { return new Dimension(width, height); } public void showSlide(String filename) { setTitle(filename); // Read our original image slide = Toolkit.getDefaultToolkit().createImage(filename); reshowSlide(); } public void reshowSlide() { if (slide == null) return; transformedSlide = slide; // If we want to rescale, set up the filter if (rescale.isSelected()) { // Find our current image size Dimension dim = getSlideDimension(); if (dim == null) return; double xscale = (double)width / (double)dim.width; double yscale = (double)height / (double)dim.height; double xyscale = Math.min(xscale, yscale); // Set hints for maximum quality RenderingHints hints = new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); hints.add( new RenderingHints( RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY)); ImageFilter rescaleFilter = new BufferedImageFilter( new AffineTransformOp( AffineTransform.getScaleInstance(xyscale, xyscale), hints)); transformedSlide = Toolkit.getDefaultToolkit().createImage( new FilteredImageSource( transformedSlide.getSource(), rescaleFilter)); } // If we want to sharpen, set up the filter if (sharpen.isSelected()) { float ctr = 2, offc = -.125f; ImageFilter sharpenFilter = new BufferedImageFilter( new ConvolveOp( new Kernel(3, 3, new float[] { offc, offc, offc, offc, ctr , offc, offc, offc, offc }))); transformedSlide = Toolkit.getDefaultToolkit().createImage( new FilteredImageSource( transformedSlide.getSource(), sharpenFilter)); } repaint(); } public void paintComponent(Graphics g) { g.drawImage(transformedSlide, 0, 0, this); } } static public void main(String[] argv) { int width = 100, height = 100; // Handle the args if (argv.length == 2) { try { width = Integer.parseInt(argv[0]); height = Integer.parseInt(argv[1]); } catch (NumberFormatException e) { usage(); } } else if (argv.length != 0) usage(); // Build our list of input files LinkedList inputFiles = new LinkedList(); BufferedReader reader = new BufferedReader( new InputStreamReader(System.in)); // Read words until we can't... could use StreamTokenizer here, // but its defaults are too strange for this. try { for (;;) { // Skip whitespace int ch; while ((ch = reader.read()) != -1 && Character.isWhitespace((char)ch)); if (ch == -1) break; StringBuffer buffer = new StringBuffer(); // Read a filename buffer.append((char)ch); while ((ch = reader.read()) != -1 && !Character.isWhitespace((char)ch)) buffer.append((char)ch); // Add to the list inputFiles.add(buffer.toString()); if (ch == -1) break; } } catch (IOException e) {} SlideShow slideShow = new SlideShow(inputFiles, width, height); slideShow.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent ev) { System.exit(0); } }); slideShow.pack(); slideShow.setVisible(true); } static public void usage() { System.err.println("Usage: SlideShow [ ]"); System.exit(1); } }