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