1. 程式人生 > 實用技巧 >TwelveMonkeys處理圖片

TwelveMonkeys處理圖片

TwelveMonkeys處理圖片

專案中用到圖片處理功能,主要是調整tiff圖片的dpi,並進行圖片壓縮。

之前用的是jai的方式處理的,主要jar包是jai_imageio、jai_codec等。

因為jai的包名為com.sun開頭。甲方認為後續如果調整jdk可能會出問題(我瞭解的情況是:jai作為單獨jar包引入,並未和jdk繫結,只是包名是com.sun開頭),讓調整為TwelveMonkeys的ImageIO-tiff。

jai處理圖片

import javax.imageio.ImageIO;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageReaderSpi;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageEncoder;
import com.sun.media.jai.codec.TIFFEncodeParam;
import com.sun.media.jai.codec.TIFFField;
import com.sun.media.jai.codecimpl.TIFFImageDecoder;
import javax.imageio.spi.IIORegistry;
import java.awt.image.RenderedImage;
import java.io.ByteArrayInputStream;

public class ImageUtil {

    private final static Logger logger = LoggerFactory.getLogger(ImageUtil.class);

    private static final double PRINTER_RESOLUTION = 300.0;
    private static final String COMPRESSION_TYPE = "CCITT T.6";
    private static final long[] DPI_DATA = {300L, 300L};

    static {
        IIORegistry registry = IIORegistry.getDefaultInstance();
        registry.registerServiceProvider(new TIFFImageWriterSpi());
        registry.registerServiceProvider(new TIFFImageReaderSpi());
    }

    /**
     * 修改tiff的畫素值
     *
     * @param bout
     * @throws IOException
     */
    public static ByteArrayOutputStream changeResolution(byte[] bout) {

        try {
            RenderedImage renderedImage = ImageIO.read(new ByteArrayInputStream(bout));
            TIFFEncodeParam param = new TIFFEncodeParam();
            param.setCompression(TIFFEncodeParam.COMPRESSION_GROUP4);
            if (DPI_DATA[0] > 0 || DPI_DATA[1] > 0) {
                int fieldCount = 1;
                if (DPI_DATA[0] > 0 && DPI_DATA[1] > 0) {
                    fieldCount = 2;
                }
                TIFFField[] tiffFields = new TIFFField[fieldCount];
                int index = 0;
                if (DPI_DATA[0] > 0) {
                    long xdpiArray[][] = new long[1][2];
                    xdpiArray[0] = new long[]{DPI_DATA[0], 1};
                    TIFFField xRes = new TIFFField(TIFFImageDecoder.TIFF_X_RESOLUTION,
                            TIFFField.TIFF_RATIONAL, 1, xdpiArray);
                    tiffFields[index++] = xRes;
                }
                if (DPI_DATA[1] > 0) {
                    long ydpiArray[][] = new long[1][2];
                    ydpiArray[0] = new long[]{DPI_DATA[1], 1};
                    TIFFField yRes = new TIFFField(TIFFImageDecoder.TIFF_Y_RESOLUTION,
                            TIFFField.TIFF_RATIONAL, 1, ydpiArray);
                    tiffFields[index] = yRes;
                }
                param.setExtraFields(tiffFields);
            }
            // 輸出到檔案流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageEncoder enc = ImageCodec.createImageEncoder("TIFF", out, param);
            enc.encode(renderedImage);
            out.close();
            return out;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

TwelveMonkeys ImageIO-tiff

maven座標

<dependency>
    <groupId>com.twelvemonkeys.imageio</groupId>
    <artifactId>imageio-tiff</artifactId>
    <version>3.6</version>
</dependency>

網上關於使用TwelveMonkeys ImageIO-tiff調整tiff的dpi的介紹不是很多,還是在TwelveMonkeys的github倉庫issue中找到了啟發。

import com.twelvemonkeys.imageio.metadata.Entry;
import com.twelvemonkeys.imageio.metadata.tiff.Rational;
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadata;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.RenderedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ImageUtil {

    private final static Logger logger = LoggerFactory.getLogger(ImageUtil.class);

    private static final double PRINTER_RESOLUTION = 300.0;
    private static final String COMPRESSION_TYPE = "CCITT T.6";
    private static final long DPI_DATA = 300L;
    private static final String FORMAT = "TIFF";

    /**
     * 修改tiff的畫素值
     *
     * @param bout
     * @throws IOException
     */
    public static ByteArrayOutputStream changeResolution(byte[] bout) throws IOException {
        RenderedImage renderedImage = ImageIO.read(new ByteArrayInputStream(bout));
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(FORMAT);
        ImageWriter writer = writers.next();
        ImageWriteParam param = writer.getDefaultWriteParam();
        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        param.setCompressionType(COMPRESSION_TYPE);
        param.setCompressionQuality(1f);
        final List<Entry> entries = new ArrayList<Entry>();
        entries.add(new TIFFEntry(TIFF.TAG_X_RESOLUTION, new Rational(DPI_DATA)));
        entries.add(new TIFFEntry(TIFF.TAG_Y_RESOLUTION, new Rational(DPI_DATA)));
        final IIOMetadata tiffImageMetadata = new TIFFImageMetadata(entries);
        // 輸出到流
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageOutputStream output = ImageIO.createImageOutputStream(out);
        writer.setOutput(output);
        writer.write(null, new IIOImage(renderedImage, null, tiffImageMetadata), param);
        out.close();
        return out;
    }

}

github issue地址https://github.com/haraldk/TwelveMonkeys/issues/439

注意issue中回答的程式碼是錯誤的。正確的應該是 writer.write(null, new IIOImage(renderedImage, null, tiffImageMetadata), param);