2009-05-03 1 views
12

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

  • Free/Open Source (основные)
  • Простота внедрения
  • Качество результатов
  • Performance
  • Размер исполнительный документ

ответ

4

Посмотрите на Java Image I/O API, чтобы прочитать/записать изображение. Затем используйте AffineTransform для изменения размера.

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

+0

В примере, который вы цитируете, используется 'getScaledInstance()', а не AffineTransform. Так что это? Я читал смешанные рецензии, что 'getScaledInstance' не так впечатляет ... – gdbj

4

Посмотрите также на java-image-scaling библиотеки. Он создал более качественные изображения, которые ImageIO.

0

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

Есть два интерфейса для языка Java:

JMagick, который использует интерфейс JNI для ImageMagick

и

im4java что интерфейс командной строки для ImageMagick

9

Я действительно рекомендую давая imgscalr вид.

Он выпущен под лицензией Apache 2, размещенный на GitHub, были развернуты в нескольких веб-приложений уже имеет очень простой, но pedantically documented 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-летнюю ошибку BufferImageOp JDK для вас!)

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

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

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

0

Я пробовал 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) дает лучшие результаты.

-1

Найдено это будет быстрее:

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(); 
    } 
} 
1

Я знаю, что это очень старый вопрос, но я получил свое собственное решение для этого с помощью стандартного 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)); 

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