Настройка уровня сжатия jpg с помощью ImageIO в Java
Я использую javax.imageio.ImageIO
сохранить BufferedImage
как файл jpeg.
В частности, я создал следующую функцию Java:
public static void getScreenShot(BufferedImage capture, Path folder, String filename) {
try {
ImageIO.write(capture, "jpeg", new File(folder.toString()+"/"+filename+".jpg"));
} catch (AWTException | IOException ex) {
Logger.getLogger(ScreenShotMaker.class.getName()).log(Level.SEVERE, null, ex);
}
}
аналогично любому программному обеспечению для обработки изображений, я хочу изменить уровень сжатия файла jpeg. Тем не менее, я ищу эту опцию, которая, кажется, отсутствует в ImageIO
.
могу ли я установить уровень сжатия и как?
2 ответов
вы должны использовать JPEGImageWriteParam
а затем сохраните изображение с помощью ImageWriter.write()
. Прежде чем писать, установите выход через ImageWriter.setOutput
.
установить уровень сжатия следующим образом:
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
jpegParams.setCompressionQuality(1f);
здесь 1f
номер поплавка который стоит для качества 100%. Значение по умолчанию:около 70% если я не ошиблась.
редактировать
тогда, вы должны сделать следующее, Чтобы получить пример ImageWriter
. Есть два пути, короткий и длинный (я так, на всякий случай).
The короткий путь (по предложению Лапо в одном комментарии):
final ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
// specifies where the jpg image has to be written
writer.setOutput(new FileImageOutputStream(
new File(folder.toString() + "/" + filename + ".jpg")));
// writes the file with given compression level
// from your JPEGImageWriteParam instance
writer.write(null, new IIOImage(capture, null, null), jpegParams);
или времени
// use IIORegistry to get the available services
IIORegistry registry = IIORegistry.getDefaultInstance();
// return an iterator for the available ImageWriterSpi for jpeg images
Iterator<ImageWriterSpi> services = registry.getServiceProviders(ImageWriterSpi.class,
new ServiceRegistry.Filter() {
@Override
public boolean filter(Object provider) {
if (!(provider instanceof ImageWriterSpi)) return false;
ImageWriterSpi writerSPI = (ImageWriterSpi) provider;
String[] formatNames = writerSPI.getFormatNames();
for (int i = 0; i < formatNames.length; i++) {
if (formatNames[i].equalsIgnoreCase("JPEG")) {
return true;
}
}
return false;
}
},
true);
//...assuming that servies.hasNext() == true, I get the first available service.
ImageWriterSpi writerSpi = services.next();
ImageWriter writer = writerSpi.createWriterInstance();
// specifies where the jpg image has to be written
writer.setOutput(new FileImageOutputStream(
new File(folder.toString() + "/" + filename + ".jpg")));
// writes the file with given compression level
// from your JPEGImageWriteParam instance
writer.write(null, new IIOImage(capture, null, null), jpegParams);
более краткий способ-получить ImageWriter
непосредственно с ImageIO
:
ImageWriter jpgWriter = ImageIO.getImageWritersByFormatName("jpg").next();
ImageWriteParam jpgWriteParam = jpgWriter.getDefaultWriteParam();
jpgWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
jpgWriteParam.setCompressionQuality(0.7f);
ImageOutputStream outputStream = createOutputStream(); // For example implementations see below
jpgWriter.setOutput(outputStream);
IIOImage outputImage = new IIOImage(image, null, null);
jpgWriter.write(null, outputImage, jpgWriteParam);
jpgWriter.dispose();
вызов ImageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT)
необходимо для того, чтобы явно установить уровень сжатия (качество).
на ImageWriteParam.setCompressionQuality()
1.0f
максимальное качество, минимальное обжатие, пока 0.0f
минимальное качество, максимальное обжатие.
ImageWriter.setOutput
должен быть передан ImageOutputStream
. Хотя метод принимает Object
, согласно документации обычно нет поддерживается:
использование общего
Object
кромеImageOutputStream
предназначено для писателей которые взаимодействуют сразу с прибором вывода или протоколом воображения. Набор юридических классов рекламируется поставщиком услугgetOutputTypes
метод; большинство авторов вернут одноэлементный массив, содержащий толькоImageOutputStream.class
указать, что они принимают толькоImageOutputStream
.
большинство случаев должны обрабатываться этими двумя классы:
-
FileImageOutputStream
- реализацияImageOutputStream
который записывает свой вывод непосредственно вFile
илиRandomAccessFile
. -
MemoryCacheImageOutputStream
- реализацияImageOutputStream
который записывает свой вывод в обычныйOutputStream
. Обычно используется сByteArrayOutputStream
(спасибо за совет, @lmiguelmh!).