Каков наилучший способ масштабирования изображений в Java?

StackOverflow https://stackoverflow.com/questions/816548

Вопрос

У меня есть веб-приложение, написанное на Java (Spring, Hibernate / JPA, Struts2), где пользователи могут загружать изображения и сохранять их в файловой системе.Я хотел бы масштабировать эти изображения так, чтобы они имели одинаковый размер для отображения на сайте.Какие библиотеки или встроенные функции обеспечат наилучшие результаты?Я буду учитывать следующие критерии при принятии своего решения (в таком порядке):

  • Бесплатный / с открытым исходным кодом (обязательно)
  • Простота в реализации
  • Качество результатов
  • Производительность
  • Размер исполняемого файла
Это было полезно?

Решение

Взгляните на Java Image API ввода-вывода изображений для чтения / записи изображения.Затем используйте Аффинная трансформация чтобы изменить размер.

Также, вот полный пример с использованием java.awt.Image.

Другие советы

Я бы действительно рекомендовал дать imgscalr - отображение взгляд.

Он выпущен по лицензии Apache 2, размещен на ГитХаб, уже развернут в нескольких веб-приложениях, имеет очень простой, но педантично документированный API, содержит код, который прозрачно устраняет 2 основные ошибки в изображениях в JDK, которые вы заметите, только если внезапно начнете получать "черные" изображения после операции масштабирования или ужасно выглядящие результаты, дает вам наилучшие результаты, доступные на Java, доступен через Maven, а также ZIP и представляет собой всего лишь один класс.

Базовое использование выглядит следующим образом:

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 320);

Это самый простой вызов, при котором библиотека сделает наилучшее предположение о качестве, учтет ваши пропорции изображения и поместит результат в ограничивающую рамку размером 320x320.ОБРАТИТЕ внимание, ограничивающая рамка - это только максимально используемый размер изображения, поскольку пропорции вашего изображения соблюдены, результирующее изображение все равно будет соответствовать этому, скажем, 320x200.

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

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 
                                       150, 100, Scalr.OP_ANTIALIAS);

Все это всего лишь примеры, API широк и охватывает все - от сверхпростых вариантов использования до очень специализированных.Вы даже можете передать свои собственные BufferedImageOps для применения к изображению (и библиотека автоматически исправит 6-летнюю ошибку BufferedImageOp JDK для вас!)

Для успешного масштабирования изображений в Java требуется гораздо больше, чем библиотека делает за вас, например, всегда сохранять изображение в одном из наиболее поддерживаемых типов изображений RGB или ARGB во время работы с ним.Под прикрытием конвейер обработки изображений Java2D возвращается к более низкому программному конвейеру, если тип изображения, используемый для каких-либо операций с изображениями, плохо поддерживается.

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

Надеюсь, это поможет.

Загляните также в java-масштабирование изображений библиотека.Это создало изображения более высокого качества, чем ImageIO.

Я знаю, что это очень старый вопрос, но я получил свое собственное решение для этого, используя стандартный Java API

import java.awt.*;
import java.awt.event.*;
import javax.imageio.*
import java.awt.image.*;

BufferedImage im, bi, bi2;
Graphics2D gfx;
int imWidth, imHeight, dstWidth, dstHeight;
int DESIRED_WIDTH = 500, DESIRED_HEIGHT = 500;

im = ImageIO.read(new File(filePath));
imWidth = im.getWidth(null);
imHeight = im.getHeight(null);

dstWidth = DESIRED_WIDTH;
dstHeight = (dstWidth * imHeight) / imWidth;

bi = new BufferedImage(dstWidth, dstHeight, im.getType());

gfx = bi.createGraphics();
gfx.drawImage(im, 0, 0, dstWidth, dstHeight, 0, 0, imWidth, imHeight, null);

bi2 = new BufferedImage(DESIRED_WIDTH, DESIRED_HEIGHT, im.getType());
gfx = bi2.createGraphics();

gfx.drawImage(bi, 0, 0, DESIRED_WIDTH, DESIRED_HEIGHT, null);

ImageIO.write(bi2, "jpg", new File(filePath));

Я уверен, что его можно улучшить и адаптировать.

Лучшим инструментом для редактирования изображений является Магия изображений и это с открытым исходным кодом.

Существует два интерфейса для языка Java:

ДЖмагик который использует интерфейс JNI для ImageMagick

и

im4java ( им4джава ) что такое интерфейс командной строки для ImageMagick

Я попробовал imgscalr по сравнению со стандартной Java 1.6, и я не могу сказать, что это лучше.

То, что я пробовал, это

BufferedImage bufferedScaled = Scalr.resize(sourceImage, Method.QUALITY, 8000, height);

и

  Image scaled = sourceImage.getScaledInstance(-1, height, Image.SCALE_SMOOTH);
  BufferedImage bufferedScaled = new BufferedImage(scaled.getWidth(null),  scaled.getHeight(null), BufferedImage.TYPE_INT_RGB);
  bufferedScaled.getGraphics().drawImage(scaled, 0, 0, null);

после 5-минутного тестирования на мой взгляд сложилось впечатление, что вторая вещь (чистая Java 1.6) дает лучшие результаты.

Обнаружил, что это будет быстрее:

public static BufferedImage getScaledInstance(final BufferedImage img, final int targetWidth, final int targetHeight,
                                              final Object hint) {
    final int type = BufferedImage.TYPE_INT_RGB;
    int drawHeight = targetHeight;
    int drawWidth = targetWidth;
    final int imageWidth = img.getWidth();
    final int imageHeight = img.getHeight();
    if ((imageWidth <= targetWidth) && (imageHeight <= targetHeight)) {
        logger.info("Image " + imageWidth + "/" + imageHeight + " within desired scale");
        return img;
    }
    final double sar = ((double) imageWidth) / ((double) imageHeight);
    if (sar != 0) {
        final double tar = ((double) targetWidth) / ((double) targetHeight);
        if ((Math.abs(tar - sar) > .001) && (tar != 0)) {
            final boolean isSoureWider = sar > (targetWidth / targetHeight);
            if (isSoureWider) {
                drawHeight = (int) (targetWidth / sar);
            }
            else {
                drawWidth = (int) (targetHeight * sar);
            }
        }
    }
    logger.info("Scaling image from " + imageWidth + "/" + imageHeight + " to " + drawWidth + "/" + drawHeight);
    final BufferedImage result = new BufferedImage(drawWidth, drawHeight, type);
    try {
        final Graphics2D g2 = result.createGraphics();
        try {
            if (hint != null) {
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            }
            g2.drawImage(img, 0, 0, drawWidth, drawHeight, null);
        }
        finally {
            g2.dispose();
        }
        return result;
    }
    finally {
        result.flush();
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top