2012-10-14 21 views
6

Ho un'immagine di dire dimensioni 800x800 che ha una dimensione di 170 kb. Voglio ridimensionare questa immagine per dire 600x600. Dopo il ridimensionamento voglio ridurre la dimensione dell'immagine. Come posso fare questo?Ridimensionamento delle immagini in Java per ridurre le dimensioni dell'immagine

+0

Si può dare un'occhiata a http://stackoverflow.com/questions/11959758/java-maintaining-aspect-ratio-of-jpanel-background-image/11959928#11959928 – MadProgrammer

+0

1) * "Dopo il ridimensionamento voglio la dimensione dell'immagine da ridurre. "* Se tenuto in memoria o serializzato in PNG, JPG o GIF? Il primo si tradurrà in una riduzione dei byte, il secondo spesso no. 2) Che formato è l'immagine? (PNG, GIF, JPEG ..) –

+0

Se il formato è JPEG, molto probabilmente sarà più efficace ridurre le dimensioni del byte dell'immagine su disco aumentando il rapporto di compressione. Vedi ['ImageCompressionDemo'] (http://stackoverflow.com/a/5998015/418556) per esempio sorgente. –

risposta

13

Non è necessaria una libreria di elaborazione immagini in piena regola per ridimensionare semplicemente un'immagine.

L'approccio consigliato è quello di utilizzare progressivo ridimensionamento bilineare, in questo modo (sentitevi liberi di utilizzare questo metodo come è nel codice):

public BufferedImage scale(BufferedImage img, int targetWidth, int targetHeight) { 

    int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; 
    BufferedImage ret = img; 
    BufferedImage scratchImage = null; 
    Graphics2D g2 = null; 

    int w = img.getWidth(); 
    int h = img.getHeight(); 

    int prevW = w; 
    int prevH = h; 

    do { 
     if (w > targetWidth) { 
      w /= 2; 
      w = (w < targetWidth) ? targetWidth : w; 
     } 

     if (h > targetHeight) { 
      h /= 2; 
      h = (h < targetHeight) ? targetHeight : h; 
     } 

     if (scratchImage == null) { 
      scratchImage = new BufferedImage(w, h, type); 
      g2 = scratchImage.createGraphics(); 
     } 

     g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
       RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
     g2.drawImage(ret, 0, 0, w, h, 0, 0, prevW, prevH, null); 

     prevW = w; 
     prevH = h; 
     ret = scratchImage; 
    } while (w != targetWidth || h != targetHeight); 

    if (g2 != null) { 
     g2.dispose(); 
    } 

    if (targetWidth != ret.getWidth() || targetHeight != ret.getHeight()) { 
     scratchImage = new BufferedImage(targetWidth, targetHeight, type); 
     g2 = scratchImage.createGraphics(); 
     g2.drawImage(ret, 0, 0, null); 
     g2.dispose(); 
     ret = scratchImage; 
    } 

    return ret; 

} 

codice modificato e ripulito dalla originale a Filthy Rich Clients.


Sulla base della sua commento, si può ridurre la qualità e codificare byte JPEG in questo modo:

image è il BufferedImage.

ByteArrayOutputStream os = new ByteArrayOutputStream(); 
ImageWriter writer = (ImageWriter) ImageIO.getImageWritersByFormatName("jpeg").next(); 

ImageWriteParam param = writer.getDefaultWriteParam(); 
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 
param.setCompressionQuality(0.2f); // Change this, float between 0.0 and 1.0 

writer.setOutput(ImageIO.createImageOutputStream(os)); 
writer.write(null, new IIOImage(image, null, null), param); 
writer.dispose(); 

Ora, dal momento che è un osByteArrayOutputStream, è possibile codificare Base64.

String base64 = Base64.encode(os.toByteArray()); 
+0

Voglio ridurre la dimensione dell'immagine (in byte) dopo aver ridimensionato in modo che possa inviarlo su un socket. Il dataoutputstream dice che la stringa codificata (Base64) è troppo grande. – Madeyedexter

+0

Base64 codifica invece i byte JPEG. Puoi usare 'ImageIO' per questo. – LanguagesNamedAfterCofee

+0

@Danish Vedi il mio edit – LanguagesNamedAfterCofee

3

Utilizzare un buon framework che supporti Image Processing tramite Java, ad es. IamageJ

C'è anche un supporto di base disponibile in Java attraverso alcune classi come MemoryImageSource e PixelGrabber.

+0

Ho controllato. Voglio farlo nel mio programma Java! – Madeyedexter

+0

Ho aggiornato la risposta con le informazioni di supporto di base in Core Java. Spero possa aiutare. –

5

è possibile utilizzare il 100% Java, Apache2 open source imgscalr library (una classe statica singolo) e fare qualcosa del genere:

import org.imgscalr.Scalr.*; // static imports are awesome with the lib 

... some class code ... 

// This is a super-contrived method name, I just wanted to incorporate 
// the details from your question accurately. 
public static void resizeImageTo600x600(BufferedImage image) { 
    ImageIO.write(resize(image, 600), "JPG", new File("/path/to/file.jpg")); 
} 

NOTA: Se quanto sopra sembra strano, la statica importazione mi permette di utilizzare la chiamata ridimensionamento direttamente senza specificare Scalr.resize (...)

Inoltre, se la qualità delle immagini in scala scritta fuori non sembra abbastanza buono (sarà scritto in fretta però) è possibile utilizzare ulteriori argomenti alla ridimensionare metodo in questo modo:

public static void resizeImageTo600x600(BufferedImage image) { 
    ImageIO.write(resize(image, Method.ULTRA_QUALITY, 600), "JPG", new File("/path/to/file.jpg")); 
} 

.. e si può anche applicare una BufferedImageOp al risultato per ammorbidirlo in caso il downscaling rendono l'immagine di Jaggy:

public static void resizeImageTo600x600(BufferedImage image) { 
    ImageIO.write(resize(image, Method.ULTRA_QUALITY, 600, Scalr.OP_ANTIALIAS), "JPG", new File("/path/to/file.jpg")); 
} 

si può iniziare a giocare con la libreria semplicemente aggiungendo la seguente voce dep nel Maven POM (imgscalr è in Maven central repo):

<dependency> 
    <groupId>org.imgscalr</groupId> 
    <artifactId>imgscalr-lib</artifactId> 
    <version>4.2</version> 
    <type>jar</type> 
    <scope>compile</scope> 
</dependency> 
+0

Non capisco la licenza. Posso usare questo in un sito web personale? – Ced

+0

Inoltre, se l'immagine è più piccola, si scalerà? – Ced

Problemi correlati