Total Pageviews

2019/02/13

[Java] How to compress TIF file with multiple pages?

Problem
How to compress TIF file with multiple pages in Java?

How-To
Add dependency in your pom.xml
    <dependency>
     <groupId>com.github.jai-imageio</groupId>
     <artifactId>jai-imageio-core</artifactId>
     <version>1.3.1</version>
    </dependency>

Here has sample code:
package demo.util;

import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;

import com.github.jaiimageio.impl.plugins.tiff.TIFFImageReaderSpi;
import com.github.jaiimageio.impl.plugins.tiff.TIFFImageWriterSpi;

import lombok.extern.slf4j.Slf4j;

/*
 *  tif 壓縮程式
 */
@Slf4j
public class TiffCompression {

    /**
     * 用 Deflate 進行 TIF 壓縮.
     * 
     * @param source
     *            來源 TIF 檔
     * @param target
     *            壓縮後的 TIF 檔
     * @throws IOException
     */
    public static void compress(File source, File target) throws IOException {
        ImageIO.scanForPlugins();
        ImageWriter writer = null;

        try (InputStream fis = new BufferedInputStream(new FileInputStream(source));
                ImageInputStream iis = ImageIO.createImageInputStream(fis);
                ImageOutputStream targetTif = ImageIO.createImageOutputStream(target);) {
            // tif 來源檔
            TIFFImageReaderSpi readSpi = new TIFFImageReaderSpi();
            ImageReader reader = readSpi.createReaderInstance();
            reader.setInput(iis);

            // tif 目的檔
            TIFFImageWriterSpi tiffspi = new TIFFImageWriterSpi();
            writer = tiffspi.createWriterInstance();
            writer.setOutput(targetTif);

            // 取得 tif 分頁
            Integer pageSize = reader.getNumImages(true);
            BufferedImage image[] = new BufferedImage[pageSize];

            // 設定壓縮參數
            ImageWriteParam param = writer.getDefaultWriteParam();
            param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
            // 有試過 CCITT T.4, CCITT T.6, PackBits, Deflate 與 LZW,Deflate 壓縮比最佳
            param.setCompressionType("Deflate");

            // 逐頁讀出檔案,並寫入目的地
            for (int i = 0; i < pageSize; i++) {
                image[i] = reader.read(i);
                IIOImage iioImage = new IIOImage(image[i], null, null);
                if (i == 0) {
                    writer.write(null, iioImage, param);
                } else {
                    writer.writeInsert(-1, iioImage, param);
                }
            }
        } catch (IOException e) {
            throw new IOException("TIF 壓縮失敗", e);
        } finally {
            if (writer != null) {
                writer.dispose();
            }
        }
    }
}




1 comment:

Svante said...
This comment has been removed by the author.