Mega Code Archive

 
Categories / Java / 2D Graphics GUI
 

Scale Test

import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.net.URL; import javax.imageio.ImageIO; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.SwingUtilities; /*  * ScaleTest_2008.java  *  * Created on May 1, 2007, 4:42 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.  */ /**  *  * @author Chet  */ public class ScaleTest_2008 extends JComponent {          private static final int FULL_SIZE = 190;     private static final int PADDING = 5;     private static final int QUAD_SIZE = FULL_SIZE / 2;     private static final double SCALE_FACTOR = .17;     private static BufferedImage originalImage =              new BufferedImage(FULL_SIZE, FULL_SIZE, BufferedImage.TYPE_INT_RGB);     boolean originalImagePainted = false;          /**      * Paints the test image that will be downscaled and timed by the various      * scaling methods. A different image is rendered into each of the four      * quadrants of this image: RGB stripes, a picture, vector art, and       * a black and white grid.      */     private void paintOriginalImage() {         Graphics g = originalImage.getGraphics();         // Erase to black         g.setColor(Color.BLACK);         g.fillRect(0, 0, FULL_SIZE, FULL_SIZE);                  // RGB quadrant         for (int i = 0; i < QUAD_SIZE; i += 3) {             int x = i;             g.setColor(Color.RED);             g.drawLine(x, 0, x, QUAD_SIZE);             x++;             g.setColor(Color.GREEN);             g.drawLine(x, 0, x, QUAD_SIZE);             x++;             g.setColor(Color.BLUE);             g.drawLine(x, 0, x, QUAD_SIZE);         }                  // Picture quadrant         try {             URL url = getClass().getResource("BBGrayscale.png");             BufferedImage picture = ImageIO.read(url);             // Center picture in quadrant area             int xDiff = QUAD_SIZE - picture.getWidth();             int yDiff = QUAD_SIZE - picture.getHeight();             g.drawImage(picture, QUAD_SIZE + xDiff/2, yDiff/2, null);         } catch (Exception e) {             System.out.println("Problem reading image file: " + e);         }                  // Vector drawing quadrant         g.setColor(Color.WHITE);         g.fillRect(0, QUAD_SIZE, QUAD_SIZE, QUAD_SIZE);         g.setColor(Color.BLACK);         g.drawOval(2, QUAD_SIZE + 2, QUAD_SIZE-4, QUAD_SIZE-4);         g.drawArc(20, QUAD_SIZE + 20, (QUAD_SIZE - 40), QUAD_SIZE - 40,                  190, 160);         int eyeSize = 7;         int eyePos = 30 - (eyeSize / 2);         g.fillOval(eyePos, QUAD_SIZE + eyePos, eyeSize, eyeSize);         g.fillOval(QUAD_SIZE - eyePos - eyeSize, QUAD_SIZE + eyePos,                  eyeSize, eyeSize);                  // B&W grid         g.setColor(Color.WHITE);         g.fillRect(QUAD_SIZE + 1, QUAD_SIZE + 1, QUAD_SIZE, QUAD_SIZE);         g.setColor(Color.BLACK);         for (int i = 0; i < QUAD_SIZE; i += 4) {             int pos = QUAD_SIZE + i;             g.drawLine(pos, QUAD_SIZE + 1, pos, FULL_SIZE);             g.drawLine(QUAD_SIZE + 1, pos, FULL_SIZE, pos);         }                  originalImagePainted = true;     }          /**      * Progressive bilinear scaling: for any downscale size, scale      * iteratively by halves using BILINEAR filtering until the proper       * size is reached.      */     private BufferedImage getOptimalScalingImage(BufferedImage inputImage,             int startSize, int endSize) {         int currentSize = startSize;         BufferedImage currentImage = inputImage;         int delta = currentSize - endSize;         int nextPow2 = currentSize >> 1;         while (currentSize > 1) {             if (delta <= nextPow2) {                 if (currentSize != endSize) {                     BufferedImage tmpImage = new BufferedImage(endSize,                             endSize, BufferedImage.TYPE_INT_RGB);                     Graphics g = tmpImage.getGraphics();                     ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION,                              RenderingHints.VALUE_INTERPOLATION_BILINEAR);                     g.drawImage(currentImage, 0, 0, tmpImage.getWidth(),                              tmpImage.getHeight(), null);                     currentImage = tmpImage;                 }                 return currentImage;             } else {                 BufferedImage tmpImage = new BufferedImage(currentSize >> 1,                         currentSize >> 1, BufferedImage.TYPE_INT_RGB);                 Graphics g = tmpImage.getGraphics();                 ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION,                          RenderingHints.VALUE_INTERPOLATION_BILINEAR);                 g.drawImage(currentImage, 0, 0, tmpImage.getWidth(),                          tmpImage.getHeight(), null);                 currentImage = tmpImage;                 currentSize = currentImage.getWidth();                 delta = currentSize - endSize;                 nextPow2 = currentSize >> 1;             }         }         return currentImage;     }          /**      * Progressive Bilinear approach: this method gets each scaled version from      * the getOptimalScalingImage method and copies it into place.      */     private void drawBetterImage(Graphics g, int yLoc) {         int xLoc = 100;         int delta = (int)(SCALE_FACTOR * FULL_SIZE);         for (int scaledSize = FULL_SIZE; scaledSize > 0; scaledSize -= delta) {             Image scaledImage = getOptimalScalingImage(originalImage, FULL_SIZE, scaledSize);             g.drawImage(scaledImage, xLoc, yLoc + (FULL_SIZE - scaledSize)/2,                      null);             xLoc += scaledSize + 20;         }     }          /**      * This approach uses either the getScaledInstance() approach to get      * each new size or it scales on the fly using drawImage().      */     private void drawImage(Graphics g, int yLoc, boolean getScaled) {         int xLoc = 100;         int delta = (int)(SCALE_FACTOR * FULL_SIZE);         if (getScaled) {             for (int scaledSize = FULL_SIZE; scaledSize > 0; scaledSize -= delta) {                 Image scaledImage = originalImage.getScaledInstance(scaledSize,                         scaledSize, Image.SCALE_AREA_AVERAGING);                 g.drawImage(scaledImage, xLoc, yLoc + (FULL_SIZE - scaledSize)/2,                          null);                 xLoc += scaledSize + 20;             }         } else {             for (int scaledSize = FULL_SIZE; scaledSize > 0; scaledSize -= delta) {                 g.drawImage(originalImage, xLoc, yLoc + (FULL_SIZE - scaledSize)/2,                          scaledSize, scaledSize, null);                 xLoc += scaledSize + 20;             }         }     }          /**      * Scale the image to several smaller sizes using each of the approaches      * and time each series of operations. The times are output into the      * application window for each row that they represent.      */     protected void paintComponent(Graphics g) {         if (!originalImagePainted) {             paintOriginalImage();         }         long startTime, endTime, totalTime;         int xLoc, yLoc;                  // Draw scaled versions with nearest neighbor         xLoc = 5;         yLoc = 20;         startTime = System.nanoTime();         drawImage(g, yLoc, false);         endTime = System.nanoTime();         totalTime = (endTime - startTime) / 1000000;         g.drawString("NEAREST ", xLoc, yLoc + (FULL_SIZE / 2));         g.drawString(Long.toString(totalTime) + " ms",                  xLoc, yLoc + (FULL_SIZE / 2) + 15);         System.out.println("NEAREST: " + (endTime - startTime) / 1000000);         // BILINEAR         yLoc += FULL_SIZE + PADDING;         ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION,                  RenderingHints.VALUE_INTERPOLATION_BILINEAR);         startTime = System.nanoTime();         drawImage(g, yLoc, false);         endTime = System.nanoTime();         totalTime = (endTime - startTime) / 1000000;         g.drawString("BILINEAR ", xLoc, yLoc + (FULL_SIZE / 2));         g.drawString(Long.toString(totalTime) + " ms",                  xLoc, yLoc + (FULL_SIZE / 2) + 15);         System.out.println("BILINEAR: " + (endTime - startTime) / 1000000);         // BIDUBIC         yLoc += FULL_SIZE + PADDING;         ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION,                  RenderingHints.VALUE_INTERPOLATION_BICUBIC);         startTime = System.nanoTime();         drawImage(g, yLoc, false);         endTime = System.nanoTime();         totalTime = (endTime - startTime) / 1000000;         g.drawString("BICUBIC ", xLoc, yLoc + (FULL_SIZE / 2));         g.drawString(Long.toString(totalTime) + " ms",                  xLoc, yLoc + (FULL_SIZE / 2) + 15);         System.out.println("BICUBIC: " + (endTime - startTime) / 1000000);         // getScaledInstance()         yLoc += FULL_SIZE + PADDING;         ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION,                  RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);         startTime = System.nanoTime();         drawImage(g, yLoc, true);         endTime = System.nanoTime();         totalTime = (endTime - startTime) / 1000000;         g.drawString("getScaled ", xLoc, yLoc + (FULL_SIZE / 2));         g.drawString(Long.toString(totalTime) + " ms",                  xLoc, yLoc + (FULL_SIZE / 2) + 15);         System.out.println("getScaled: " + (endTime - startTime) / 1000000);         // Progressive Bilinear         yLoc += FULL_SIZE + PADDING;         startTime = System.nanoTime();         drawBetterImage(g, yLoc);         endTime = System.nanoTime();         totalTime = (endTime - startTime) / 1000000;         g.drawString("Progressive ", xLoc, yLoc + (FULL_SIZE / 2));         g.drawString(Long.toString(totalTime) + " ms",                  xLoc, yLoc + (FULL_SIZE / 2) + 15);         System.out.println("faster: " + (endTime - startTime) / 1000000);         // Draw image sizes         xLoc = 100;         int delta = (int)(SCALE_FACTOR * FULL_SIZE);         for (int scaledSize = FULL_SIZE; scaledSize > 0; scaledSize -= delta) {             g.drawString(scaledSize + " x " + scaledSize,                      xLoc + Math.max(0, scaledSize/2 - 20), 15);             xLoc += scaledSize + 20;         }     }     private static void createAndShowGUI() {         JFrame f = new JFrame();         f.setLayout(new BorderLayout());         f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         f.setSize(900, 50 + (5 * FULL_SIZE) + (6 * PADDING));         ScaleTest_2008 test = new ScaleTest_2008();         f.add(test);                 f.setVisible(true);     }          public static void main(String args[]) {         Runnable doCreateAndShowGUI = new Runnable() {             public void run() {                 createAndShowGUI();             }         };         SwingUtilities.invokeLater(doCreateAndShowGUI);     } }