import java.awt.*; import java.awt.color.*; import java.awt.image.*; import java.io.*; import java.util.*; import javax.imageio.*; import javax.imageio.metadata.*; import javax.imageio.stream.*; public class JPEGPerf { private static BufferedImage getScaledInstance(BufferedImage img, int targetWidth) { int w = targetWidth; int h = (int)(((double)targetWidth / img.getWidth()) * img.getHeight()); return getScaledInstance(img, w, h, RenderingHints.VALUE_INTERPOLATION_BILINEAR, true); } private static BufferedImage getScaledInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint, boolean higherQuality) { BufferedImage ret = (BufferedImage)img; int w, h; if (higherQuality) { // Use multi-step technique: start with original size, then // scale down in multiple passes with drawImage() // until the target size is reached w = img.getWidth(); h = img.getHeight(); } else { // Use one-step technique: scale directly from original // size to target size with a single drawImage() call w = targetWidth; h = targetHeight; } do { if (higherQuality && w > targetWidth) { w /= 2; if (w < targetWidth) { w = targetWidth; } } if (higherQuality && h > targetHeight) { h /= 2; if (h < targetHeight) { h = targetHeight; } } // NOTE: create a new image in the same format as the original, // preserving any embedded color space... ColorModel cm = ret.getColorModel(); WritableRaster raster = ret.getRaster().createCompatibleWritableRaster(w, h); BufferedImage tmp = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null); Graphics2D g2 = tmp.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); g2.drawImage(ret, 0, 0, w, h, null); g2.dispose(); ret = tmp; } while (w != targetWidth || h != targetHeight); return ret; } private static BufferedImage readImage(String filename, boolean convertToSRGB) throws Exception { File infile = new File(filename); ImageInputStream in = ImageIO.createImageInputStream(infile); ImageReader reader = ImageIO.getImageReaders(in).next(); reader.setInput(in); ImageReadParam irp = reader.getDefaultReadParam(); Iterator specs = reader.getImageTypes(0); while (specs.hasNext()) { ImageTypeSpecifier spec = specs.next(); //System.out.println(spec + " " + spec.getColorModel().getColorSpace()); if (!convertToSRGB && !spec.getColorModel().getColorSpace().isCS_sRGB()) { irp.setDestinationType(spec); break; } } //System.out.println("TESTING: " + filename + ", convert to sRGB: " + convertToSRGB); BufferedImage orig = reader.read(0, irp); //System.out.println(orig); in.close(); return orig; } private static final ColorSpace srgbCS = ColorSpace.getInstance(ColorSpace.CS_sRGB); private static BufferedImage maybeColorConvertImage(BufferedImage image) { ColorModel origCM = image.getColorModel(); ColorSpace origCS = origCM.getColorSpace(); if (!origCS.isCS_sRGB() && (origCM instanceof ComponentColorModel)) { WritableRaster raster = image.getRaster(); ColorConvertOp convert = new ColorConvertOp(origCS, srgbCS, null); convert.filter(raster, raster); ColorModel newCM = new ComponentColorModel(srgbCS, origCM.hasAlpha(), origCM.isAlphaPremultiplied(), origCM.getTransparency(), origCM.getTransferType()); image = new BufferedImage(newCM, raster, newCM.isAlphaPremultiplied(), null); } return image; } private static void test(String filename, boolean optimized) throws Exception { long start = System.currentTimeMillis(); BufferedImage img = readImage(filename, !optimized); img = maybeColorConvertImage(img); long end = System.currentTimeMillis(); System.out.println("total: " + (end-start)); } private static void writeImage(BufferedImage img, String filename, String format) throws Exception { System.out.println("writing: " + filename); File outfile = new File(filename); ImageWriter writer = ImageIO.getImageWritersBySuffix(format).next(); ImageOutputStream out = ImageIO.createImageOutputStream(outfile); writer.setOutput(out); ImageWriteParam iwp = writer.getDefaultWriteParam(); if ("jpg".equals(format)) { iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); iwp.setCompressionQuality(0.85f); } writer.write(null, new IIOImage(img, null, null), iwp); } public static void main(String[] args) throws Exception { //String filename = "flower.jpg"; String filename = "gorilla.jpg"; System.out.println("ColorSpace conversion done by JPEGImageReader..."); for (int i = 0; i < 3; i++) { test(filename, false); } System.out.println("ColorSpace conversion done in-place by ColorConvertOp..."); for (int i = 0; i < 3; i++) { test(filename, true); } } }