2013-12-16 16 views
6

Szukasz sposobu na kompresowanie obrazów w pliku pdf i wydrukowanie pliku PDF do archiwizacji. Nie mogę skompresować obrazów przed stworzeniem, ponieważ mogłoby to pogorszyć jakość wydruku.skompresować pdf z dużymi obrazami za pośrednictwem java

Wielkość każdego pliku PDF wynosi około 8 MB, a większość składa się z 2 obrazów. Obrazy są w formacie PNG i są wprowadzane do formatu PDF podczas generowania (używany generator 3rd party)

Czy istnieje sposób kompresowania tych plików w Javie bez użycia narzędzia innej firmy. Próbowałem z pdfboxem, itextem i 3rd party exe (neevia), jedynym narzędziem, które dało mi dotychczas jakieś wyniki (do około pół MB), ale nie chcę zrezygnować z kontroli dla exe . Przykładowy kod znajduje się poniżej.

import java.io.BufferedReader; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.util.Arrays; 

import org.apache.pdfbox.exceptions.COSVisitorException; 
import org.apache.pdfbox.pdmodel.PDDocument; 
import org.apache.pdfbox.pdmodel.common.PDStream; 

import com.itextpdf.text.DocumentException; 
import com.itextpdf.text.pdf.PdfReader; 
import com.itextpdf.text.pdf.PdfStamper; 
import com.itextpdf.text.pdf.PdfWriter; 

public class compressPDF { 

public static void main (String[] args) throws IOException, DocumentException, COSVisitorException { 


    /* 
    * Using PDF Box 
    */ 

    PDDocument doc; // = new PDDocument(); 

    doc = PDDocument.load("C:/_dev_env_/TEMP/compressPDF/TRPT_135002_1470_20131212_121423.PDF"); 

    PDStream stream= new PDStream(doc); 
    stream.addCompression(); 

    doc.save("C:/_dev_env_/TEMP/compressPDF/compressed_pdfBox.pdf"); 

    doc.close(); 

    /* 
    * Using itext 
    */ 

    PdfReader reader = new PdfReader("C:/_dev_env_/TEMP/compressPDF/TRPT_135002_1470_20131212_121423.PDF"); 

    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("C:/_dev_env_/TEMP/compressPDF/compressed_Itext.pdf"), PdfWriter.VERSION_1_5); 
    stamper.setFullCompression(); 
    stamper.getWriter().setCompressionLevel(50); 
    int total = reader.getNumberOfPages() + 1; 
    for (int i = 1; i < total; i++) { 
     reader.setPageContent(i, reader.getPageContent(i)); 
    } 
    stamper.close(); 
    reader.close(); 

    /* 
    * Using 3rd party - Neevia 
    */ 
    try { 
    Process process = new ProcessBuilder("C:/Program Files (x86)/neeviaPDF.com/PDFcompress/cmdLine/CLcompr.exe","C:/_dev_env_/TEMP/compressPDF/TRPT_135002_1470_20131212_121423.PDF", "C:/_dev_env_/TEMP/compressPDF/compressed_Neevia.pdf").start(); 
    InputStream is = process.getInputStream(); 
    InputStreamReader isr = new InputStreamReader(is); 
    BufferedReader br = new BufferedReader(isr); 
    String line; 

    System.out.printf("Output of running %s is:", Arrays.toString(args)); 

    while ((line = br.readLine()) != null) { 
     System.out.println(line); 
    } 
    } catch (Exception e) { 
     System.out.println(e); 
    } finally { 
     System.out.println("Created!!"); 
    } 

} 

} 
+0

Co zapisywania obrazów jak? Czy rozważałeś format bezstratny, jak png? – Taylor

+0

Obrazy są przechowywane w formacie png i przenoszone do dokumentu za pomocą generatora o nazwie doc1 (strona trzecia). Dziękuję za szybką odpowiedź :) –

+1

Jeśli większość rozmiaru pdf to te obrazy i są już skompresowane, możesz być w impasie. Zrobiłem trochę badań w międzyczasie, a pdf będzie przechowywać obrazy z kompresją: https://en.wikipedia.org/wiki/Pdf#Raster_images, więc możesz chcieć dostroić sposób, w jaki plik PDF jest montowany. Nie wiem, ile można zrobić, gdy już plik pdf zostanie już złożony, chyba że usuniesz i ponownie dodasz obrazy. – Taylor

Odpowiedz

16

Użyłem poniższy kod na dowód koncepcji ... działa wspaniale :) Dzięki Bruno ustawiania mnie na właściwą drogę :)

package compressPDF; 

import java.awt.Graphics2D; 
import java.awt.geom.AffineTransform; 
import java.awt.image.BufferedImage; 
import java.io.ByteArrayOutputStream; 
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 ResizeImage { 

/** The resulting PDF file. */ 
//public static String RESULT = "results/part4/chapter16/resized_image.pdf"; 
/** The multiplication factor for the image. */ 
public static float FACTOR = 0.5f; 

/** 
* Manipulates a PDF file src with the file dest as result 
* @param src the original PDF 
* @param dest the resulting PDF 
* @throws IOException 
* @throws DocumentException 
*/ 
public void manipulatePdf(String src, String dest) throws IOException, DocumentException { 
    PdfName key = new PdfName("ITXT_SpecialId"); 
    PdfName value = new PdfName("123456789"); 
    // 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); 
      BufferedImage bi = image.getBufferedImage(); 
      if (bi == null) continue; 
      int width = (int)(bi.getWidth() * FACTOR); 
      int height = (int)(bi.getHeight() * FACTOR); 
      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.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(dest)); 
    stamper.close(); 
    reader.close(); 
} 

/** 
* Main method. 
* 
* @param args no arguments needed 
* @throws DocumentException 
* @throws IOException 
*/ 
public static void main(String[] args) throws IOException, DocumentException { 
    //createPdf(RESULT); 
    new ResizeImage().manipulatePdf("C:/_dev_env_/TEMP/compressPDF/TRPT_135002_1470_20131212_121423.PDF", "C:/_dev_env_/TEMP/compressPDF/compressTest.pdf"); 
} 

} 
+1

(Uwaga: możesz zaakceptować własną odpowiedź, klikając na znacznik wyboru pod liczbą głosów własnej odpowiedzi). – rwong

+0

Nie mogę znaleźć tych dwóch klas. BufferedImage, Graphics2D – Erum