Compress PDF with large images on Android

This question compress pdf with large images via java gives the code to compress PDF with iText in Java. Since Android does not have Graphics2D, AffineTransform, BufferedImage and ImageIO, I was thinking about adapting this code using the Bitmap class.

UPDATE: Thanks to @TilmanHausherr, I changed the compression to JPEG and got the following working code.

public static void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    // Read the file
    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 (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);
            byte[] imageBytes= image.getImageAsBytes();

            Bitmap bmp;
            bmp = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
            if (bmp == null) continue;

            int width=bmp.getWidth();
            int height=bmp.getHeight();

            Bitmap outBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
            Canvas outCanvas=new Canvas(outBitmap);
            outCanvas.drawBitmap(bmp, 0f, 0f, null);

            ByteArrayOutputStream imgBytes = new ByteArrayOutputStream();

            outBitmap.compress(Bitmap.CompressFormat.JPEG, 50, imgBytes);

            stream.setData(imgBytes.toByteArray(), false, PdfStream.BEST_COMPRESSION);
            stream.put(PdfName.FILTER, PdfName.DCTDECODE);
            imgBytes.close();
        }
    }
    // Save altered PDF
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    stamper.close();
    reader.close();
}

      

Unfortunately, JPEG is not a good option in my case as I have transparencies. Using PNG creates empty images even if I set the FLATEDECODE filter, which I understand should be a PNG filter.

The only working code I have for PNG is this:

   public static void manipulatePdf(String src, String dest) throws IOException, DocumentException {
    // Read the file
    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 (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())) {
            byte[] streamBytes= PdfReader.getStreamBytes(stream);
            stream.setData(streamBytes, true, PdfStream.BEST_COMPRESSION);
        }
    }
    // Save altered PDF
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
    stamper.close();
    reader.close();
}

      

The above code is passing compression to iText, which may or may not be enough.

+3


source to share





All Articles