Как получить миниатюру хорошего качества - PullRequest
18 голосов
/ 12 октября 2011

Я пытаюсь создать миниатюру высокого качества этого изображения с Java и Scalr 3.2

full scale image

Этосоответствующий исходный код, где THUMB_WIDTH = 77 и THUMB_HEIGHT = 57

BufferedImage srcImg = ImageIO.read(new File(sourceFile)); 
BufferedImage dstImg = Scalr.resize(srcImg, Scalr.Method.QUALITY, 
    THUMB_WIDTH, THUMB_HEIGHT); 
ImageIO.write(dstImg, format, new File(destFile));

Если я использую format = "png", вот результат:

png thumbnail

ЕслиЯ использую format = "jpg", вот результат:

jpg thumbnail

С идентификатором imagemagick Я обнаружил, что JPEG сохраняется с качеством 75этого совершенно недостаточно, чтобы создать красивый эскиз.PNG мне тоже не очень нравится.

Вот вывод идентификатора исходного файла и двух миниатюр:

$ identify 42486_1.jpg 42486_s1.jpg 42486_s1.png 
42486_1.jpg JPEG 580x435 580x435+0+0 8-bit DirectClass 50.6KB 0.000u 0:00.000
42486_s1.jpg[1] JPEG 77x58 77x58+0+0 8-bit DirectClass 2.22KB 0.000u 0:00.000
42486_s1.png[2] PNG 77x58 77x58+0+0 8-bit DirectClass 12.2KB 0.000u 0:00.000

Вопросы

  • Как улучшить качество созданного эскиза?
  • Как сохранить JPEG с более высоким качеством?Я хотел бы попробовать с более высоким качеством и сравнить результаты.Я не смог найти ничего в JavaDoc для ImageIO.write.
  • Почему я говорю Scalr, что мои максимальные размеры 77x57, и он выводит изображение 77x58?Я думаю, что это для поддержания пропорции, но это моя максимальная ширина и максимальная высота.Ширина или высота могут быть меньше, но не больше.

ОБНОВЛЕНИЕ : С помощью веб-поиска я нашел статью о том, как настроить качество сжатия изображений JPEG .Я написал свой собственный метод для сохранения BufferedImage с настройкой качества:

/**
 * Write a JPEG file setting the compression quality.
 * 
 * @param image
 *                a BufferedImage to be saved
 * @param destFile
 *                destination file (absolute or relative path)
 * @param quality
 *                a float between 0 and 1, where 1 means uncompressed.
 * @throws IOException
 *                 in case of problems writing the file
 */
private void writeJpeg(BufferedImage image, String destFile, float quality) 
throws IOException {
    ImageWriter writer = null;
    FileImageOutputStream output = null;
    try {
        writer = ImageIO.getImageWritersByFormatName("jpeg").next();
        ImageWriteParam param = writer.getDefaultWriteParam();
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionQuality(quality);
        output = new FileImageOutputStream(new File(destFile));
        writer.setOutput(output);
        IIOImage iioImage = new IIOImage(image, null, null);
        writer.write(null, iioImage, param);
    } catch (IOException ex) {
        throw ex;
    } finally {
        if (writer != null) writer.dispose();
        if (output != null) output.close();
    }
}

Вот результаты.PNG:

png thumbnail

Качество JPEG 75:

jpg thumbnail

Качество JPEG 90 (граватары при переполнении стека сохраняются как качество JPEG 90):

jpg thumbnail quality 90

и размер файла:

thumb90.jpg JPEG 77x58 77x58+0+0 8-bit DirectClass 6.89KB 0.000u 0:00.000

ОБНОВЛЕНИЕ 2 : тест для сравнения Scalr с java-image-scaling .

private void scaleAndSaveImageWithScalr(String sourceFile, String destFile, int width, int height)
    throws IOException {
    BufferedImage sourceImage = ImageIO.read(new File(sourceFile));
    BufferedImage destImage = Scalr.resize(sourceImage, Scalr.Method.QUALITY, width, height);
    writeJpeg(destImage, destFile, JPEG_QUALITY);
}

private void scaleAndSaveImageWithJImage(String sourceFile, String destFile, int width, int height)
    throws IOException {
    BufferedImage sourceImage = ImageIO.read(new File(sourceFile));
    ResampleOp resampleOp = new ResampleOp(width, height);
    resampleOp.setFilter(ResampleFilters.getLanczos3Filter());
    resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
    BufferedImage destImage = resampleOp.filter(sourceImage, null);
    writeJpeg(destImage, destFile, JPEG_QUALITY);
}

Качество JPEG 90, сгенерированное с помощью Scalr:

jpg thumb from scalr

Качество JPEG 90, сгенерированное с масштабированием изображения java:

jpg thumb from java-image-scaling

Я не получил дальнейших отзывов, поэтому я лично пришел к выводу, что java-image-scaling обеспечивает превосходное качество, и поэтому я выбираю именно эту библиотеку.

Ответы [ 5 ]

1 голос
/ 30 декабря 2012

@ Stivlo, я прошу прощения за то, что не ответил на это, я никогда не получал никаких уведомлений от SO по этому вопросу.

java-image-scaling действительно имеет несколько хороших фильтров, которые помогут с точной настройкой, если вам это нужно. Тем не менее, в v4.2 imgscalr я добавил новый ULTRA_QUALITY , который может приблизить вас к тому, что вы хотите.

Я надеюсь, что это помогает, но понимаю, что на это, к сожалению, отвечает почти год спустя. Извините за это.

1 голос
/ 12 октября 2011

Это не полный ответ на ваш вопрос, но:

Относительно качества JPEG:

Качество сжатия можно установить с помощью ImageWriteParam как , описанного здесь . Они предлагают использовать int значение 0 | 1, но я считаю, что вы должны указать значение с плавающей запятой в диапазоне от 0,0 до 1,0.

Относительно ваших проблем масштабирования:

С домашней страницы Scalr :

ПРИМЕЧАНИЕ. Если указана ширина и высота, нарушающие пропорции (например, попытка изменить размер изображения 800 × 600 до 150 × 150 квадрат) библиотека сначала посмотрит на ориентацию изображения (пейзаж / квадрат или портрет), а затем выберите основное измерение (ландшафт или квадрат использует ширину, портрет использует высоту) для пересчета правильный вторичный размер; игнорирование того, что было передано пользователем это нарушало пропорции.

В вашем случае основным размером будет ширина 77, и, следовательно, ваш предел высоты 57 будет игнорироваться.

0 голосов
/ 25 августа 2016

Если вы хотите получить высококачественный результат, используйте библиотеку [RapidDecoder] [1]. Это просто, как следует:

import rapid.decoder.BitmapDecoder; ... Bitmap bitmap = BitmapDecoder.from (getResources (), R.drawable.image) .scale (ширина, высота) .useBuiltInDecoder (правда) .decode () Не забудьте использовать встроенный декодер, если вы хотите уменьшить масштаб менее чем на 50% и получить результат HQ.

0 голосов
/ 07 августа 2014

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

java-image-scaling может создать некрасивую границу вокруг прозрачных краев в зависимости от изображения, и это выглядит очень плохо. Я не нашел способа избежать этого.

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

0 голосов
/ 21 марта 2012

Я провел те же тесты, и java-image-scaling определенно показал лучшие результаты для миниатюр размером менее 250 пикселей.Он также поддерживает резкую фильтрацию, которая улучшает результаты.

Я храню обе библиотеки, поскольку синтаксис Scalr часто проще, всего одна строка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...