iText: Reduce image quality (for reducing the resulting PDF size)

Scale the image first, then open the scaled image with iText.

There is a create method in ImageDataFactory that accepts an AWT image. Scale the image using AWT tools first, then open it like this:

String imagePath = "C:\\path\\to\\image.jpg";
java.awt.Image awtImage = ImageIO.read(new File(imagePath));

// scale image here
int scaledWidth = awtImage.getWidth(null) / 2;
int scaledHeight = awtImage.getHeight(null) / 2;
BufferedImage scaledAwtImage = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = scaledAwtImage.createGraphics();
g.drawImage(awtImage, 0, 0, scaledWidth, scaledHeight, null); 
g.dispose();

/* 
Optionally pick a color to replace with transparency.
Any pixels that match this color will be replaced by tansparency.
*/
Color bgColor = Color.WHITE;

Image itextImage = new Image(ImageDataFactory.create(scaledAwtImage, bgColor));

For better tips on how to scale an image, see How can I resize an image using Java?

If you still need the original size when adding to PDF, just scale it back up again.

itextImage.scale(2f, 2f);

Note: This code is untested.


EDIT in response to comments on bounty

You got me thinking and looking. It appears iText treats importing an AWT image as a raw image. I presume it treats it the same as a BMP, which simply writes the pixel data using /FlateDecode, which is probably significantly less than optimal. The only way I can think of to achieve your requirement would be to use ImageIO to write the scaled image to the file system or a ByteArrayOutputStream as a jpeg, then use the resultant file/bytes to open with iText.

Here's an updated example using byte arrays. If you want to get any more fancy with compression levels and such, refer here.

String imagePath = "C:\\path\\to\\image.jpg";
java.awt.Image awtImage = ImageIO.read(new File(imagePath));

// scale image here
int scaledWidth = awtImage.getWidth(null) / 2;
int scaledHeight = awtImage.getHeight(null) / 2;
BufferedImage scaledAwtImage = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g = scaledAwtImage.createGraphics();
g.drawImage(awtImage, 0, 0, scaledWidth, scaledHeight, null); 
g.dispose();

ByteArrayOutputStream bout = new ByteArrayOutputStream()
ImageIO.write(scaledAwtImage, "jpeg", bout);
byte[] imageBytes = bout.toByteArray();

Image itextImage = new Image(ImageDataFactory.create(imageBytes));