Ich muss die Größe von PNG-, JPEG- und GIF-Dateien ändern. Wie kann ich das mit Java machen?
Ich muss die Größe von PNG-, JPEG- und GIF-Dateien ändern. Wie kann ich das mit Java machen?
Antworten:
Nach dem Laden des Bildes können Sie versuchen:
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 Ich habe gerade (Apache 2, gehostet auf GitHub) eine einfache Bildskalierungsbibliothek für Java namens imgscalr veröffentlicht (verfügbar in Maven Central ).
Die Bibliothek implementiert einige verschiedene Ansätze zur Bildskalierung (einschließlich des inkrementellen Ansatzes von Chris Campbell mit einigen geringfügigen Verbesserungen) und wählt entweder den für Sie optimalen Ansatz aus, wenn Sie dazu aufgefordert werden, oder bietet Ihnen den schnellsten oder am besten aussehenden Ansatz (wenn Sie dies wünschen) danach fragen).
Die Verwendung ist kinderleicht, nur eine Reihe statischer Methoden. Der einfachste Anwendungsfall ist:
BufferedImage scaledImage = Scalr.resize(myImage, 200);
Bei allen Vorgängen werden die ursprünglichen Proportionen des Bildes beibehalten. In diesem Fall fordern Sie imgscalr auf, die Größe Ihres Bilds innerhalb von 200 Pixel Breite und 200 Pixel Höhe zu ändern. Standardmäßig wird automatisch der am besten aussehende und schnellste Ansatz ausgewählt, da dies nicht der Fall war nicht angegeben.
Am Anfang war mir klar, dass dies wie Eigenwerbung aussieht (es ist), aber ich verbrachte meinen Teil der Zeit damit, genau dasselbe Thema zu googeln und kam immer wieder auf unterschiedliche Ergebnisse / Ansätze / Gedanken / Vorschläge und beschloss, mich hinzusetzen und eine zu schreiben einfache Implementierung, die 80-85% der Anwendungsfälle anspricht, in denen Sie ein Bild haben und wahrscheinlich ein Miniaturbild dafür möchten - entweder so schnell wie möglich oder so gut wie möglich (für diejenigen, die es versucht haben, werden Sie feststellen Wenn Sie ein Graphics.drawImage auch mit BICUBIC-Interpolation auf ein ausreichend kleines Bild ausführen, sieht es immer noch wie Müll aus.
new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer()
. Ich mag deinen Weg auch und ich denke, es ist einfacher.
Thumbnailator ist eine Open-Source-Bibliothek zur Größenänderung von Bildern für Java mit einer fließenden Oberfläche, die unter der MIT-Lizenz vertrieben wird.
Ich habe diese Bibliothek geschrieben, weil es überraschend schwierig sein kann, hochwertige Miniaturansichten in Java zu erstellen, und der resultierende Code ziemlich chaotisch sein kann. Mit Thumbnailator ist es möglich, ziemlich komplizierte Aufgaben mit einer einfachen fließenden API auszudrücken.
Ein einfaches Beispiel
Ein einfaches Beispiel: Nehmen Sie ein Bild und ändern Sie die Größe auf 100 x 100 (wobei das Seitenverhältnis des Originalbilds beibehalten wird) und speichern Sie es in einer Datei in einer einzigen Anweisung:
Thumbnails.of("path/to/image")
.size(100, 100)
.toFile("path/to/thumbnail");
Ein fortgeschrittenes Beispiel
Das Ausführen komplexer Größenänderungsaufgaben wird durch die fließende Benutzeroberfläche von Thumbnailator vereinfacht.
Nehmen wir an, wir möchten Folgendes tun:
0.85
,thumbnail.
an den Anfang angehängtIn Thumbnailator übersetzt, könnten wir die oben genannten Schritte wie folgt ausführen:
Thumbnails.of(new File("path/to/directory").listFiles())
.size(100, 100)
.outputFormat("JPEG")
.outputQuality(0.85)
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
Ein Hinweis zur Bildqualität und -geschwindigkeit
Diese Bibliothek verwendet auch die progressive bilineare Skalierungsmethode , die in Filthy Rich Clients von Chet Haase und Romain Guy hervorgehoben wurde, um hochwertige Miniaturansichten zu generieren und gleichzeitig eine akzeptable Laufzeitleistung sicherzustellen.
Sie benötigen dazu keine Bibliothek. Sie können es mit Java selbst tun.
Chris Campbell hat eine ausgezeichnete und detaillierte Beschreibung der Skalierung von Bildern - siehe diesen Artikel .
Chet Haase und Romain Guy haben in ihrem Buch Filthy Rich Clients auch eine detaillierte und sehr informative Beschreibung der Bildskalierung .
Java Advanced Imaging ist jetzt Open Source und bietet die erforderlichen Vorgänge.
Wenn Sie mit großen Bildern arbeiten oder ein gut aussehendes Ergebnis erzielen möchten, ist dies in Java keine triviale Aufgabe. Wenn Sie dies einfach über eine Rescale-Operation über Graphics2D tun, wird keine hochwertige Miniaturansicht erstellt. Sie können dies mit JAI tun, aber es erfordert mehr Arbeit, als Sie sich vorstellen können, um etwas zu erhalten, das gut aussieht, und JAI hat die böse Angewohnheit, Ihre JVM mit OutOfMemory-Fehlern zu belasten.
Ich schlage vor, ImageMagick als externe ausführbare Datei zu verwenden, wenn Sie damit durchkommen können. Es ist einfach zu bedienen und macht den Job richtig, so dass Sie nicht müssen.
Die Java-API bietet keine Standard-Skalierungsfunktion für Bilder und eine Herabstufung der Bildqualität.
Aus diesem Grund habe ich versucht, cvResize von JavaCV aus zu verwenden, aber es scheint Probleme zu verursachen.
Ich habe eine gute Bibliothek für die Bildskalierung gefunden: Fügen Sie einfach die Abhängigkeit für "Java-Bildskalierung" in Ihre pom.xml ein.
<dependency>
<groupId>com.mortennobel</groupId>
<artifactId>java-image-scaling</artifactId>
<version>0.8.6</version>
</dependency>
Im Maven-Repository erhalten Sie dazu die aktuelle Version.
Ex. In Ihrem Java-Programm
ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);
Sie können versuchen, das GraphicsMagick-Bildverarbeitungssystem mit im4java als Befehlszeilenschnittstelle für Java zu verwenden.
GraphicsMagick bietet viele Vorteile, aber einen für alle:
Image Magick wurde erwähnt. Es gibt ein JNI-Frontend-Projekt namens JMagick. Es ist kein besonders stabiles Projekt (und Image Magick selbst hat sich bekanntermaßen stark verändert und sogar die Kompatibilität beeinträchtigt). Wir haben jedoch gute Erfahrungen mit JMagick und einer kompatiblen Version von Image Magick in einer Produktionsumgebung gemacht, um die Skalierung mit hohem Durchsatz und geringer Latenz durchzuführen. Die Geschwindigkeit war wesentlich besser als bei einer Java-Grafikbibliothek, die wir zuvor ausprobiert haben.
Verwenden Sie einfach die Antwort von Burkhard, aber fügen Sie diese Zeile nach dem Erstellen der Grafiken hinzu:
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
Sie können den Wert auch auf BICUBIC setzen. Dies führt zu einer besseren Bildqualität, ist jedoch teurer. Es gibt andere Rendering-Hinweise, die Sie festlegen können, aber ich habe festgestellt, dass die Interpolation den bemerkenswertesten Effekt erzeugt. Denken Sie daran, wenn Sie viel zoomen möchten, wird Java-Code höchstwahrscheinlich sehr langsam sein. Ich finde, dass größere Bilder eine Verzögerung von etwa 300% Zoom erzeugen, selbst wenn alle Rendering-Hinweise so eingestellt sind, dass die Geschwindigkeit über die Qualität optimiert wird.
Sie können Marvin (reines Java-Bildverarbeitungsframework) für diese Art von Operation verwenden: http://marvinproject.sourceforge.net
Skalierungs-Plug-In: http://marvinproject.sourceforge.net/en/plugins/scale.html
Es stellt sich heraus, dass das Schreiben eines performanten Skalierers nicht trivial ist. Ich habe es einmal für ein Open Source-Projekt gemacht: ImageScaler .
Im Prinzip würde 'java.awt.Image # getScaledInstance (int, int, int)' auch die Arbeit erledigen, aber es gibt einen bösen Fehler dabei - siehe meinen Link für Details.
Ich habe eine Lösung mit den frei verfügbaren Klassen (AnimatedGifEncoder, GifDecoder und LWZEncoder) entwickelt, die für die Verarbeitung von GIF-Animationen verfügbar sind.
Sie können das jgifcode jar herunterladen und die GifImageUtil-Klasse ausführen. Link: http://www.jgifcode.com
Sie können folgendes beliebtes Produkt verwenden: thumbnailator
Wenn Sie imgScalr nicht importieren möchten, wie die Antwort von @Riyad Kalla, über der ich auch getestet habe, funktioniert dies einwandfrei. Sie können dies jedoch aus der Antwort von Peter Walser @Peter Walser zu einem anderen Problem machen:
/**
* 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;
}
}
Versuchen Sie diese folgende Methode:
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);