Мені потрібно змінити розмір файлів PNG, JPEG та GIF. Як я можу це зробити за допомогою Java?
Мені потрібно змінити розмір файлів PNG, JPEG та GIF. Як я можу це зробити за допомогою Java?
Відповіді:
Після завантаження зображення ви можете спробувати:
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 Щойно я випустив (Apache 2, розміщений на GitHub) просту бібліотеку масштабування зображень для Java під назвою imgscalr (доступна на Maven central ).
Бібліотека реалізує декілька різних підходів до масштабування зображень (включаючи інкрементальний підхід Кріса Кемпбелла з кількома незначними вдосконаленнями), або вибере для вас найоптимальніший підхід, якщо ви попросите, або надасть вам найшвидший або найкращий вигляд (якщо ви просимо про це).
Використання мертво-просто, просто купа статичних методів. Найпростіший варіант використання:
BufferedImage scaledImage = Scalr.resize(myImage, 200);
Усі операції підтримують початкові пропорції зображення, тому в цьому випадку ви просите imgscalr змінити розмір зображення в межах 200 пікселів завширшки та 200 пікселів заввишки, і за замовчуванням він автоматично вибере найкращий і найшвидший підхід для цього, оскільки він не був не вказано
З самого початку я розумію, що це виглядає як самореклама (це так), але я витратив свою справедливу частку часу, гуляючи на цю саму тему і продовжував придумувати різні результати / підходи / думки / пропозиції та вирішив сісти і написати проста реалізація, яка стосуватиметься 80-85% випадків використання, коли у вас є зображення, і, ймовірно, потрібно мініатюру для нього - якнайшвидшого або максимально гарного вигляду (для тих, хто спробував, ви помітите роблячи Graphics.drawImage навіть при інтерполяції BICUBIC на досить маленьке зображення, воно все ще виглядає як сміття).
new ImageScaler(img).resizeTo(...).rotate(...).cropTo(...).toOutputBuffer()
. Мені подобається і твій шлях, і я думаю, що це простіше.
Thumbnailator - це бібліотека розміру зображень з відкритим кодом для Java з вільним інтерфейсом, що поширюється за ліцензією MIT.
Я написав цю бібліотеку, тому що робити якісні мініатюри на Java може бути напрочуд складно, а отриманий код може бути досить безладним. За допомогою Thumbnailator можна висловити досить складні завдання, використовуючи простий вільний API.
Простий приклад
Для простого прикладу, зробити зображення та змінити його до 100 x 100 (збереження пропорцій оригінального зображення) та зберегти його у файл можна досягти в одному операторі:
Thumbnails.of("path/to/image")
.size(100, 100)
.toFile("path/to/thumbnail");
Передовий приклад
Виконання складних завдань щодо зміни розміру спрощено за допомогою вільного інтерфейсу Thumbnailator.
Припустимо, ми хочемо зробити наступне:
0.85
,thumbnail.
додаванням до початкуПерекладене на мініатюру, ми зможемо виконати вищезазначене з наступним:
Thumbnails.of(new File("path/to/directory").listFiles())
.size(100, 100)
.outputFormat("JPEG")
.outputQuality(0.85)
.toFiles(Rename.PREFIX_DOT_THUMBNAIL);
Примітка про якість та швидкість зображення
Ця бібліотека також використовує прогресивний метод білінеарного масштабування, виділений у брудних клієнтів Chet Haase та Romain Guy, щоб генерувати якісні ескізи, забезпечуючи при цьому прийнятну ефективність виконання.
Для цього вам не потрібна бібліотека. Ви можете це зробити з самою Java.
Кріс Кемпбелл має чудовий та детальний опис масштабування зображень - дивіться цю статтю .
Чет Хааз та Ромен Гай також мають детальну та дуже інформативну написання масштабування зображень у своїй книзі " Клієни Брудні Річки" .
Java Advanced Imaging тепер є відкритим кодом та забезпечує необхідні вам операції.
Якщо ви маєте справу з великими зображеннями або хочете приємного вигляду, це не тривіальна задача в java. Просто це зробити через масштабний вибір через Graphics2D не створить мініатюру високої якості. Ви можете зробити це за допомогою JAI, але для цього потрібно більше роботи, ніж ви могли б уявити, щоб отримати щось, що виглядає добре, і JAI має неприємну звичку дути наш JVM помилками OutOfMemory.
Я пропоную використовувати ImageMagick як зовнішній виконуваний файл, якщо ви можете піти з ним. Він простий у використанні, і він виконує роботу правильно, щоб вам не довелося.
Якщо встановлення Imagemagick на вашій машині є варіантом, я рекомендую im4java . Це дуже тонкий шар абстракції в інтерфейсі командного рядка, але робить свою роботу дуже добре.
Java API не забезпечує стандартну функцію масштабування зображень та зниження якості зображення.
Через це я спробував використовувати cvResize від JavaCV, але це, здається, спричинило проблеми.
Я знайшов хорошу бібліотеку для масштабування зображень: просто додайте залежність від "java-image-масштабування" у свій pom.xml.
<dependency>
<groupId>com.mortennobel</groupId>
<artifactId>java-image-scaling</artifactId>
<version>0.8.6</version>
</dependency>
У сховищі Maven ви отримаєте останню версію для цього.
Вих. У вашій програмі java
ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);
Ви можете спробувати скористатися системою обробки зображень GraphicsMagick за допомогою im4java як інтерфейс командного рядка для Java.
Є багато переваг GraphicsMagick, але одна для всіх:
Згаданий образ Magick. Є передній проект JNI під назвою JMagick. Це не особливо стабільний проект (і саме Image Magick, як відомо, багато що змінило і навіть порушило сумісність). Це означає, що ми мали хороший досвід використання JMagick та сумісної версії Image Magick у виробничих умовах для масштабування з високою пропускною здатністю та низькою затримкою. Швидкість була значно краща, ніж у всій графічній бібліотеці Java, яку ми раніше пробували.
Просто використовуйте відповідь Беркхарда, але додайте цей рядок після створення графіки:
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
Ви також можете встановити значення BICUBIC, воно дасть зображення кращої якості, але це більш дорога операція. Можна встановити й інші підказки щодо візуалізації, але я виявив, що інтерполяція дає найбільш помітний ефект. Майте на увазі, якщо ви хочете збільшити масштаб, ява-код, швидше за все, буде дуже повільним. Я вважаю, що більші зображення починають створювати відставання близько 300% масштабу навіть при встановленні всіх підказок на візуалізацію для оптимізації швидкості над якістю.
Ви можете використовувати Marvin (чисту рамку обробки зображень Java) для таких операцій: http://marvinproject.sourceforge.net
Масштабний плагін: http://marvinproject.sourceforge.net/en/plugins/scale.html
Виявляється, написання виконавського скалера - не тривіально. Я зробив це один раз для проекту з відкритим кодом: ImageScaler .
В принципі, "java.awt.Image # getScaledInstance (int, int, int)" також зробив би цю роботу, але з цим є неприємна помилка - для детальної інформації зверніться до мого посилання.
Я розробив рішення із вільно доступними класами (AnimatedGifEncoder, GifDecoder та LWZEncoder), доступними для обробки GIF Animation.
Ви можете завантажити банку jgifcode та запустити клас GifImageUtil. Посилання: http://www.jgifcode.com
Ви можете використовувати наступний популярний продукт: ескіз
Якщо ви не хочете імпортувати imgScalr, як-от @Riyad Kalla, відповідь, над якою я тестував, теж добре працює, ви можете зробити це взято з відповіді Пітера Уолсера @ Петера Вальсера з іншого питання:
/**
* 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;
}
}
Спробуйте цей спосіб наступного:
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);