2016-12-09 7 views
0

PDFをイメージにレンダリングするとき、icepdfはOutOfMemoryErrorを使ってランダムに爆発します。それは日食メモリ・アナライザでA0ページまたは同様に大規模なドキュメントページ レンダリングされたイメージのサイズをicepdfで制限する

  • をレンダリングOOMへ

    1. 閉じる私は、メモリ内の1/2GBのイメージを検索:私は二つのことを見つけ、これを追跡しようとしています。

    これは、出力イメージのサイズを管理可能なものに制限することを示唆しています。私はこれをするのが一番簡単な方法だろうか?

    icepdfのPageオブジェクトを見ましたが、そこには常にPage.BOUNDARY_CROPBOXを使用することを強くお勧めします。他の用途はJavadocに記載されていないようです。

    出力画像のサイズをDocument.getPageImageに制限する方法や、OOMを防止するために使用できるその他の方法(Xmxを増やすこと以外はできません)を制限する方法はありますか。画質の低下はオプションです。しかし、それは全部ではなく、「特大の」画像にのみ適用されるべきです。

    すでにDocument.paintPage()を使用して定義済みの画像を使用しようとしましたが、これでは十分ではありませんでした。

    Debugは、問題のあるドキュメントを最終的に拡大することを可能にしました。ので、これは本当に巨大である高さ= 18676、幅= 13248となり

    2016-12-09T14:23:35Z DEBUG class org.icepdf.core.pobjects.Document 1  MEMFREE: 712484296 of 838860800 
    2016-12-09T14:23:35Z DEBUG class org.icepdf.core.pobjects.Document 1  LOADING: ..../F1-2.pdf 
    2016-12-09T14:23:37Z WARN class org.icepdf.core.pobjects.graphics.ScaledImageReference 1  Error loading image: 9 0 R Image stream= {Type=XObject, Length=8 0 R, Filter=FlateDecode, ColorSpace=DeviceGray, Decode=[1, 0], Height=18676, Width=13248, Subtype=Image, BitsPerComponent=1, Name=Im1} 9 0 R 
    

    :私のようなログを取得します。

    イメージのロード中にOOMが既に発生していると思うので、後でスケーリングしても問題はありません。また、それはプロパティーorg.icepdf.core.imageReference=scaledが十分早くヒットしないようです。

    私にとっては、このような大きめの画像は無視しても問題ありません。万一?

  • 答えて

    1

    PDFコンテンツをデコードするときに、画像読み込みはメモリで最もメモリが高くなります。現時点では、実際に大きな画像の画像読み込みをオフにする賢明な方法はありませんが、これを実装したい場合は、いくつかのヒントを教えてください。

    ImageReferenceFactory.javaクラスは、システムプロパティorg.icepdf.core.imageReferenceの背後にあるファクトリです.getImageReferenced()のデフォルトがImageStreamReferenceであることがわかります。あなたはこのように新しいImageReferenceタイプを作成することができます

    public static org.icepdf.core.pobjects.graphics.ImageReference 
    getImageReference(ImageStream imageStream, Resources resources, GraphicsState graphicsState, 
            Integer imageIndex, Page page) { 
        switch (scaleType) { 
         case SCALED: 
          return new ScaledImageReference(imageStream, graphicsState, resources, imageIndex, page); 
         case SMOOTH_SCALED: 
          return new SmoothScaledImageReference(imageStream, graphicsState, resources, imageIndex, page); 
         case MIP_MAP: 
          return new MipMappedImageReference(imageStream, graphicsState, resources, imageIndex, page); 
         case SKIP_LARGE: 
          return new SkipLargeImageReference(imageStream, graphicsState, resources, imageIndex, page); 
         default: 
          return new ImageStreamReference(imageStream, graphicsState, resources, imageIndex, page); 
        } 
    } 
    

    次はあなたの新しいSkipLargeImageReferenceクラスでクラスImageStreamReferenceを拡張することができます。次に、call()メソッドを次のようにオーバーライドすると、定義されたMAX_SIZEを超えるイメージの読み込みはスキップされます。

    サイドノートで
    public BufferedImage call() { 
        BufferedImage image = null; 
        if (imageStream.getWidth() < MAX_SIZE && imageStream.getHeight() < MAX_SIZE){ 
         long start = System.nanoTime(); 
         try { 
          image = imageStream.getImage(graphicsState, resources); 
         } catch (Throwable e) { 
          logger.log(Level.WARNING, "Error loading image: " + imageStream.getPObjectReference() + 
            " " + imageStream.toString(), e); 
         } 
         long end = System.nanoTime(); 
         notifyImagePageEvents((end - start)); 
         return image; 
        } 
        return null; 
    } 
    

    :これは一度だけ画像をデコードして、あなたがorg.icepdf.core.imageReference=defaultを使用していることを確認してください画像をデコードするために必要なメモリの量を最小限にすること。 org.icepdf.core.imageReference=scaledはフルサイズの画像を実際にデコードし、スケールを実行して非常に大きなメモリスパイクを作成します。私たちはNIOのダイレクトByteBuffersを試しています。これはデコードメモリの使用量をヒープから外すことを約束しています。

    +0

    これは私が大まかに推測したことです。イメージは読み込み中に非常に大きくなることがあります。 SkipImageStreamReferenceを実装するというあなたの提案を試みました。Xmx = 900m(意図的に少し小さい)では、1500x1500より小さい画像でもOOMで爆発します。 10000^2〜20000^2のサイズの構造図がたくさんあるので、線形にスケーリングされている場合は90GB以上のRAMが必要です。 – Harald

    +0

    メモリマップされたバイトバッファはOOMを防ぎますが、それでも多くのRAMまたは膨大なスワップ領域またはページファイルが必要になり、パフォーマンスが低下します。私はPDFレンダリングが実際にどのように機能するのか分かりませんが、最初のレンダリングでさえも要求されたサイズに解像度を下げる方法があるはずです。 – Harald

    関連する問題