2013-12-16 15 views
6

Tìm cách nén hình ảnh trong pdf và xuất bản pdf để lưu trữ. Tôi không thể nén hình ảnh trước khi tạo vì nó sẽ làm ảnh hưởng đến chất lượng của bản in.nén pdf với hình ảnh lớn qua java

Kích thước của mỗi bản PDF là khoảng 8MB với số lượng lớn ảnh này được tạo thành từ 2 hình ảnh. Hình ảnh có định dạng png và được đưa vào pdf trong quá trình tạo (máy phát của bên thứ ba được sử dụng)

Có cách nào để nén chúng trong java mà không sử dụng công cụ của bên thứ 3. Tôi đã thử với pdfbox, itext và một bên thứ ba exe (neevia), công cụ của bên thứ ba là người duy nhất đã cho tôi bất kỳ kết quả nào cho đến nay (giảm xuống còn khoảng một nửa MB) nhưng tôi không muốn từ bỏ quyền kiểm soát một exe . Mã mẫu dưới đây.

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

gì bạn đang lưu những hình ảnh như? Bạn đã xem xét một định dạng lossless như png chưa? – Taylor

+0

Hình ảnh được lưu trữ ở định dạng png và được đưa vào tài liệu bằng cách sử dụng trình tạo có tên doc1 (bên thứ 3). Cảm ơn bạn đã trả lời nhanh :) –

+1

Nếu phần lớn kích thước pdf là những hình ảnh đó và chúng đã được nén, bạn có thể bị bế tắc. Tôi đã làm một số nghiên cứu trong tạm thời và pdf sẽ lưu trữ hình ảnh với nén: https://en.wikipedia.org/wiki/Pdf#Raster_images, do đó bạn có thể muốn điều chỉnh cách pdf được lắp ráp. Không chắc chắn nhiều có thể được thực hiện một khi pdf đã được lắp ráp, trừ khi bạn loại bỏ và thêm lại hình ảnh. – Taylor

Trả lời

16

tôi đã sử dụng mã dưới đây cho một bằng chứng của khái niệm ... Làm việc một điều trị :) Nhờ Bruno lập tôi trên con đường đúng đắn :)

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

(Lưu ý: bạn thực sự có thể chấp nhận câu trả lời của riêng bạn bằng cách nhấp vào dấu kiểm bên dưới số phiếu bầu của câu trả lời của bạn.) – rwong

+0

tôi không thể tìm thấy hai lớp này BufferedImage, Graphics2D – Erum