4

複数ページの tiff に関するいくつかの質問と圧縮に関するいくつかの質問を見てきましたが、2 つをリンクしている (私が見た) ものはありません。この質問は、私が見た限りでは非常に近いものであり、私を信じられないほど近くに置いているので、願っています. 言及されているOracleフォーラムのスレッド(圧縮を使用した複数ページのPDFからTIFFへの変換について話している)に行きましたが、これを行うためにコードを完成させることに近づいていると思います。誰でも手伝ってもらえますか? これを短くするために、try/catch を削除します (基本的に、コンソールにメッセージを出力して false を返すだけです)。

 public static boolean CompressedTiff(List<BufferedImage> images, File path)
 {
    if (!path.getParentFile().exists())
         path.getParentFile().mkdirs();
    path.createNewFile();
    ImageOutputStream ios;
         ios = ImageIO.createImageOutputStream(path);

    Iterator<ImageWriter> imageWriters = ImageIO.getImageWritersByFormatName("TIFF");
    ImageWriter writer = (ImageWriter)imageWriters.next();
    writer.setOutput(ios);
    TIFFImageWriteParam writeParam = (TIFFImageWriteParam)writer.getDefaultWriteParam();
    writeParam.setCompressionMode(2);
    writeParam.setCompressionType("LZW"); 
    writer.prepareWriteSequence(null);

    for(int i = 0; i < images.size(); i++)
    {
        ImageTypeSpecifier spec = ImageTypeSpecifier.createFromRenderedImage(images.get(i));
        javax.imageio.metadata.IIOMetadata metadata = writer.getDefaultImageMetadata(spec, writeParam);
        IIOImage iioImage = new IIOImage(images.get(i), null, metadata);
        writer.writeToSequence(iioImage, writeParam);
        images.get(i).flush();//modified after release.

        images.get(i).flush();
        writer.endWriteSequence();
        ios.flush();
        writer.dispose();
        ios.close();
    }
    return true;

}

次のパスの writer.writeToSequence で、prepareWriteSequence を呼び出す必要があると言って失敗しました。に変更しました

 writer.prepareWriteSequence(metadata);
 writer.writeToSequence(iioImage, writeParam);

以前の writer.prepareWriteSequence(null); も削除されました。

ファイルを適切にナビゲートしているように見えますが、出力はレンダリング可能な tif のタイプではありません。マルチページまたはそれ以外。

私は JAI をインストールしているので、何らかの方法でそれを使用して圧縮イメージを実現できれば、それは素晴らしいことです。私が使用しているTIFFを生成するコードはこれを使用していますが、ページに圧縮を追加する限り、何も機能していません。

編集: ios.flush(); の束を追加しました。ios.close(); catch ブロックで呼び出し、レンダリングできない TIFF の問題を防ぎます。ただし、最初のページを超えてページを追加することはありません。

4

1 に答える 1

3

それが役立つ場合、これは TiffImageWriteParam を変更して圧縮を設定するために使用するコードです。

try {
    jWriteParam.setCompressionMode(_compression != TiffCompression.NO_COMPRESSION 
                  ? ImageWriteParam.MODE_EXPLICIT : ImageWriteParam.MODE_DISABLED);

    if (_compression != TiffCompression.NO_COMPRESSION) {
        // this code corrects the compression if, say, the client code asked for
        // CCITT but the actual image pixel format was CMYK or some other non-1 bit
        // image type.
        TiffCompression mode = recastToValidCompression(_compression, pf);
        jWriteParam.setCompressionType(getCompressionType(mode));
        TIFFCompressor compressor = getTiffCompressor(mode, jWriteParam, shouldUsePredictor(pf));
        jWriteParam.setTIFFCompressor(compressor);
        if (_compression == TiffCompression.JPEG_COMPRESSION) {
            // Java supports setting to 1.0 (ie 100), but it will not actually do lossless (maybe)
            if (_jpegQuality == 100 && !jWriteParam.isCompressionLossless())
                continue;
            jWriteParam.setCompressionQuality(toJavaJpegQuality());
        }
    }
}
catch (UnsupportedOperationException e)
{
    // this shouldn't get here, but you should consider what to do if it does.
    // set a default? throw?
}

ここに getTiffCompressor() があります:

private TIFFCompressor getTiffCompressor (TiffCompression compression, TIFFImageWriteParam writeParam, boolean usePredictor)
{
    int predictor = usePredictor 
            ? BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING 
            : BaselineTIFFTagSet.PREDICTOR_NONE;

    switch (compression) 
    {
    case GROUP_3_FAX_ENCODING:
        return new TIFFT4Compressor();
    case GROUP_4_FAX_ENCODING:
        return new TIFFT6Compressor();
    case JPEG_COMPRESSION:
        return new TIFFJPEGCompressor(writeParam);
    case MACINTOSH_PACKBITS:
        return new TIFFPackBitsCompressor();
    case DEFLATE:
        return new TIFFDeflateCompressor(writeParam, predictor);
    case LZW:
        return new TIFFLZWCompressor(predictor);
    case MODIFIED_HUFFMAN:
        return new TIFFRLECompressor();
    case NO_COMPRESSION:
    case DEFAULT:
    default:
        return null;
    }
}

TiffCompression は、TIFF ファイルに提供する圧縮をモデル化する独自の列挙型です。最後に、getCompressionType() を次に示します。

private String getCompressionType (TiffCompression compression)
{
    switch (compression)
    {
    case GROUP_3_FAX_ENCODING:
        return "CCITT T.4";
    case GROUP_4_FAX_ENCODING:
        return "CCITT T.6";
    case JPEG_COMPRESSION:
        return "JPEG";
    case MACINTOSH_PACKBITS:
        return "PackBits";
    case DEFLATE:
        return "Deflate";
    case LZW:
        return "LZW";
    case MODIFIED_HUFFMAN:
        return "CCITT RLE";
    case NO_COMPRESSION:
    case DEFAULT:
    default:
        return null;
    }
}

私のコードは任意の数の画像をエンコードするように構築されており、あなたのコードはそうではないため、すべてを示すことはできません。したがって、コード構造は大きく異なります。私の場合は、よりオープンなアーキテクチャを持つシーケンス ライターを使用するようにエンコーダをセットアップしました。画像を取り込み、オプションでデフォルトの圧縮を変更するイベントを起動し、ライターを作成してパラメーターを書き込み、メタデータ/画像タグを設定し、進行状況イベントを起動して、シーケンスを書き込みます。次に、最後に書き込まれた ifd にパッチを適用する必要があります。これは、tiff エンコーダーがそれらを破損して書き込むため、パッチを適用する必要があるためです。

于 2012-04-25T15:25:32.533 に答える