2013-12-16 25 views
6

pdfで画像を圧縮し、アーカイブのためにpdfを出力する方法を探しています。作成前に画像を圧縮することができないため、印刷品質が損なわれる可能性があります。大きな画像を持つPDFで圧縮する

各pdfのサイズは約8MBで、その大部分は2枚の画像で構成されています。画像はpng形式であり、生成時にpdfに変換されます(第三者発電機が使用されています)

サードパーティのツールを使用せずにjavaで圧縮する方法はありますか?私はpdfbox、itext、サードパーティ製のexe(neevia)を試してきました。サードパーティのツールはこれまでのところ私に結果を与えてくれた唯一のものです(半分程度のMBまで)。しかし、EXEへの制御を放棄したくない。 サンプルコードは以下のとおりです。

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

あなたのように画像をどのように保存されている...コンセプトの証明のために以下のコードを使用?あなたはpngのような可逆フォーマットを考えましたか? – Taylor

+0

イメージはpng形式で保存され、doc1(サードパーティ)というジェネレータを使用してドキュメントに取り込まれます。迅速な返信ありがとう:) –

+1

pdfのサイズの大部分がそれらのイメージであり、すでに圧縮されている場合、あなたは難点にあるかもしれません。私はその間にいくつかの研究を行い、pdfは圧縮した画像を保存します:https://en.wikipedia.org/wiki/Pdf#Raster_imagesこれで、pdfがどのように組み立てられているかを調整することができます。イメージを削除して再追加しない限り、pdfがすでにアセンブルされていれば、多くのことを行うことはできません。 – Taylor

答えて

16

私は正しい道に私を設定するためのブルーノのおかげ:)御馳走ワークス:)

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

(備考:あなた自身の答えの投票数の下にあるチェックマークをクリックすると、あなた自身の回答を実際に受け入れることができます) – rwong

+0

これらの2つのクラスを見つけることができません。BufferedImage、Graphics2D – Erum