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);

posted @ 2020-08-24 10:34  鸡米饭  阅读(2392)  评论(0编辑  收藏  举报