2017-07-02 11 views
0

iText 7 http://itextpdf.com/ライブラリを使用します:itext7-io-7.0.2.jar、itext7-kernel-7.0.2.jar、itext7-layout-7.0.2.jar、slf4j- api-1.7.25.jar、slf4j-simple-1.7.25.jar、 はドキュメントページの背景イメージを設定し、いくつかの類似したページを同じドキュメント(pdf-file)に保存します。イメージファイルiText 7 jarファイルから背景イメージを読み取る

final String IMAGE = "/resources/image.jpg"; 

は、jarファイルのリソースとして保存する必要があります。 java.awtでの

ImageData imgData = ImageDataFactory.create(new Main().loadImage(IMAGE), true); 

コード:ImageDataをオブジェクトは、メソッドがcom.itextpdf.io.image.ImageDataFactoryの(java.awt.Imageの画像、をjava.awt.Color色)を作成し使用して作成されます。 image.BufferedImage loadImage(文字列imageFilename)メソッドです:

private BufferedImage loadImage(String imageFilename) { 
    BufferedImage img = null; 
    try { 
     img = javax.imageio.ImageIO.read(getClass().getResourceAsStream(imageFilename)); 
    } catch (IOException ex) { 
     Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    return img; 
} 

のImageDataオブジェクトをループで使用されます。

Document document = ... (get Document object) 
PdfDocument pdf = document.getPdfDocument(); 
PageSize pageSize = pdf.getDefaultPageSize(); 
PdfPage page = pdf.addNewPage(); 
for (int i = 0; i < documents.size(); i++) { 
     PdfCanvas canvas = new PdfCanvas(page); 
     canvas.addImage(imgData, pageSize, false); 
     ... (add document body) 
     if (i < documents.size() - 1) { 
      page = pdf.addNewPage(); 
      document.add(new AreaBreak(AreaBreakType.NEXT_PAGE)); 
     } 
} 
document.close(); 

問題は、私は、JARファイルからプログラムを実行した後、私は得ることですpdf-文書はmuです(createメソッドを使用しますが、画像のバイトからのImageDataオブジェクトを作成した場合

ImageData imgData = ImageDataFactory.create("src/resources/image.jpg"); 

:私は、直接画像参照(81メガバイト対17ページの文書のための9メガバイト)を使用して、IDEからプログラムを実行したときよりも大きなCH com.itextpdf.io.image.ImageDataFactoryのバイト[]バイト、ブールrecoverImage):

ImageData imgData = ImageDataFactory.create(new Main().loadImageByte(IMAGE), true); 

と使用バイト[] loadImageByte(文字列imageFilename)方法:

private byte[] loadImageByte(String imageFilename) { 
    byte[] dataBytes = null; 
    try { 
     InputStream is = getClass().getResourceAsStream(imageFilename); 
     dataBytes = new byte[is.available()]; 
     is.read(dataBytes); 
    } catch (IOException ex) { 
     Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    return dataBytes; 
} 

SI作成されたpdfドキュメントのzeは、IDEからプログラムを実行するとき、またはjarファイルから開始するときの両方で小さくなります。 ただし、後者の場合、文書が開かないため、Adobe Acrobat 9に「画像のデータが不十分です」というエラーが表示されます(両方の文書のバイトが異なります)。

ファイルサイズが異なる理由は何ですか?jarファイルからプログラムによって小さなサイズのpdfドキュメントを取得する方法はありますか?

+0

確かめるためにすべてを詳細に調べる必要がありますが、ファイルサイズが異なると考えられる理由は、サイズが小さい場合、イメージはXOBjectとして一度保存され、ドキュメント全体と大きなファイルの場合は、その都度イメージが追加されます。 –

+0

'loadImageByte'経由の2回目の試みについて:' is.available() 'を使ってリソースファイルのサイズを調べます。これは間違っていますが、 'is.available()'は実際に使用されている 'InputStream'クラスに応じてより小さい値を返します。実際に使用される' InputStream'クラスは、ファイルシステム内のリソースjarアーカイブから圧縮されたリソースを使用してjarファイルから実行されます。 – mkl

+0

問題を再現するためにイメージファイルを共有できますか? – mkl

答えて

0

問題は、画像データをラップするPdfImageXObjectを使用することによって解決される。

public static final String IMAGE = "/resources/image.jpg"; 
public static final String DEST = "result.pdf"; 

public static void main(String[] args) throws FileNotFoundException { 

    int pageNumber = 5; 
    PdfWriter writer = new PdfWriter(DEST); 
    PdfDocument pdf = new PdfDocument(writer); 
    Document document = new Document(pdf, PageSize.A4.rotate()); 
    ImageData imgData = ImageDataFactory.create(new Main().loadImageByte(IMAGE), true); 
    /*Wrapping image data in a PdfImageXObject*/ 
    PdfImageXObject imgObject = new PdfImageXObject(imgData); 
    /*Calculate the page area for the image - the image size will change*/ 
    PageSize pageSize = pdf.getDefaultPageSize(); 
    Rectangle rectangle = new Rectangle(pageSize.getWidth(), pageSize.getHeight()); 
    /*Loop*/ 
    PdfPage page = pdf.addNewPage(); 
    for (int i = 0; i < pageNumber; i++) { 
     PdfCanvas canvas = new PdfCanvas(page); 
     /*Add background image as PdfImageXObject*/ 
     canvas.addXObject(imgObject, rectangle); 

     (PDF building blocks adding) 

     if (i < pageNumber - 1) { 
      page = pdf.addNewPage(); 
      document.add(new AreaBreak(AreaBreakType.NEXT_PAGE)); 
     } 
    } 
    document.close(); 
} 

結果のPDFファイルの検査PDFXplorerには、あなたがDocumentオブジェクトに複数回、同じ前景画像を追加するときにすることを示していますadd(Image image)メソッドでは、画像は単一のPDF XObjectへの参照として追加されます。同時に、addImage(ImageData image, Rectangle rect, boolean asInline)メソッドを使用してPdfCanvasオブジェクトに背景イメージを同様に複数追加すると、いくつかの異なるPDF XObjectインスタンスが作成されます。 これらのメソッドの引数の違いに注意してください。 iText 7ライブラリのソースコードを分析したところ、ImageクラスはImageインスタンスが作成されるたびに作成されるPdfXObjectメンバを持っていますが、ImageDataクラスは対応するPdfXObjectに関連付けられていません。

関連する問題