2013-03-21 16 views
12

Ciao Ho un'immagine del codice QR, e voglio ridimensionarla, quando provo a ridimensionarla a una piccola immagine usando questo codice, ottengo sempre un'immagine sfocata, e il codice QR non è più valido quando lo scannerizzo , ma funziona bene quando ho ridimensionare ad un grande immagini di dimensioni con lo stesso codice:come ridimensionare l'immagine in 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; 
} 

qual è il problema, non esattamente a capire, per favore mi dia almeno un accenno, grazie

+0

Non hai mostrato un dettaglio fondamentale - quello suggerimento interpolazione si sta impostando! –

+0

grazie mille, il mio suggerimento di interpolazione è RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR, ho provato con tutti i valori possibili, ancora non ha funzionato – Walllzzz

risposta

23

Io uso la trasformazione affine a realizzare questo compito, ecco il mio codice, speriamo vi sia utile

/** 
* 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

Grazie mille funziona, ma amico cosa mettere in fWidth e fHeight?, Ogni volta che ottengo output diversi – Walllzzz

+1

quelli sono i fattori di scala per le coordinate sull'asse X e Y vedere il [javadoc] (http: // docs. oracle.com/javase/6/docs/api/java/awt/geom/AffineTransform.html#getScaleInstance%28double,%20double%29). per esempio se vuoi avere un'immagine risultante 'mezza' grande come quella originale, quindi passa' 0.5' per fWidth e fHeight. Valori inferiori a "1" si ridurranno, valori superiori a "1" cresceranno, "1" genererà un'immagine delle stesse dimensioni. – A4L

+0

Grazie risolto il mio problema, sceglierò questa come risposta accettata, sebbene tutte le risposte siano accettate – Walllzzz

7

Ho scritto questa classe che personalmente uso anche io. Spero che il codice sia diretto.

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

Grazie, non l'ho provato perché il codice sopra funzionava, lascia che gli altri ci provino. – Walllzzz

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

Fornisci maggiori informazioni su come questo codice risolve il problema dell'OP. Non è chiaro come questo codice aiuti. – aravind

5

in base alla risposta di @ A4L:

Un altro straigt versione avanti. Anche la sua soluzione ha solo scalato la tela e non l'immagine stessa.

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; 
    } 

per aumentare la qualità si potrebbe aggiungere

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

La semplicità è geniale. Grazie. – Apostolos

+0

Anche per quanto riguarda la qualità, una strategia potrebbe essere quella di fare lo scalpiccio in diversi piccoli passi fino a raggiungere la dimensione desiderata desiderata. – A4L

+0

Vero, chiamato "Aumento progressivo" - Spiego questo qui: http://stackoverflow.com/questions/24745147/java-resize-image-without-losing-quality/36367652#36367652 basato sul blog di Campbell: https: // community.oracle.com/docs/DOC-983611 – for3st

0

In realtà, la soluzione è ancora più semplice. Non è necessario creare un nuovo BufferedImage. È possibile applicare il metodo indicato da for3st direttamente all'immagine originale di BufferedImage ('immagine') e impostare la larghezza e l'altezza desiderate. Così una singola istruzione è necessaria solo (incluso nella documentazione di Java stadard):

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