2013-03-21 52 views
12

你好,我有一个QR码图像,我想调整它,当我尝试使用此代码把它调整到一个小图像,我总是得到一个blury图像和QR码不再有效时,我对其进行扫描,但是当我调整到一个大尺寸的图像具有相同的代码,它工作正常:如何调整图像在java中?

public BufferedImage getScaledInstance(BufferedImage img, 
            int targetWidth, 
            int targetHeight, 
            Object hint, 
            boolean higherQuality) 
{ 
int type = (img.getTransparency() == Transparency.OPAQUE) ? 
    BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; 
BufferedImage ret = (BufferedImage)img; 
int w, h; 
if (higherQuality) { 
    // Use multi-step technique: start with original size, then 
    // scale down in multiple passes with drawImage() 
    // until the target size is reached 
    w = img.getWidth(); 
    h = img.getHeight(); 
} else { 
    // Use one-step technique: scale directly from original 
    // size to target size with a single drawImage() call 
    w = targetWidth; 
    h = targetHeight; 
} 

do { 
    if (higherQuality && w > targetWidth) { 
     w /= 2; 
     if (w < targetWidth) { 
      w = targetWidth; 
     } 
    } 

    if (higherQuality && h > targetHeight) { 
     h /= 2; 
     if (h < targetHeight) { 
      h = targetHeight; 
     } 
    } 

    BufferedImage tmp = new BufferedImage(w, h, type); 
    Graphics2D g2 = tmp.createGraphics(); 
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); 
    //  g2.setRenderingHint(RenderingHints.KEY_DITHERING, hint); 
    g2.drawImage(ret, 0, 0, w, h, null); 
    g2.dispose(); 

    ret = tmp; 
} while (w != targetWidth || h != targetHeight); 

return ret; 
} 

是什么问题,我完全不明白,请给我至少一个提示,谢谢

+0

您还没有显示关键细节 - 您设置了什么插值提示! – 2013-03-21 21:37:33

+0

非常感谢,我的插值提示是RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR,我尝试了所有可能的值,仍然没有工作 – Walllzzz 2013-03-21 21:54:06

回答

23

我用仿射变换来实现这一任务,这里是我的代码,希望它有助于

/** 
* scale image 
* 
* @param sbi image to scale 
* @param imageType type of image 
* @param dWidth width of destination image 
* @param dHeight height of destination image 
* @param fWidth x-factor for transformation/scaling 
* @param fHeight y-factor for transformation/scaling 
* @return scaled image 
*/ 
public static BufferedImage scale(BufferedImage sbi, int imageType, int dWidth, int dHeight, double fWidth, double fHeight) { 
    BufferedImage dbi = null; 
    if(sbi != null) { 
     dbi = new BufferedImage(dWidth, dHeight, imageType); 
     Graphics2D g = dbi.createGraphics(); 
     AffineTransform at = AffineTransform.getScaleInstance(fWidth, fHeight); 
     g.drawRenderedImage(sbi, at); 
    } 
    return dbi; 
} 
+0

非常感谢它的工作原理,但哥们要放什么fWidth和fHeight,每次我得到不同的输出 – Walllzzz 2013-03-21 21:45:14

+1

那些规模因素在X坐标和Y轴见[javadoc的(HTTP://文档。 oracle.com/javase/6/docs/api/java/awt/geom/AffineTransform.html#getScaleInstance%28double,%20double%29)。例如,如果你想要得到的图像“half”是原来的那么大,所以fWidth和fHeight都通过'0.5'。小于'1'的值将缩小,大于'1'的值将放大,'1'将导致尺寸相同的图像。 – A4L 2013-03-21 21:55:32

+0

谢谢它解决了我的问题,我会选择这个作为公认的答案,altough所有的答案被接受 – Walllzzz 2013-03-21 22:21:23

7

我写了这个班,我个人也使用。我希望代码直截了当。

import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.Toolkit; 
import java.awt.image.BufferedImage; 
import java.awt.image.CropImageFilter; 
import java.awt.image.FilteredImageSource; 
import java.io.File; 
import java.io.IOException; 
import javax.imageio.ImageIO; 
import javax.swing.ImageIcon; 
import javax.swing.JComponent; 


public class ImageScaler { 

     private ImageIcon originalImage; 
     private ImageIcon scaledImage; 

     public ImageScaler(Image image) { 
       this.originalImage = new ImageIcon(image); 
     } 

     public ImageScaler(String fileName) { 
       originalImage = new ImageIcon(fileName); 
     } 

     public void createScaledImage(int size, ScalingDirection scalingDirection) { 
       if (scalingDirection == ScalingDirection.HORIZONTAL) { 
         scaledImage = new ImageIcon(originalImage.getImage().getScaledInstance(size, -1, Image.SCALE_SMOOTH)); 
       } else { 
         scaledImage = new ImageIcon(originalImage.getImage().getScaledInstance(-1, size, Image.SCALE_SMOOTH)); 
       }  
     } 

     public void createScaledImage(int size, ScalingDirection scalingDirection, int scale) { 
       if (scalingDirection == ScalingDirection.HORIZONTAL) { 
         scaledImage = new ImageIcon(originalImage.getImage().getScaledInstance(size, -1, scale)); 
       } else { 
         scaledImage = new ImageIcon(originalImage.getImage().getScaledInstance(-1, size, scale)); 
       } 
     } 

     public void createScaledImage(int width, int height, ScaleType scaleType) { 
       int imageWidth = originalImage.getImage().getWidth(null); 
       int imageHeight = originalImage.getImage().getHeight(null); 
       double originalImageRatio = imageWidth/(double) imageHeight; 
       double scaledImageRatio = width/(double) height; 

       if(scaleType == ScaleType.FIT) { 
         if(imageHeight - (Math.abs(imageWidth - width)/originalImageRatio) <= height) { 
           scaledImage = new ImageIcon(originalImage.getImage().getScaledInstance(width, -1, Image.SCALE_SMOOTH)); 
         } else if(imageWidth - (Math.abs(imageHeight - height) * originalImageRatio) <= width) { 
           scaledImage = new ImageIcon(originalImage.getImage().getScaledInstance(-1, height, Image.SCALE_SMOOTH)); 
         } 
       } else if(scaleType == ScaleType.FILL) { 
         if(imageHeight - (Math.abs(imageWidth - width)/originalImageRatio) >= height) { 
           scaledImage = new ImageIcon(originalImage.getImage().getScaledInstance(width, -1, Image.SCALE_SMOOTH)); 
           int thumbHeight = scaledImage.getImage().getHeight(null); 

           // Crop the image 
           scaledImage = new ImageIcon(Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(scaledImage.getImage().getSource(), new CropImageFilter(0, (thumbHeight-height)/2, width, height)))); 
         } else if(imageWidth - (Math.abs(imageHeight - height) * originalImageRatio) >= width) { 
           scaledImage = new ImageIcon(originalImage.getImage().getScaledInstance(-1, height, Image.SCALE_SMOOTH)); 
           int thumbWidth = scaledImage.getImage().getWidth(null); 

           // Crop the image 
           scaledImage = new ImageIcon(Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(scaledImage.getImage().getSource(), new CropImageFilter((thumbWidth-width)/2, 0, width, height)))); 
         }    
       } 
     } 

     public void saveScaledImage(File file, ImageType imageType) { 
       if (scaledImage != null) { 
         BufferedImage bi = new BufferedImage(scaledImage.getIconWidth(), scaledImage.getIconHeight(), BufferedImage.TYPE_INT_RGB); 
         Graphics g = bi.getGraphics(); 
         g.drawImage(scaledImage.getImage(), 0, 0, null); 
         try { 
           ImageIO.write(bi, imageType.value(), file); 
         } catch (IOException ioe) { 
           System.out.println("Error occured saving scaled image"); 
         } 
       } else { 
         System.out.println("Scaled image has not yet been created"); 
       } 
     } 

     public void saveOriginalImage(File file, ImageType imageType) { 
       if (originalImage != null) { 
         BufferedImage bi = new BufferedImage(originalImage.getIconWidth(), originalImage.getIconHeight(), BufferedImage.TYPE_INT_RGB); 
         Graphics g = bi.getGraphics(); 
         g.drawImage(originalImage.getImage(), 0, 0, null); 
         try { 
           ImageIO.write(bi, imageType.value(), file); 
         } catch (IOException ioe) { 
           System.out.println("Error occured saving original image"); 
         } 
       } else { 
         System.out.println("Original image has not yet been created"); 
       } 
     } 

     // ENUMS 
     public enum ScalingDirection {VERTICAL, HORIZONTAL}; 
     public enum ScaleType {FIT, FILL}; 
     public enum ImageType { 
       IMAGE_JPEG ("jpeg"), 
       IMAGE_JPG ("jpg"), 
       IMAGE_PNG ("png"); 

       private String value = null; 

       ImageType(String value) { 
         this.value = value; 
       } 

       String value() { 
         return value; 
       } 
     }; 
} 
+0

谢谢你,我没有尝试它,因为上面的代码工作,让别人试试看。 ? – Walllzzz 2013-03-21 22:22:43

1
public static BufferedImage resizeImg(BufferedImage img, int newW, int newH) 
    { 
    int w = img.getWidth(); 
    int h = img.getHeight(); 
    BufferedImage dimg = new BufferedImage(newW, newH, img.getType()); 
    Graphics2D g = dimg.createGraphics(); 
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
      RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
    g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null); 
    g.dispose(); 
    return dimg;  
    } 
+1

提供有关此代码如何解决OP问题的更多信息。目前还不清楚这个代码如何提供帮助。 – aravind 2014-12-12 14:25:53

5

基于@ A4L的回答是:

更straigt前的版本。他的解决方案也只能缩放画布而不是图像本身。

public static BufferedImage scale(BufferedImage imageToScale, int dWidth, int dHeight) { 
     BufferedImage scaledImage = null; 
     if (imageToScale != null) { 
      scaledImage = new BufferedImage(dWidth, dHeight, imageToScale.getType()); 
      Graphics2D graphics2D = scaledImage.createGraphics(); 
      graphics2D.drawImage(imageToScale, 0, 0, dWidth, dHeight, null); 
      graphics2D.dispose(); 
     } 
     return scaledImage; 
    } 

,以提高质量,你可以添加

graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
graphics2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
+0

简单性很强。谢谢。 – Apostolos 2016-11-17 21:11:39

+0

也为了提高质量,一个策略可以是在几个小步骤中进行缩放,直到达到期望的期望大小。 – A4L 2016-11-18 11:56:56

+0

正确,称为“渐进式缩放” - 我在此解释:http://stackoverflow.com/questions/24745147/java-resize-image-without-losing-quality/36367652#36367652基于Campbell的博客:https:// community.oracle.com/docs/DOC-983611 – for3st 2016-11-18 12:00:10

0

其实,解决的办法是更简单。您不必创建新的BufferedImage。您可以将for3st提到的方法直接应用到原始BufferedImage图像('图像')并设置您希望的宽度和高度。因此只需要一个语句(包括在stadard Java文档中):

drawImage(BufferedImage image, int x, int y, int width, int height, ImageObserver observer)