Mega Code Archive

 
Categories / Java / Advanced Graphics
 

Image Zooming

import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.File; import java.util.ArrayList; import java.util.List; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JSlider; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.jdesktop.animation.timing.Animator; import org.jdesktop.animation.transitions.Effect; import org.jdesktop.animation.transitions.EffectsManager; import org.jdesktop.animation.transitions.EffectsManager.TransitionType; import org.jdesktop.animation.transitions.ScreenTransition; import org.jdesktop.animation.transitions.TransitionTarget; import org.jdesktop.animation.transitions.effects.CompositeEffect; import org.jdesktop.animation.transitions.effects.Move; import org.jdesktop.animation.transitions.effects.Scale; //import org.jdesktop.tools.io.FileTreeWalk; //import org.jdesktop.tools.io.FileTreeWalker; //import org.jdesktop.tools.io.UnixGlobFileFilter; import java.io.FileFilter; import java.io.File; import java.util.regex.Pattern; import java.util.regex.Matcher; /*  * ImageBrowser.java  *  * Created on May 3, 2007, 3:11 PM  *  * Copyright (c) 2007, Sun Microsystems, Inc  * All rights reserved.  *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  *  *   * Redistributions of source code must retain the above copyright  *     notice, this list of conditions and the following disclaimer.  *   * Redistributions in binary form must reproduce the above  *     copyright notice, this list of conditions and the following  *     disclaimer in the documentation and/or other materials provided  *     with the distribution.  *   * Neither the name of the TimingFramework project nor the names of its  *     contributors may be used to endorse or promote products derived  *     from this software without specific prior written permission.  *  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */ /**  * This demo of the AnimatedTransitions library uses a layout manager  * to assist in setting up the next screen that the application  * transitions to.  *  * The slider in the window controls the picture thumbnail size. The  * standard FlowLayout manager organizes the pictures according to  * the thumbnail sizes. The transition animates the change from  * one thumbnail size to the next.  *  * @author Chet  */ public class ImageBrowser extends JComponent          implements TransitionTarget, ChangeListener {          private static final int SLIDER_INCREMENT = 50;     int numPictures = 40;     JLabel label[];     Animator animator = new Animator(500);     ScreenTransition transition = new ScreenTransition(this, this, animator);     Dimension newSize = new Dimension();     List<ImageHolder> images = new ArrayList<ImageHolder>();     static int currentSize = 50;     GradientPaint bgGradient = null;     int prevHeight = 0;     static JSlider slider = new JSlider(1, 400 / SLIDER_INCREMENT,              1 + currentSize / SLIDER_INCREMENT);     static int numImages = 0;          /** Creates a new instance of ImageBrowser */     public ImageBrowser() {         setOpaque(true);         animator.setAcceleration(.1f);         animator.setDeceleration(.4f);         setLayout(new FlowLayout());         loadImages();         label = new JLabel[images.size()];         // For each image:         // - set the icon at the current thumbnail size         // - create/set a custom effect that will move/scale the         // images. Note that the main reason for the custom effect         // is that scaling effects typically redraw the actual component         // instead of using image tricks. In this case, image tricks are         // just fine. So the custom effect is purely an optimization here.         for (int i = 0; i < images.size(); ++i) {             label[i] = new JLabel();             label[i].setIcon(new ImageIcon(images.get(i).getImage(currentSize)));             add(label[i]);             Effect move = new Move();             Effect scale = new Scale();             CompositeEffect comp = new CompositeEffect(move);             comp.addEffect(scale);             comp.setRenderComponent(false);             EffectsManager.setEffect(label[i], comp, TransitionType.CHANGING);         }     }     /**      * Paints a gradient in the background of this component      */     @Override     protected void paintComponent(Graphics g) {         if (getHeight() != prevHeight) {             prevHeight = getHeight();             bgGradient = new GradientPaint(0, 0,                      new Color(0xEBF4FA), 0, prevHeight, new Color(0xBBD9EE));         }         ((Graphics2D)g).setPaint(bgGradient);         g.fillRect(0, 0, getWidth(), prevHeight);     }          /**      * Loads all images found in the directory "images" (which therefore must      * be found in the folder in which this app runs).      */     private void loadImages() {         //try {             //File imagesDir = new File("images");             //FileTreeWalker walker = new FileTreeWalker(imagesDir,                //      new UnixGlobFileFilter("*.jpg"));             //walker.walk(new FileTreeWalk() {               //  public void walk(File path) {                     //numImages++;                     try {                         BufferedImage image = ImageIO.read(ImageBrowser.class.getResource("shanghai.jpg"));                         images.add(new ImageHolder(image));                     } catch (Exception e) {                         System.out.println("Problem loading images: " + e);                     }                 //}             //});         //} catch (Exception e) {           //  System.out.println("Problem loading images: " + e);         //}     }              /**      * TransitionTarget implementation: The setup for the next screen entails      * merely assigning a new icon to each JLabel with the new thumbnail      * size      */     public void setupNextScreen() {         for (int i = 0; i < images.size(); ++i) {             label[i].setIcon(new ImageIcon(images.get(i).getImage(currentSize)));         }         // revalidation is necessary for the LayoutManager to do its job         revalidate();     }          /**      * This method handles changes in slider state, which can come from either      * mouse manipulation of the slider or right/left keyboard events. This      * event changes the current thumbnail size and starts the transition.      * We will then receive a callback to setupNextScreen() where we set up      * the GUI according to this new thumbnail size.      */     public void stateChanged(ChangeEvent ce) {         currentSize = slider.getValue() * 25;         if (!transition.getAnimator().isRunning()) {             transition.start();         }     }          private static void createAndShowGUI() {   JFrame f = new JFrame("Image Browser");         f.setLayout(new BorderLayout());   f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   f.setSize(500, 400);   ImageBrowser component = new ImageBrowser();   f.add(component, BorderLayout.CENTER);         f.add(slider, BorderLayout.SOUTH);         slider.setBackground(new Color(0xBBD9EE));         slider.addChangeListener(component);   f.setVisible(true);     }     /**      * @param args the command line arguments      */     public static void main(String[] args) {         try {             UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());         } catch (ClassNotFoundException ex) {             ex.printStackTrace();         } catch (InstantiationException ex) {             ex.printStackTrace();         } catch (IllegalAccessException ex) {             ex.printStackTrace();         } catch (UnsupportedLookAndFeelException ex) {             ex.printStackTrace();         }   Runnable doCreateAndShowGUI = new Runnable() {       public void run() {     createAndShowGUI();       }   };   SwingUtilities.invokeLater(doCreateAndShowGUI);     } } /**  * This is a utility class that holds our images at various scaled  * sizes. The images are pre-scaled down by halves, using the progressive  * bilinear technique. Thumbnails from these images are requested  * from this class, which are created by down-scaling from the next-largest  * pre-scaled size available.  */ class ImageHolder {     private List<BufferedImage> scaledImages = new ArrayList<BufferedImage>();     private static final int MIN_SIZE = 50;         /**      * Given any image, this constructor creates and stores down-scaled      * versions of this image down to some MIN_SIZE      */     ImageHolder(BufferedImage originalImage) {         int imageW = originalImage.getWidth();         int imageH = originalImage.getHeight();         scaledImages.add(originalImage);         BufferedImage prevImage = originalImage;         while (imageW > MIN_SIZE && imageH > MIN_SIZE) {             imageW = imageW >> 1;             imageH = imageH >> 1;             BufferedImage scaledImage = new BufferedImage(imageW, imageH,                     prevImage.getType());             Graphics2D g2d = scaledImage.createGraphics();             g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,                     RenderingHints.VALUE_INTERPOLATION_BILINEAR);             g2d.drawImage(prevImage, 0, 0, imageW, imageH, null);             g2d.dispose();             scaledImages.add(scaledImage);         }     }          /**      * This method returns an image with the specified width. It finds      * the pre-scaled size with the closest/larger width and scales      * down from it, to provide a fast and high-quality scaed version      * at the requested size.      */     BufferedImage getImage(int width) {         for (BufferedImage scaledImage : scaledImages) {             int scaledW = scaledImage.getWidth();             // This is the one to scale from if:             // - the requested size is larger than this size             // - the requested size is between this size and              //   the next size down             // - this is the smallest (last) size             if (scaledW < width || ((scaledW >> 1) < width) ||                     (scaledW >> 1) < MIN_SIZE) {                 if (scaledW != width) {                     // Create new version scaled to this width                     // Set the width at this width, scale the                     // height proportional to the image width                     float scaleFactor = (float)width / scaledW;                     int scaledH = (int)(scaledImage.getHeight() *                              scaleFactor + .5f);                     BufferedImage image = new BufferedImage(width,                             scaledH, scaledImage.getType());                     Graphics2D g2d = image.createGraphics();                     g2d.setRenderingHint(                             RenderingHints.KEY_INTERPOLATION,                             RenderingHints.VALUE_INTERPOLATION_BILINEAR);                     g2d.drawImage(scaledImage, 0, 0,                              width, scaledH, null);                     g2d.dispose();                     scaledImage = image;                 }                 return scaledImage;             }         }         // shouldn't get here         return null;     } } /**  * Copyright (c) 2006, Sun Microsystems, Inc  * All rights reserved.  *   * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  *   *   * Redistributions of source code must retain the above copyright  *     notice, this list of conditions and the following disclaimer.  *   * Redistributions in binary form must reproduce the above  *     copyright notice, this list of conditions and the following   *     disclaimer in the documentation and/or other materials provided   *     with the distribution.  *   * Neither the name of the Harvester project nor the names of its  *     contributors may be used to endorse or promote products derived   *     from this software without specific prior written permission.  *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */ class UnixGlobFileFilter implements FileFilter {     private Pattern pattern;     public UnixGlobFileFilter(String filter) {         pattern = Pattern.compile(globToRegex(filter));     }     public boolean accept(File file) {         String path = file.getName();         Matcher matcher = pattern.matcher(path);         return matcher.matches();     }     private String globToRegex(String glob) {         char c = '\0';         boolean escape = false;         boolean enclosed = false;         StringBuffer buffer = new StringBuffer(glob.length());         for (int i = 0; i < glob.length(); i++) {             c = glob.charAt(i);             if (escape) {                 buffer.append('\\');                 buffer.append(c);                 escape = false;                 continue;             }             switch (c) {                 case '*':                     buffer.append('.').append('*');                     break;                 case '?':                     buffer.append('.');                     break;                 case '\\':                     escape = true;                     break;                 case '.':                     buffer.append('\\').append('.');                     break;                 case '{':                     buffer.append('(');                     enclosed = true;                     break;                 case '}':                     buffer.append(')');                     enclosed = false;                     break;                 case ',':                     if (enclosed)                         buffer.append('|');                     else                         buffer.append(',');                     break;                 default:                     buffer.append(c);             }         }         return buffer.toString();     } } /**  * Copyright (c) 2006, Sun Microsystems, Inc  * All rights reserved.  *   * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  *   *   * Redistributions of source code must retain the above copyright  *     notice, this list of conditions and the following disclaimer.  *   * Redistributions in binary form must reproduce the above  *     copyright notice, this list of conditions and the following   *     disclaimer in the documentation and/or other materials provided   *     with the distribution.  *   * Neither the name of the Harvester project nor the names of its  *     contributors may be used to endorse or promote products derived   *     from this software without specific prior written permission.  *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */ class FileTreeWalker {     private File path;     private static final FileFilter directoryFilter = new FileFilter() {         public boolean accept(File pathname) {             return pathname.isDirectory();         }     };     private FileFilter filter;     public FileTreeWalker(File path) throws IOException {         this(path, new FileFilter() {             public boolean accept(File pathname) {                 return pathname.isFile();             }         });     }     public FileTreeWalker(File path, FileFilter filter) throws IOException {         if (path == null || !path.exists() || path.isFile()) {             throw new IOException("Path " + path + " is not a valid directory.");         }         this.path = path;         this.filter = filter;     }     public void walk(FileTreeWalk walk) {         walkDirectory(walk, path);     }     private void walkDirectory(FileTreeWalk walk, File dir) {         File[] files = dir.listFiles(filter);         for (File file : files) {             walk.walk(file);         }         File[] dirs = dir.listFiles(directoryFilter);         for (File subDir : dirs) {             walkDirectory(walk, subDir);         }     } } /**  * Copyright (c) 2006, Sun Microsystems, Inc  * All rights reserved.  *   * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  *   *   * Redistributions of source code must retain the above copyright  *     notice, this list of conditions and the following disclaimer.  *   * Redistributions in binary form must reproduce the above  *     copyright notice, this list of conditions and the following   *     disclaimer in the documentation and/or other materials provided   *     with the distribution.  *   * Neither the name of the Harvester project nor the names of its  *     contributors may be used to endorse or promote products derived   *     from this software without specific prior written permission.  *   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */ interface FileTreeWalk {     public void walk(File path); }                               Filthy-Rich-Clients-ImageZooming.zip( 228 k)