Instantly share code, notes, and snippets.

Embed
What would you like to do?
A Processing sketch to save JPG images with variable compression
/*
JPEG COMPRESSION
Jeff Thompson | 2016 | www.jeffreythompson.org
For web-based images, controlling the compression of a JPG
can optimize dimensions and file size. The built-in save()
command for Processing doesn't give us this control, but we
can use Java's ImageIO to add this functionality.
*/
import java.awt.image.BufferedImage;
import javax.imageio.plugins.jpeg.*;
import javax.imageio.*;
import javax.imageio.stream.*;
void setup() {
// set the amount of compression
// 1.0 = no compression, largest image file
// 0.5 = 50% compression
// 0.0 = 100% compression, smallest image file
float compressionLevel = 0.5;
// image to compress and image to output
String imageFile = sketchPath("") + "test.jpg";
String outputFilename = sketchPath("") + "compressed.jpg";
try {
// setup JPG output
JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
jpegParams.setCompressionQuality(compressionLevel);
final ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
writer.setOutput(new FileImageOutputStream(new File(outputFilename)));
// load image to compress
// alternatively, you could access the sketch's pixel array and save it
PImage img = loadImage(imageFile);
img.loadPixels();
// output to BufferedImage object
// create the object, then write the pixel data to it
BufferedImage out = new BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_RGB);
for (int i=0; i<img.pixels.length; i++) {
out.setRGB(i%img.width, i/img.width, img.pixels[i]);
}
// save it!
writer.write(null, new IIOImage(out, null, null), jpegParams);
println("Saved!");
}
catch (Exception e) {
println("Problem saving... :(");
println(e);
}
// all done
exit();
}
@kasperkamperman

This comment has been minimized.

kasperkamperman commented Feb 12, 2018

Thanks for sharing this code. I've utilised it in an example that shows how to upload images with Processing to a webserver. See: https://www.kasperkamperman.com/blog/processing-save-image-to-web/

I've modified the loadImage part to get rid of the for-loop, that walks through all the pixels. I suppose the solution below could be faster (although I didn't test it).

Instead of the code from line 41 - 49 I've used:
BufferedImage in = (BufferedImage) img.getNative();
BufferedImage out = new BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_RGB);
out.getGraphics().drawImage(in,0,0,null);

(based on this resource: https://blog.idrsolutions.com/2009/10/converting-java-bufferedimage-between-colorspaces/).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment