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


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

16 116

16 ответов:

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

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% случаев использования, когда у вас есть изображение и, вероятно, хотите миниатюру для него-либо как можно быстрее, либо как можно красивее (для тех, кто пробовал, вы заметите, что делаете графику.drawImage даже с БИКУБИЧЕСКОЙ интерполяцией на достаточно маленькое изображение, это все равно выглядит как мусор).

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

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

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

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

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

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

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

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

  1. возьмите изображения в каталог и,
  2. изменить их размер 100 х 100, с соотношением сторон исходного изображения,
  3. сохраните их все в JPEG с настройками качества 0.85,
  4. где имена файлов взяты из оригинала с помощью thumbnail. прилагается к началу

В переводе на Thumbnailator, мы могли бы выполнить вышеизложенное со следующим:

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

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

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

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

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

Chet Haase и Romain Guy также имеют подробную и очень информативную запись масштабирования изображений в своей книге, Грязные Богатые Клиенты.

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

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

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

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

вы можете попробовать использовать GraphicsMagick Система Обработки Изображений С im4java как командный интерфейс для Java.

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

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

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

из-за этого я попытался использовать 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);

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

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

вы можете использовать Marvin (pure Java image processing framework) для такого рода операций: http://marvinproject.sourceforge.net

масштаб плагин: http://marvinproject.sourceforge.net/en/plugins/scale.html

оказывается, что написание performant scaler не является тривиальным. Я сделал это однажды для проекта с открытым исходным кодом: ImageScaler.

в принципе ' java.ОУ.Изображение#getScaledInstance (int, int, int)' также выполнит эту работу, но есть неприятная ошибка с этим - см. мою ссылку для получения подробной информации.

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

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

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

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

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

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