Ответ 1
Посмотрите API-интерфейс Java Image I/O API для чтения/записи изображения. Затем используйте AffineTransform для изменения размера.
Кроме того, вот вам полный пример с использованием java.awt.Image.
У меня есть веб-приложение, написанное на Java (Spring, Hibernate/JPA, Struts2), где пользователи могут загружать изображения и хранить их в файловой системе. Я хотел бы масштабировать эти изображения, чтобы они имели согласованный размер для отображения на сайте. Какие библиотеки или встроенные функции будут предлагать наилучшие результаты? Я буду учитывать следующие критерии при принятии моего решения (в этом порядке):
Посмотрите API-интерфейс Java Image I/O API для чтения/записи изображения. Затем используйте AffineTransform для изменения размера.
Кроме того, вот вам полный пример с использованием java.awt.Image.
Я действительно рекомендовал бы взглянуть на imgscalr.
Он выпущен под лицензией Apache 2, размещенной на GitHub, уже развернута в нескольких веб-приложениях, имеет очень простой, но документально подтвержденный API, имеет код, который работает вокруг 2 основных ошибок изображения в JDK для вас прозрачно, что вы только заметите, если вдруг начнете получать "черные" изображения после шкалы операционные или ужасные результаты, дает вам наилучшие результаты, доступные на Java, доступен через Maven, а также ZIP и является всего лишь одним классом.
Основное использование выглядит следующим образом:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 320);
Это самый простой вызов, когда библиотека будет лучше всего оценивать качество, оценивать пропорции изображения и соответствовать результатам в ограничительной рамке 320x320. ПРИМЕЧАНИЕ. Ограничивающая рамка - это только максимальная используемая W/H, так как ваши пропорции изображения соблюдены, получившееся изображение будет по-прежнему соблюдаться, скажем 320x200.
Если вы хотите переопределить автоматический режим и заставить его получить наилучший результат и даже применить к результату очень мягкий фильтр с псевдонимом, чтобы он выглядел еще лучше (особенно хорош для эскизов), этот вызов выглядят так:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY,
150, 100, Scalr.OP_ANTIALIAS);
Все это всего лишь примеры, API обширен и охватывает все, от суперпростых вариантов использования до очень специализированных. Вы можете даже передать свой собственный BufferedImageOps, который будет применен к изображению (и библиотека автоматически исправляет 6-летнюю ошибку JDK BufferedImageOp для вас!)
Существует намного больше возможностей для масштабирования изображений в Java, успешно выполняемых для вас, например, всегда сохраняя изображение в одном из наилучших поддерживаемых типов изображений RGB или ARGB во время работы с ним. Под обложками конвейер обработки изображений Java2D возвращается к более низкому программному конвейеру, если тип изображения, используемый для любых операций с изображениями, плохо поддерживается.
Если бы все это звучало как большая головная боль, это вроде того... почему я написал библиотеку и открыл ее, поэтому люди могли просто изменять размеры своих изображений и продолжать свою жизнь, не беспокоясь об этом.
Надеюсь, что это поможет.
Посмотрите также на java-image-scaling. Он создал более качественные изображения, которые 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));
Я уверен, что его можно улучшить и адаптировать.
Лучшим инструментом для редактирования изображений является ImageMagick, и он является открытым исходным кодом.
Для языка Java существуют два интерфейса:
JMagick, который использует интерфейс JNI для ImageMagick
и
im4java что такое интерфейс командной строки для 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();
}
}