2016-06-08 2 views
0

Я видел several examples создания сжатых изображений JPG из Java BufferedImage объектов путем записи в файл, но возможно ли выполнить сжатие JPG без записи в файл? Возможно, написав ByteArrayOutputStream, как this?Java BufferedImage JPG сжатие без записи в файл

ImageWriter jpgWriter = ImageIO.getImageWritersByFormatName("jpg").next(); 
ImageWriteParam jpgWriteParam = jpgWriter.getDefaultWriteParam(); 
jpgWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 
jpgWriteParam.setCompressionQuality(0.7f); 

ImageOutputStream outputStream = createOutputStream(); 
jpgWriter.setOutput(outputStream); 
IIOImage outputImage = new IIOImage(image, null, null); 

// in this example, the JPG is written to file... 
// jpgWriter.write(null, outputImage, jpgWriteParam); 
// jpgWriter.dispose(); 

// ...but I want to compress without saving, such as 
ByteArrayOutputStream compressed = ??? 
+1

это 33 upvotes, что вам еще нужно ?? – gpasch

+0

@gpasch, я могу ошибаться, но я не думаю, что любой из вопросов, которые я связывал, чтобы делать то, что я хочу. – JeffThompson

ответ

4

Просто передайте ваш ByteArrayOutputStream в ImageIO.createImageOutputStream(...) так:

// The important part: Create in-memory stream 
ByteArrayOutputStream compressed = new ByteArrayOutputStream(); 
ImageOutputStream outputStream = ImageIO.createImageOutputStream(compressed); 

// NOTE: The rest of the code is just a cleaned up version of your code 

// Obtain writer for JPEG format 
ImageWriter jpgWriter = ImageIO.getImageWritersByFormatName("jpg").next(); 

// Configure JPEG compression: 70% quality 
ImageWriteParam jpgWriteParam = jpgWriter.getDefaultWriteParam(); 
jpgWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); 
jpgWriteParam.setCompressionQuality(0.7f); 

// Set your in-memory stream as the output 
jpgWriter.setOutput(outputStream); 

// Write image as JPEG w/configured settings to the in-memory stream 
// (the IIOImage is just an aggregator object, allowing you to associate 
// thumbnails and metadata to the image, it "does" nothing) 
jpgWriter.write(null, new IIOImage(image, null, null), jpgWriteParam); 

// Dispose the writer to free resources 
jpgWriter.dispose(); 

// Get data for further processing... 
byte[] jpegData = compressed.toByteArray(); 

PS: По умолчанию ImageIO будет использовать кэширование диска при создании ImageOutputStream. Это может замедлить запись потока в памяти. Чтобы отключить его, используйте ImageIO.setCache(false) (отключает кэширование диска глобально) или явно создать MemoryCacheImageOutputStream (локальный), как это:

ImageOutputStream outputStream = new MemoryCacheImageOutputStream(compressed); 
+0

Спасибо @haraldK! Я не совсем уверен, что здесь происходит. Если данные JPG сжаты и записаны в 'ByteArrayOutputStream' с именем' сжатый', что делает раздел 'IIOImage'? – JeffThompson

+1

@JeffThompson Я обновил ответ для вас. 'IIOImage' ничего не делает, он просто содержит данные, которые вы хотите написать. Если вы хотите узнать больше, я предлагаю вам ознакомиться с документацией по API или следовать руководству. :-) – haraldK

+1

@ downwoter Пожалуйста, не «наказывайте» абсолютно правильный и правильный ответ, просто потому что * вы * думаете, что вопрос не стоит отвечать. Вместо этого сверните вопрос или голосуйте, чтобы закрыть его. – haraldK