Devo ridimensionare i file PNG, JPEG e GIF. Come posso fare questo usando Java?
Devo ridimensionare i file PNG, JPEG e GIF. Come posso fare questo usando Java?
Risposte:
Dopo aver caricato l'immagine puoi provare:
BufferedImage createResizedCopy(Image originalImage,
int scaledWidth, int scaledHeight,
boolean preserveAlpha)
{
System.out.println("resizing...");
int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
Graphics2D g = scaledBI.createGraphics();
if (preserveAlpha) {
g.setComposite(AlphaComposite.Src);
}
g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
g.dispose();
return scaledBI;
}
FWIW Ho appena rilasciato (Apache 2, ospitato su GitHub) una semplice libreria di ridimensionamento delle immagini per Java chiamata imgscalr (disponibile su Maven central ).
La libreria implementa alcuni approcci diversi al ridimensionamento delle immagini (incluso l'approccio incrementale di Chris Campbell con alcuni miglioramenti minori) e sceglierà l'approccio ottimale per te se lo chiedi, o ti darà l'aspetto più veloce o migliore (se chiedere quello).
L'uso è semplicissimo, solo un mucchio di metodi statici. Il caso d'uso più semplice è:
BufferedImage scaledImage = Scalr.resize(myImage, 200);
Tutte le operazioni mantengono le proporzioni originali dell'immagine, quindi in questo caso stai chiedendo a imgscalr di ridimensionare l'immagine entro un limite di 200 pixel di larghezza e 200 pixel di altezza e per impostazione predefinita selezionerà automaticamente l'approccio più bello e veloce da quando non lo era non specificato.
All'inizio mi rendo conto che sembra un'autopromozione (lo è), ma ho trascorso la mia giusta parte del tempo a cercare su Google questo stesso identico argomento e ho continuato a trovare risultati / approcci / pensieri / suggerimenti diversi e ho deciso di sedermi e scrivere un semplice implementazione che indirizzerebbe quei casi d'uso dell'80-85% in cui hai un'immagine e probabilmente desideri una miniatura per essa - il più velocemente possibile o il più bello possibile (per quelli che hanno provato, noterai facendo un Graphics.drawImage anche con interpolazione BICUBIC su un'immagine abbastanza piccola, sembra ancora spazzatura).
new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer(). Mi piace anche la tua strada e penso che sia più semplice.
Thumbnailator è una libreria di ridimensionamento di immagini open source per Java con un'interfaccia fluida, distribuita con licenza MIT.
Ho scritto questa libreria perché realizzare miniature di alta qualità in Java può essere sorprendentemente difficile e il codice risultante potrebbe essere piuttosto disordinato. Con Thumbnailator, è possibile esprimere compiti abbastanza complicati usando una semplice API fluente.
Un semplice esempio
Per un semplice esempio, prendere un'immagine e ridimensionarla a 100 x 100 (preservare le proporzioni dell'immagine originale) e salvarla in un file può essere ottenuta in una singola istruzione:
Thumbnails.of("path/to/image")
.size(100, 100)
.toFile("path/to/thumbnail");
Un esempio avanzato
L'esecuzione di attività di ridimensionamento complesse è semplificata dall'interfaccia fluida di Thumbnailator.
Supponiamo di voler fare quanto segue:
0.85,thumbnail.aggiunta all'inizioTradotto in Thumbnailator, saremmo in grado di eseguire quanto sopra con il seguente:
Thumbnails.of(new File("path/to/directory").listFiles())
.size(100, 100)
.outputFormat("JPEG")
.outputQuality(0.85)
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
Una nota sulla qualità e la velocità dell'immagine
Questa libreria utilizza anche il metodo di ridimensionamento bilineare progressivo evidenziato in Filthy Rich Clients da Chet Haase e Romain Guy al fine di generare miniature di alta qualità garantendo prestazioni di runtime accettabili.
Non hai bisogno di una biblioteca per farlo. Puoi farlo con Java stesso.
Chris Campbell ha una descrizione eccellente e dettagliata delle immagini in scala: leggi questo articolo .
Chet Haase e Romain Guy hanno anche una descrizione dettagliata e molto istruttiva del ridimensionamento delle immagini nel loro libro, Filthy Rich Clients .
Java Advanced Imaging è ora open source e fornisce le operazioni necessarie.
Se hai a che fare con immagini di grandi dimensioni o desideri un risultato piacevole, non è un compito banale in Java. La semplice esecuzione tramite un'operazione di ridimensionamento tramite Graphics2D non crea un'anteprima di alta qualità. Puoi farlo usando JAI, ma richiede più lavoro di quanto tu possa immaginare per ottenere qualcosa che abbia un bell'aspetto e JAI ha la brutta abitudine di far esplodere la tua JVM con errori OutOfMemory.
Suggerisco di usare ImageMagick come eseguibile esterno se riesci a cavartela. È semplice da usare e fa bene il lavoro in modo da non doverlo fare.
L'API Java non fornisce una funzionalità di ridimensionamento standard per le immagini e il downgrade della qualità delle immagini.
Per questo motivo ho provato ad usare cvResize da JavaCV ma sembra causare problemi.
Ho trovato una buona libreria per il ridimensionamento delle immagini: aggiungi semplicemente la dipendenza per "ridimensionamento delle immagini java" nel tuo pom.xml.
<dependency>
<groupId>com.mortennobel</groupId>
<artifactId>java-image-scaling</artifactId>
<version>0.8.6</version>
</dependency>
Nel repository Maven otterrai la versione recente per questo.
Ex. Nel tuo programma Java
ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);
Potresti provare a utilizzare GraphicsMagick Image Processing System con im4java come interfaccia a riga di comando per Java.
Ci sono molti vantaggi di GraphicsMagick, ma uno per tutti:
Image Magick è stato menzionato. Esiste un progetto front-end JNI chiamato JMagick. Non è un progetto particolarmente stabile (e Image Magick stesso è noto per cambiare molto e persino rompere la compatibilità). Detto questo, abbiamo avuto una buona esperienza nell'uso di JMagick e di una versione compatibile di Image Magick in un ambiente di produzione per eseguire il ridimensionamento con un throughput elevato e un basso tasso di latenza. La velocità era sostanzialmente migliore rispetto a una libreria grafica tutta Java che avevamo già provato.
Usa semplicemente la risposta di Burkhard ma aggiungi questa riga dopo aver creato la grafica:
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
Puoi anche impostare il valore su BICUBIC, produrrà un'immagine di qualità migliore ma è un'operazione più costosa. Ci sono altri suggerimenti per il rendering che puoi impostare ma ho scoperto che l'interpolazione produce l'effetto più notevole. Tieni a mente se vuoi ingrandire molto, il codice java molto probabilmente sarà molto lento. Trovo che immagini più grandi inizino a produrre un ritardo di circa il 300% di zoom anche con tutti i suggerimenti di rendering impostati per ottimizzare la velocità rispetto alla qualità.
È possibile utilizzare Marvin (puro framework di elaborazione delle immagini Java) per questo tipo di operazione: http://marvinproject.sourceforge.net
Plug-in ridimensionamento : http://marvinproject.sourceforge.net/en/plugins/scale.html
Si scopre che scrivere uno scaler performante non è banale. L'ho fatto una volta per un progetto open source: ImageScaler .
In linea di principio 'java.awt.Image # getScaledInstance (int, int, int)' farebbe anche il lavoro, ma c'è un brutto bug con questo - fare riferimento al mio link per i dettagli.
Ho sviluppato una soluzione con le classi liberamente disponibili (AnimatedGifEncoder, GifDecoder e LWZEncoder) disponibili per gestire l'animazione GIF.
È possibile scaricare il jgifcode jar ed eseguire la classe GifImageUtil. Link: http://www.jgifcode.com
è possibile utilizzare il seguente prodotto popolare: thumbnailator
Se non vuoi importare imgScalr come la risposta @Riyad Kalla sopra la quale ho testato troppo funziona bene, puoi farlo preso da Peter Walser rispondere @Peter Walser su un altro problema però:
/**
* utility method to get an icon from the resources of this class
* @param name the name of the icon
* @return the icon, or null if the icon wasn't found.
*/
public Icon getIcon(String name) {
Icon icon = null;
URL url = null;
ImageIcon imgicon = null;
BufferedImage scaledImage = null;
try {
url = getClass().getResource(name);
icon = new ImageIcon(url);
if (icon == null) {
System.out.println("Couldn't find " + url);
}
BufferedImage bi = new BufferedImage(
icon.getIconWidth(),
icon.getIconHeight(),
BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
// paint the Icon to the BufferedImage.
icon.paintIcon(null, g, 0,0);
g.dispose();
bi = resizeImage(bi,30,30);
scaledImage = bi;// or replace with this line Scalr.resize(bi, 30,30);
imgicon = new ImageIcon(scaledImage);
} catch (Exception e) {
System.out.println("Couldn't find " + getClass().getName() + "/" + name);
e.printStackTrace();
}
return imgicon;
}
public static BufferedImage resizeImage (BufferedImage image, int areaWidth, int areaHeight) {
float scaleX = (float) areaWidth / image.getWidth();
float scaleY = (float) areaHeight / image.getHeight();
float scale = Math.min(scaleX, scaleY);
int w = Math.round(image.getWidth() * scale);
int h = Math.round(image.getHeight() * scale);
int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
boolean scaleDown = scale < 1;
if (scaleDown) {
// multi-pass bilinear div 2
int currentW = image.getWidth();
int currentH = image.getHeight();
BufferedImage resized = image;
while (currentW > w || currentH > h) {
currentW = Math.max(w, currentW / 2);
currentH = Math.max(h, currentH / 2);
BufferedImage temp = new BufferedImage(currentW, currentH, type);
Graphics2D g2 = temp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(resized, 0, 0, currentW, currentH, null);
g2.dispose();
resized = temp;
}
return resized;
} else {
Object hint = scale > 2 ? RenderingHints.VALUE_INTERPOLATION_BICUBIC : RenderingHints.VALUE_INTERPOLATION_BILINEAR;
BufferedImage resized = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = resized.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(image, 0, 0, w, h, null);
g2.dispose();
return resized;
}
}
Prova questo metodo folowing:
ImageIcon icon = new ImageIcon("image.png");
Image img = icon.getImage();
Image newImg = img.getScaledInstance(350, 350, java.evt.Image.SCALE_SMOOTH);
icon = new ImageIcon(img);
JOptionPane.showMessageDialog(null, "image on The frame", "Display Image", JOptionPane.INFORMATION_MESSAGE, icon);