compress pdf size with DPI via java [closed]

心不动则不痛 提交于 2019-12-11 17:30:58

问题


Looking for a way to compress pdf qulity with changing DPI in JAVA.

As example I tried PDFBox/itext libraries but still couldn't achieve it. Specially I need set the DPI if the current PDF DPI is higher (I need to reduce the quality on scanned documents)

Please note that, I am looking only free and opensource libraries.


回答1:


Finally, I found the best solution using itextpdf Library. We can reduce the DPI based on the Factor.

eg: Factor = NewDPI/CurrentDPI (FACTOR = 0.5f)

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PRStream;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfNumber;
import com.itextpdf.text.pdf.PdfObject;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.PdfImageObject;

public class ReduceSize {

    public static final String SRC = "/Users/xxxx/Downloads/low/input.pdf";
    public static final String DEST = "/Users/xxxx/Downloads/low/output.pdf";
    public static final float FACTOR = 0.5f;

    public static void main(String[] args) throws DocumentException, IOException {
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new ReduceSize().manipulatePdf(SRC, DEST);
    }
    public void manipulatePdf(String src, String dest) throws DocumentException, IOException {
        PdfReader reader = new PdfReader(src);
        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 (!PdfName.IMAGE.equals(stream.getAsName(PdfName.SUBTYPE)))
                continue;
            if (!PdfName.DCTDECODE.equals(stream.getAsName(PdfName.FILTER)))
                continue;
            PdfImageObject image = new PdfImageObject(stream);
            BufferedImage bi = image.getBufferedImage();
            if (bi == null)
                continue;
            int width = (int)(bi.getWidth() * FACTOR);
            int height = (int)(bi.getHeight() * FACTOR);
            if (width <= 0 || height <= 0)
                continue;
            BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            AffineTransform at = AffineTransform.getScaleInstance(FACTOR, FACTOR);
            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.NO_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);
        }
        reader.removeUnusedObjects();
        // Save altered PDF
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        stamper.setFullCompression();
        stamper.close();
        reader.close();
    }

}



回答2:


Please try with full compression

PdfReader reader = new PdfReader ( src) ; 
PdfStamper stamper = new PdfStamper( reader, new FileOutputStream(dest) , 
Pdfwrlter. VERSION 1_5) ; 
stamper.getWriter().setCompressionLeveI (9);
int total = reader . getNumberOfPages() + 1; 
for (int i = 1; i < total; i++) {
      reader . setpagecontent (i, reader . getpagecontent (i) ) ; 
}
stamper. setFuIICompression() ; 
stamper. close ( ) ; 



回答3:


Since you couldn't achieve your goal with other tools, may I suggest my company's offering PDF Optimizer, you can specify a trigger DPI and a target DPI for color, grayscale, and monochrome images. If you prefer you can accomplish the same thing programmatically with the PDF Library.



来源:https://stackoverflow.com/questions/55466422/compress-pdf-size-with-dpi-via-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!