import java.awt.Dimension; 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 java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.SwingUtilities; public class ImageScale3 extends JComponent { private BufferedImage image; private static final int PADDING = 20; private static final double SCALE_FACTOR = .1; private int scaleW, scaleH; public ImageScale3() { try { URL url = new URL("http://farm4.static.flickr.com/3609/3620307800_6e7d70f593_b.jpg"); image = ImageIO.read(url); scaleW = (int)(SCALE_FACTOR * image.getWidth()); scaleH = (int)(SCALE_FACTOR * image.getHeight()); setPreferredSize(new Dimension(PADDING + (3 * (scaleW + PADDING)), PADDING + (2 * (scaleH + PADDING)))); } catch (IOException e) { System.err.println("Image Loading ERROR: " + e); System.exit(0); } } private BufferedImage getOptimalScalingImage(BufferedImage inputImage, double scaleFactor) { // 現在のイメージのサイズ int currentWidth = inputImage.getWidth(); int currentHeight = inputImage.getHeight(); // 最終的なイメージのサイズ int endWidth = (int)(currentWidth * scaleFactor); int endHeight = (int)(currentHeight * scaleFactor); // 現在のイメージ BufferedImage currentImage = inputImage; // 最終的なサイズと現在のイメージの差 int delta = currentWidth - endWidth; // 次に縮小するサイズ int nextPow2 = currentWidth >> 1; while (currentWidth > 1) { // 最終的なイメージとサイズの差が、次に縮小するサイズよりも // 小さいかどうか調べる if (delta <= nextPow2) { // イメージのサイズの差が小さい場合 if (currentWidth != endWidth) { // 最終的な縮小率が 1/2n にならない場合 BufferedImage tmpImage = new BufferedImage(endWidth, endHeight, BufferedImage.TYPE_INT_RGB); Graphics2D g = (Graphics2D)tmpImage.getGraphics(); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(currentImage, 0, 0, tmpImage.getWidth(), tmpImage.getHeight(), null); g.dispose(); currentImage = tmpImage; } return currentImage; } else { // イメージのサイズの差が大きい場合 // 更に半分に縮小する BufferedImage tmpImage = new BufferedImage(currentWidth >> 1, currentHeight >> 1, BufferedImage.TYPE_INT_RGB); Graphics2D g = (Graphics2D)tmpImage.getGraphics(); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(currentImage, 0, 0, tmpImage.getWidth(), tmpImage.getHeight(), null); g.dispose(); // 変数の更新 currentImage = tmpImage; currentWidth = currentImage.getWidth(); currentHeight = currentImage.getHeight(); delta = currentWidth - endWidth; nextPow2 = currentWidth >> 1; } } return currentImage; } public void paintComponent(Graphics g) { int x = PADDING; int y = PADDING; Graphics2D g2d = (Graphics2D)g; // NEAREST NEIGHBOR g2d.drawString("NearestNeighbor", x, y - 4); long start = System.nanoTime(); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR); g2d.drawImage(image, x, y, scaleW, scaleH, null); long end = System.nanoTime(); System.out.println("Nearest Neighbor: " + (end - start)/1000000.0 + "ms"); // BILINEAR x += scaleW + PADDING; g2d.drawString("Bilinear", x, y - 4); start = System.nanoTime(); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g2d.drawImage(image, x, y, scaleW, scaleH, null); end = System.nanoTime(); System.out.println("Bilinear: " + (end - start)/1000000.0 + "ms"); // BICUBIC x += scaleW + PADDING; g2d.drawString("Bicubic", x, y - 4); start = System.nanoTime(); g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC); g2d.drawImage(image, x, y, scaleW, scaleH, null); end = System.nanoTime(); System.out.println("Bicubic: " + (end - start)/1000000.0 + "ms"); // getScaledInstance() DEFAULT x = PADDING; y += scaleH + PADDING; g2d.drawString("Default", x, y - 4); start = System.nanoTime(); Image scaledImg1 = image.getScaledInstance(scaleW, scaleH, Image.SCALE_DEFAULT); g.drawImage(scaledImg1, x, y, null); end = System.nanoTime(); System.out.println("Default: " + (end - start)/1000000.0 + "ms"); // getScaledInstance() SMOOTH x += scaleW + PADDING; g2d.drawString("Smooth", x, y - 4); start = System.nanoTime(); Image scaledImg2 = image.getScaledInstance(scaleW, scaleH, Image.SCALE_SMOOTH); g.drawImage(scaledImg2, x, y, null); end = System.nanoTime(); System.out.println("Smooth: " + (end - start)/1000000.0 + "ms"); // 最適 x += scaleW + PADDING; g2d.drawString("最適", x, y - 4); start = System.nanoTime(); Image scaledImg3 = getOptimalScalingImage(image, SCALE_FACTOR); g2d.drawImage(scaledImg3, x, y, null); end = System.nanoTime(); System.out.println("最適: " + (end - start)/1000000.0 + "ms"); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { JFrame frame = new JFrame("Image Scaling"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new ImageScale3()); frame.validate(); frame.pack(); frame.setVisible(true); } }); } }