Как изменить размер изображения с помощью Java?

Мне нужно изменить размер PNG, JPEG и GIF файлов. Как это сделать с помощью Java?

Ответ 1

После загрузки изображения вы можете попробовать:

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

Ответ 2

FWIW Я только что выпустил (Apache 2, размещенный на GitHub) простую библиотеку масштабирования изображений для Java под названием imgscalr (доступно на центр Maven).

В библиотеке реализованы несколько разных подходов к масштабированию изображений (включая инкрементный подход Криса Кэмпбелла с несколькими незначительными усовершенствованиями) и либо выберете наиболее оптимальный для вас подход, если вы попросите его, либо предоставите вам самый быстрый или лучший вид (если вы просите об этом).

Использование мертво-простое, просто куча статических методов. Самый простой вариант использования:

BufferedImage scaledImage = Scalr.resize(myImage, 200);

Все операции поддерживают исходные пропорции изображения, поэтому в этом случае вы запрашиваете imgscalr для изменения размера изображения в пределах 200 пикселей в ширину и 200 пикселей в высоту, и по умолчанию он автоматически выбирает наилучший и самый быстрый способ для этого поскольку он не был указан.

Я понимаю, с самого начала это выглядит как самореклама (это так), но я потратил свою долю времени на поиски этого одного и того же предмета и продолжал придумывать разные результаты/подходы/мысли/предложения и решил сесть и напишите простую реализацию, которая адресовала бы 80-85% случаев использования, где у вас есть изображение, и, возможно, для него требуется миниатюра - как можно быстрее или как можно более красиво (для тех, кто попробовал, вы 'll замечает, что делает Graphics.drawImage даже с интерполяцией BICUBIC на достаточно маленьком изображении, он по-прежнему выглядит как мусор).

Ответ 3

Thumbnailator - это библиотека изменения размера изображения с открытым исходным кодом для Java с плавным интерфейсом, распространяемая по лицензии MIT.

Я написал эту библиотеку, потому что создание высококачественных миниатюр в Java может быть удивительно сложным, и полученный код может быть довольно грязным. С помощью Thumbnailator можно выразить довольно сложные задачи с помощью простого свободного API.

Простой пример

Для простого примера, взяв изображение и изменив его размер до 100 x 100 (сохраняя соотношение сторон исходного изображения) и сохраните его в файл, можно получить в одном выражении:

Thumbnails.of("path/to/image")
    .size(100, 100)
    .toFile("path/to/thumbnail");

Расширенный пример

Выполнение сложных задач масштабирования упрощается с помощью свободного интерфейса Thumbnailator.

Предположим, что мы хотим сделать следующее:

  • возьмите изображения в каталоге и
  • измените размер до 100 x 100 с соотношением сторон исходного изображения,
  • сохраните их все в формате JPEG с настройками качества 0.85,
  • где имена файлов берутся из оригинала с thumbnail., добавленным в начало

Переведенный на Thumbnailator, мы сможем выполнить вышеуказанное:

Thumbnails.of(new File("path/to/directory").listFiles())
    .size(100, 100)
    .outputFormat("JPEG")
    .outputQuality(0.85)
    .toFiles(Rename.PREFIX_DOT_THUMBNAIL);

Заметка о качестве и скорости изображения

Эта библиотека также использует прогрессивный метод билинейного масштабирования, выделенный в Filthy Rich Clients Чет Хаазе и Роменом Гаем, чтобы генерировать высококачественные эскизы, обеспечивая при этом приемлемую производительность во время выполнения.

Ответ 4

Вам не нужна библиотека, чтобы сделать это. Вы можете сделать это с самой Java.

У Криса Кэмпбелла отличная и подробная информация о масштабировании изображений - см. эту статью.

Чет Хаас и Ромен Гай также подробно и очень информативно описывают масштабирование изображений в своей книге Filthy Rich Clients.

Ответ 5

Java Advanced Imaging теперь является открытым исходным кодом и предоставляет необходимые вам операции.

Ответ 6

Если вы имеете дело с большими изображениями или хотите получить красивый результат, это не тривиальная задача в java. Просто сделать это с помощью функции rescale op через Graphics2D не создаст миниатюру высокого качества. Вы можете сделать это с помощью JAI, но это требует больше работы, чем вы могли бы представить, чтобы получить что-то хорошее, и у JAI есть неприятная привычка выдувать нашу JVM с ошибками OutOfMemory.

Я предлагаю использовать ImageMagick в качестве внешнего исполняемого файла, если вы можете с ним справиться. Его прост в использовании, и он делает работу правильно, так что вам не нужно.

Ответ 7

Если у вас есть функция imagemagick, установленная на вашем компьютере, я рекомендую im4java. Это очень тонкий слой абстракции на интерфейсе командной строки, но делает его работу очень хорошо.

Ответ 8

Java API не предоставляет стандартную функцию масштабирования для изображений и снижения качества изображения.

Из-за этого я попытался использовать cvResize из JavaCV, но, похоже, это вызывает проблемы.

Я нашел хорошую библиотеку для масштабирования изображения: просто добавьте зависимость для "java-image-scaling" в ваш pom.xml.

<dependency>
    <groupId>com.mortennobel</groupId>
    <artifactId>java-image-scaling</artifactId>
    <version>0.8.6</version>
</dependency>

В репозитории Maven вы получите последнюю версию для этого.

Ex. В вашей Java-программе

ResampleOp resamOp = new ResampleOp(50, 40);
BufferedImage modifiedImage = resamOp.filter(originalBufferedImage, null);

Ответ 9

Вы можете попытаться использовать GraphicsMagick Image Processing System с im4java в качестве интерфейса comand-line для Java.

Существует много преимуществ GraphicsMagick, но один для всех:

  • GM используется для обработки миллиардов файлов на крупнейшей в мире фотографии сайтов (например, Flickr и Etsy).

Ответ 10

Изображение Магия упоминается. Существует проект JNI front end под названием JMagick. Это не очень стабильный проект (и сам Image Magick, как известно, сильно меняет и даже нарушает совместимость). Тем не менее, у нас был хороший опыт использования JMagick и совместимой версии Image Magick в производственной среде для масштабирования с высокой пропускной способностью и низкой задержкой. Скорость была значительно лучше, чем со всей графической библиотекой Java, которую мы ранее пробовали.

http://www.jmagick.org/index.html

Ответ 12

Просто используйте ответ Буркхарда, но добавьте эту строку после создания графики:

    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

Вы также можете установить значение BICUBIC, оно будет производить изображение более высокого качества, но это более дорогостоящая операция. Есть другие подсказки для рендеринга, которые вы можете установить, но я обнаружил, что интерполяция производит наиболее заметный эффект. Имейте в виду, если вы хотите увеличить масштаб, java-код, скорее всего, будет очень медленным. Я нахожу, что большие изображения начинают создавать отставание около 300% зум даже при всех подсказках, настроенных для оптимизации скорости по качеству.

Ответ 13

Оказывается, написание полноценного скалера не тривиально. Я сделал это один раз для проекта с открытым исходным кодом: ImageScaler.

В принципе, 'java.awt.Image # getScaledInstance (int, int, int)' также справился бы с этой задачей, но с этим связана одна неприятная ошибка - подробности см. В моей ссылке.

Ответ 14

Я разработал решение со свободно доступными классами (AnimatedGifEncoder, GifDecoder и LWZEncoder), доступными для обработки анимации GIF.
Вы можете загрузить jgifcode jar и запустить класс GifImageUtil. Ссылка: http://www.jgifcode.com

Ответ 15

вы можете использовать следующий популярный продукт: thumbnailator

Ответ 16

Если вы не хотите импортировать 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;
        }
    }