Мне нужно изменить размер изображения при загрузке в Java / Struts. Как это сделать? - PullRequest
3 голосов
/ 18 января 2010

Мы создаем приложение, которое обрабатывает загрузку изображений. Я хочу, чтобы пользователи могли загружать изображения с заданным размером, скажем, 128x128, и затем сервер автоматически генерировал другие размеры на основе этого, такие как 64x64, 57x57 и 25x25.

Существуют ли библиотеки, которые могут мне помочь с этим?

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

Ответы [ 5 ]

2 голосов
/ 05 июля 2011

Джош,

Это именно то, что я написал imgscalr (Apache 2), чтобы сделать для этого приложения - до сих пор обрабатывается несколько сотен тысяч изображений со всегоо мире и о поврежденных результатах не сообщалось.

Когда я впервые начал изучать масштабирование изображений в Java (для этого проекта), я увидел то, что вы, вероятно, видели, ища здесь ... 200 вопросов, задающих одно и то же, 50 различных способовчтобы сделать это, 25 из них «неправильные», по-видимому, и много головной боли.

Мне действительно нравится решать подобные проблемы, поэтому я сел и собрал все отзывы, все отчеты об ошибках, все советывсе трюки и проблемы, с которыми сталкивались люди, и скомпилировали их в супер-простой 1-класс API , который просто делает «все правильно» для вас.

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

BufferedImage scaledImg = Scalr.resize(img, 150);

, но, учитывая, что вы хотите сделать несколько очень маленьких размеров, вы захотите использовать метод масштабирования КАЧЕСТВО, который занятs Крис Кэмпбелл (команда Java2D) рекомендовал метод инкрементального масштабирования И применить к результату заранее определенный ConvolveOp, чтобы немного смягчить миниатюру, потому что она очень мала.

Пример:

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

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

Если вы когда-либо работали с ConvolveOps, чтобы попытаться смягчить изображение, вы знаете, что найти правильное ядро, достаточно острое, чтобы хорошо выглядеть, но достаточно мягкое, чтобы избавиться отЧерт, ты знаешь, что это королевская PIA - та, что у меня есть предопределенная в библиотеке, является результатом недели сотрудничества с сайтом социальной сети в Бразилии, который использовал библиотеку для масштабирования изображений профиля иЯ думаю, что мы зафиксировали это.

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

библиотека также предлагает вам множество других «лучших практик» под прикрытием, например, как можно скорее сбрасывать инкрементные изображения, чтобы сократить использование памяти и не перегружать виртуальную машину, всегда сохраняет изображения в наиболее поддерживаемых типах изображений.поэтому программный конвейер в Java2D никогда не используется (вы могли заметить это, когда люди загружают GIF-файлы, если вы используете ручной код, в конечном итоге это выглядит как дерьмо - это исправляет imgscalr) и некоторые другие нюансы, которые соответствуют моему требованию дляБиблиотека "Просто делай все правильно".

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

2 голосов
/ 18 января 2010

Я использовал библиотеки ImageIO и ImageInfo для аналогичных функций.Пока они довольно хороши.

http://java.sun.com/javase/6/docs/api/javax/imageio/ImageIO.html

http://kickjava.com/src/imageinfo/ImageInfo.java.htm

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

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

2 голосов
/ 18 января 2010

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

0 голосов
/ 19 января 2010

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

Надеюсь, что эта помощь
Гийом PATRY

/**
 * Convenience method that returns a scaled instance of the
 * provided {@code BufferedImage}.
 *
 * @param img the original image to be scaled
 * @param targetWidth the desired width of the scaled instance,
 *    in pixels
 * @param targetHeight the desired height of the scaled instance,
 *    in pixels
 * @param hint one of the rendering hints that corresponds to
 *    {@code RenderingHints.KEY_INTERPOLATION} (e.g.
 *    {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR},
 *    {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR},
 *    {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC})
 * @param higherQuality if true, this method will use a multi-step
 *    scaling technique that provides higher quality than the usual
 *    one-step technique (only useful in downscaling cases, where
 *    {@code targetWidth} or {@code targetHeight} is
 *    smaller than the original dimensions, and generally only when
 *    the {@code BILINEAR} hint is specified)
 * @return a scaled version of the original {@code BufferedImage}
 */
 public BufferedImage getScaledInstance(
            BufferedImage img,
            int targetWidth,
            int targetHeight,
            Object hint,
            boolean higherQuality) {
BufferedImage ret = (BufferedImage) img;
int w, h;
if (higherQuality) {
    // Use multi-step technique: start with original size, then
    // scale down in multiple passes with drawImage()
    // until the target size is reached
    w = img.getWidth();
    h = img.getHeight();
} else {  
    // Use one-step technique: scale directly from original
    // size to target size with a single drawImage() call
    w = targetWidth;
    h = targetHeight;
}

do {
   if (higherQuality) {
      if (w > targetWidth) {
         w /= 2;
         if (w < targetWidth) {
            w = targetWidth;
         }
      } else {
         w = targetWidth;
      }
      if (h > targetHeight) {
         h /= 2;
         if (h < targetHeight) {
        h = targetHeight;
         }
      } else {
         h = targetHeight;
      }
   }
   BufferedImage tmp = null;
   if (img.getType() == 0) {
      tmp = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
   } else {
      tmp = new BufferedImage(w, h, img.getType());
   }
   Graphics2D g2 = tmp.createGraphics();
   g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
   g2.drawImage(ret, 0, 0, w, h, null);
   g2.dispose();
   ret = tmp;
} while (w != targetWidth || h != targetHeight);
return ret;

}

0 голосов
/ 19 января 2010

С связанный источник в учебнике по Swing :

/**
 * Resizes an image using a Graphics2D object backed by a BufferedImage.
 * @param srcImg - source image to scale
 * @param w - desired width
 * @param h - desired height
 * @return - the new resized image
 */
private Image getScaledImage(Image srcImg, int w, int h){
    BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2 = resizedImg.createGraphics();
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g2.drawImage(srcImg, 0, 0, w, h, null);
    g2.dispose();
    return resizedImg;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...