Im having a problem with image compression. I used the answer described in this question compress pdf with large images via java if i set the FACTOR variable to 0.9f or 1f (original size) the resulting pdf file starts to get bigger than the ORIGINAL. But that is not the case for all files. Some files created by myself are getting smaller like planned but some just get bigger like +1/3rd and i get black backgrounds on some images ontop of it. this is getting even worse when im using the normal image compression without resizing the image This is my test file.
Lowagies method: (resize the images)
// TODO Auto-generated method stub
PdfName key = new PdfName("ITXT_SpecialId");
PdfName value = new PdfName("123456789");
// Read the file
PdfReader reader = new PdfReader(args[0]);
int n = reader.getXrefSize();
PdfObject object;
PRStream stream;
// Look for image and manipulate image stream
for (int i = 0; i < n; i++) {
object = reader.getPdfObject(i);
if (object == null || !object.isStream())
continue;
stream = (PRStream)object;
// if (value.equals(stream.get(key))) {
PdfObject pdfsubtype = stream.get(PdfName.SUBTYPE);
System.out.println(stream.type());
if (pdfsubtype != null && pdfsubtype.toString().equals(PdfName.IMAGE.toString())) {
PdfImageObject image = new PdfImageObject(stream);
BufferedImage bi = image.getBufferedImage();
if (bi == null) continue;
int width = (int)(bi.getWidth() * 1f);
int height = (int)(bi.getHeight() * 1f);
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
AffineTransform at = AffineTransform.getScaleInstance(1f, 1f);
Graphics2D g = img.createGraphics();
g.drawRenderedImage(bi, at);
ByteArrayOutputStream imgBytes = new ByteArrayOutputStream();
ImageIO.write(img, "JPG", imgBytes);
stream.clear();
stream.setData(imgBytes.toByteArray(), false, PRStream.BEST_COMPRESSION);
stream.put(PdfName.TYPE, PdfName.XOBJECT);
stream.put(PdfName.SUBTYPE, PdfName.IMAGE);
stream.put(key, value);
stream.put(PdfName.FILTER, PdfName.DCTDECODE);
stream.put(PdfName.WIDTH, new PdfNumber(width));
stream.put(PdfName.HEIGHT, new PdfNumber(height));
stream.put(PdfName.BITSPERCOMPONENT, new PdfNumber(8));
stream.put(PdfName.COLORSPACE, PdfName.DEVICERGB);
}
}
// Save altered PDF
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("/Applications/XAMPP/xamppfiles/htdocs/pdf_compress/download/"+args[2]));
stamper.close();
reader.close();
My method (Using real compression by setting the quallity of the image instead of resizing it)
PdfReader reader = new PdfReader(args[0]);
// Read the file
int n = reader.getXrefSize();
PdfObject object;
PRStream stream;
// Look for image and manipulate image stream
for (int i = 0; i < n; i++) {
object = reader.getPdfObject(i);
if (object == null || !object.isStream())
continue;
stream = (PRStream)object;
PdfObject pdfsubtype = stream.get(PdfName.SUBTYPE);
if (pdfsubtype != null && pdfsubtype.toString().equals(PdfName.IMAGE.toString())) {
System.out.println(pdfsubtype.length());
PdfImageObject image = new PdfImageObject(stream);
BufferedImage bi = image.getBufferedImage();
if (bi == null) continue;
int width = (int)(bi.getWidth());
int height = (int)(bi.getHeight());
if(width <=30 || height <=30){
continue;
}
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
AffineTransform at = null;
Graphics2D g = img.createGraphics();
g.drawRenderedImage(bi, at );
ByteArrayOutputStream imgBytes = new ByteArrayOutputStream();
Iterator iter = ImageIO.getImageWritersByFormatName("JPG");
ImageWriter writer = (ImageWriter)iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
// here goes the compression
iwp.setCompressionQuality(Float.valueOf(args[1]));
ImageOutputStream imageos = ImageIO.createImageOutputStream(imgBytes);
writer.setOutput(imageos);
IIOImage images = new IIOImage(img, null, null);
writer.write(null,images , iwp);
imageos.close();
writer.dispose();
stream.clear();
stream.setData(imgBytes.toByteArray(), false, PRStream.BEST_COMPRESSION);
stream.put(PdfName.TYPE, PdfName.XOBJECT);
stream.put(PdfName.SUBTYPE, PdfName.IMAGE);
stream.put(PdfName.FILTER, PdfName.DCTDECODE);
stream.put(PdfName.WIDTH, new PdfNumber(width));
stream.put(PdfName.HEIGHT, new PdfNumber(height));
stream.put(PdfName.BITSPERCOMPONENT, new PdfNumber(8));
stream.put(PdfName.COLORSPACE, PdfName.DEVICERGB);
}
}
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("/Applications/XAMPP/xamppfiles/htdocs/pdf_compress/download/"+args[2]));
stamper.setFullCompression();
stamper.close();
reader.close();
System.out.println("Done");
What is wrong with the code? Should i use a different image compression method? Are there any others?