Not just how to change JPEG compression, but to do so without losing the JPEG's metadata. That's the problem I had to figure out for this program I'm writing in Clojure. I found out and wrote about how to
do this in Java yesterday. Finally, here's the same thing in
Clojure:
Short explanation of what the code is doing is interwoven with the code here. The code without the comments (for easy copy/paste'ing) is at bottom.
First, we import a few Java classes:
(require 'clojure.java.io)
(import [javax.imageio IIOImage ImageIO]
[javax.imageio.plugins.jpeg JPEGImageWriteParam])
(try
Then we get the default JPEG image reader and writer:
(let [image-reader (.next (ImageIO/getImageReadersByFormatName "jpg"))
image-writer (.next (ImageIO/getImageWritersByFormatName "jpg"))]
Now we open up streams to the input and output JPEG Files. Note that
with-open
will close the streams for you, so you don't have to later.
(with-open [image-input-stream (ImageIO/createImageInputStream
(clojure.java.io/file "path/to/inputFile.jpg"))
image-output-stream (ImageIO/createImageOutputStream
(clojure.java.io/file "path/to/outputFile.jpg"))]
Next, mate the reader/writer to the respective streams:
(.setInput image-reader image-input-stream)
(.setOutput image-writer image-output-stream)
Then we'll get the JPEG input file into a container that will also contain the metadata:
(let [iio-image (IIOImage. (.read image-reader 0) nil
(.getImageMetadata image-reader 0))
Now set up the JPEG quality (
ie, compression) level desired. Here it's set to 0.7 (where 1 is highest quality, and 0 is highest compression):
jpeg-params (doto (.getDefaultWriteParam image-writer)
(.setCompressionMode JPEGImageWriteParam/MODE_EXPLICIT)
(.setCompressionQuality 0.7))]
Finally we get to write out the JPEG file with the new compression level:
(.write image-writer nil iio-image jpeg-params)))
Lastly, make sure to clean up the reader/writer's so they don't continue to hog system resources (yes, you have to do this even though Java has garbage collection):
(finally
(do (.dispose image-writer)
(.dispose image-reader)))))
To
recap, here it is again without the comments, just the bare code: