java中image与tif图片的互转

时间:2022-11-16 19:01:54
/* ****************************************************************************
 * Author:humf             工作中的点点滴滴
 * ****************************************************************************
 * 
 * Purpose.:Abstract class for converting buffered images to TIF images
 *          with proper TIF tags set.
 *          
 * ****************************************************************************
 */

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;


import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.stream.ImageOutputStream;


import com.sun.media.imageio.plugins.tiff.BaselineTIFFTagSet;
import com.sun.media.imageio.plugins.tiff.TIFFDirectory;
import com.sun.media.imageio.plugins.tiff.TIFFField;
import com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam;
import com.sun.media.imageio.plugins.tiff.TIFFTag;
import com.sun.media.imageio.stream.FileChannelImageOutputStream;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageMetadata;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriter;
import com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi;


/**
 * Abstract Class TIFConvert
 * 
 * @author Pedro J Rivera
 * 
 */
public abstract class TIFConvert {
public static final int CLR_RGB = BufferedImage.TYPE_INT_RGB;
public static final int CLR_GRAY_SCALE = BufferedImage.TYPE_BYTE_GRAY;
public static final int CLR_BLACK_WHITE = BufferedImage.TYPE_BYTE_BINARY;


public static final int COMPRESSION_NONE = BaselineTIFFTagSet.COMPRESSION_NONE;
public static final int COMPRESSION_CCITT_RLE = BaselineTIFFTagSet.COMPRESSION_CCITT_RLE;
public static final int COMPRESSION_CCITT_T_4 = BaselineTIFFTagSet.COMPRESSION_CCITT_T_4;
public static final int COMPRESSION_CCITT_T_6 = BaselineTIFFTagSet.COMPRESSION_CCITT_T_6;
// COMPRESSION_JPEG   
public static final int COMPRESSION_LZW = BaselineTIFFTagSet.COMPRESSION_LZW;
public static final int COMPRESSION_JPEG = BaselineTIFFTagSet.COMPRESSION_JPEG;
public static final int COMPRESSION_ZLIB = BaselineTIFFTagSet.COMPRESSION_ZLIB;
public static final int COMPRESSION_PACKBITS = BaselineTIFFTagSet.COMPRESSION_PACKBITS;
public static final int COMPRESSION_DEFLATE = BaselineTIFFTagSet.COMPRESSION_DEFLATE;


protected static final int DEFAULT_DPI = 300;
protected static final int DEFAULT_COLOR = CLR_BLACK_WHITE;
protected static final int DEFAULT_COMPRESSION = COMPRESSION_CCITT_T_6;
protected static final float DEFAULT_COMPRESSION_QUALITY = 1f;

/**
* Convert buffered image to a TIF and save to file
* @param image
* @param tif
* @param dpi
* @param compression
* @param quality
* @throws IOException
*/
protected static void convert(BufferedImage[] image, String tif, int dpi, int compression, float quality) throws IOException {


File file = new File(tif);


if (file.exists()) {
file.delete();
}


RandomAccessFile raf = new RandomAccessFile(file, "rw");
FileChannelImageOutputStream fios = new FileChannelImageOutputStream(raf.getChannel());


convert(image, fios, dpi, compression, quality);

fios.flush();
fios.close();
raf.close();


}

/**
* Convert buffered image to a TIF and save to file
* @param image
* @param File tif
* @param dpi
* @param compression
* @param quality
* @throws IOException
*/
protected static void convert(BufferedImage[] image, File file, int dpi, int compression, float quality) throws IOException {


if (file.exists()) {
file.delete();
}


RandomAccessFile raf = new RandomAccessFile(file, "rw");
FileChannelImageOutputStream fios = new FileChannelImageOutputStream(raf.getChannel());


convert(image, fios, dpi, compression, quality);

fios.flush();
fios.close();
raf.close();


}


/**
* Convert buffered image and return TIF as a byte array
* @param image
* @param dpi
* @param compression
* @param quality
* @return 
* @throws IOException
*/
protected static byte[] convert(BufferedImage[] image, int dpi, int compression, float quality) throws Exception {


ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);


convert(image, ios, dpi, compression, quality);

ios.flush();
ios.close();


return baos.toByteArray();
}

/**
* Convert buffered image and return TIF as a byte array
* @param image
* @param dpi
* @param compression
* @param quality
* @return 
* @throws IOException
*/
protected static byte[] convert(BufferedImage image, int dpi, int compression, float quality) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);


convert(image, ios, dpi, compression, quality);

ios.flush();
ios.close();


return baos.toByteArray();
}

/**
* Convert buffered image to TIF format
* @param image
* @param os
* @param dpi
* @param compression
* @param quality
* @throws IOException
*/
protected static void convert(BufferedImage[] image, Object os, int dpi, int compression, float quality) throws IOException {


TIFFImageWriter writer = new TIFFImageWriter(new TIFFImageWriterSpi());
TIFFImageWriteParam iwp = new TIFFImageWriteParam(writer.getLocale());


writer.setOutput(os);
writer.prepareWriteSequence(null);


iwp.setCompressionMode(TIFFImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionType(getCompression(compression));


if (!isCompressionLossless(compression)) {
if (quality < 0.0F || quality > 1.0F)
quality = DEFAULT_COMPRESSION_QUALITY;
iwp.setCompressionQuality(quality);
}


for (int i = 0; i < image.length; i++) {
ImageTypeSpecifier imageType = ImageTypeSpecifier.createFromRenderedImage(image[i]);
TIFFImageMetadata imageMetadata = (TIFFImageMetadata)writer.getDefaultImageMetadata(imageType, iwp);
imageMetadata = createImageMetadata(imageMetadata, image[i].getHeight(), image[i].getWidth(), dpi, compression, image[i].getType());
writer.writeToSequence(new IIOImage(image[i], null, imageMetadata), iwp);
}

writer.endWriteSequence();
writer.dispose();
}

/**
* Convert buffered image to TIF format
* @param image
* @param os
* @param dpi
* @param compression
* @param quality
* @throws IOException
*/
protected static void convert(BufferedImage image, Object os, int dpi, int compression, float quality) throws IOException {


TIFFImageWriter writer = new TIFFImageWriter(new TIFFImageWriterSpi());
TIFFImageWriteParam iwp = new TIFFImageWriteParam(writer.getLocale());


writer.setOutput(os);
writer.prepareWriteSequence(null);


iwp.setCompressionMode(TIFFImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionType(getCompression(compression));


if (!isCompressionLossless(compression)) {
if (quality < 0.0F || quality > 1.0F)
quality = DEFAULT_COMPRESSION_QUALITY;
iwp.setCompressionQuality(quality);
}


ImageTypeSpecifier imageType = ImageTypeSpecifier.createFromRenderedImage(image);
TIFFImageMetadata imageMetadata = (TIFFImageMetadata)writer.getDefaultImageMetadata(imageType, iwp);
imageMetadata = createImageMetadata(imageMetadata, image.getHeight(), image.getWidth(), dpi, compression, image.getType());
writer.writeToSequence(new IIOImage(image, null, imageMetadata), iwp);

writer.endWriteSequence();
writer.dispose();
}

/**
* Get an appropriate buffered image
* @param color
* @param compression
* @param width
* @param height
* @return
*/
protected static BufferedImage getBufferedImage(int color, int compression, int width, int height) {
BufferedImage image;
if (compression == COMPRESSION_CCITT_RLE ||
compression == COMPRESSION_CCITT_T_4 ||
compression == COMPRESSION_CCITT_T_6 ||
color == CLR_BLACK_WHITE ) {
       image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);
} else if (color == CLR_GRAY_SCALE) {
image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);
} else {
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
}
return image;
}

/**
* Get compression string
* @param compression
* @return
*/
protected static String getCompression(int compression) {
String c = null;
for (int i = 0; i < TIFFImageWriter.compressionTypes.length; i++) {
if (compression == TIFFImageWriter.compressionNumbers[i]) {
c = TIFFImageWriter.compressionTypes[i];
}
}
return c;
}


/**
* Get loss less flag
* @param compression
* @return
*/
protected static boolean isCompressionLossless(int compression) {
boolean lossless = true;
for (int i = 0; i < TIFFImageWriter.compressionTypes.length; i++) {
if (compression == TIFFImageWriter.compressionNumbers[i]) {
lossless = TIFFImageWriter.isCompressionLossless[i];
}
}
return lossless;
}

/**
* Return the image meta data for the new TIF image
* @param imageMetadata
* @return
* @throws IIOInvalidTreeException

*/
protected static TIFFImageMetadata createImageMetadata(TIFFImageMetadata imageMetadata, int height, int width, int dpi, int compression, int type) throws IIOInvalidTreeException {

/*
* Fields are arrays
* Each TIFF field has an associated Count. This means that all fields are actually
* one-dimensional arrays, even though most fields contain only a single value. 
*/
char[] cImageWidth = new char[] {(char)width};
char[] cImageLength = new char[] {(char)height};
char[] cResolutionUnit = new char[] {BaselineTIFFTagSet.RESOLUTION_UNIT_INCH};
long[][] cDpiResolutionX = new long[][] {{(long)dpi, (long)1}, {(long)0, (long)0}};
long[][] cDpiResolutionY = new long[][] {{(long)dpi, (long)1}, {(long)0, (long)0}};
char[] cRowsPerStrip = new char[] {(char)(height)};
// long[] cRowsPerStrip = new long[] {(long)(height)};
char[] cStripOffsets = new char[] {(char)1};
char[] cStripByteCounts = new char[] {(char)1};
long[] cSubFileType = new long[] {0};

/*
*  Get the IFD (Image File Directory) which is the root of all the tags
*  for this image. From here we can get all the tags in the image.
*/
TIFFDirectory ifd = imageMetadata.getRootIFD();

/*
*  Create the necessary TIFF tags that we want to add to the image meta data
*/
BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance();


/*
* Rows and Columns 
*/
TIFFTag tagImageLength = base.getTag(BaselineTIFFTagSet.TAG_IMAGE_LENGTH);
TIFFTag tagImageWidth = base.getTag(BaselineTIFFTagSet.TAG_IMAGE_WIDTH);
TIFFField fieldImageLength = new TIFFField(tagImageLength, TIFFTag.TIFF_SHORT, 1, cImageLength);
TIFFField fieldImageWidth = new TIFFField(tagImageWidth, TIFFTag.TIFF_SHORT, 1, cImageWidth);
ifd.addTIFFField(fieldImageLength);
ifd.addTIFFField(fieldImageWidth);


/*
*  Physical Dimensions
*/
TIFFTag tagResUnit = base.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT);
TIFFTag tagXRes = base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION);
TIFFTag tagYRes = base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION);
TIFFField fieldResUnit = new TIFFField(tagResUnit, TIFFTag.TIFF_SHORT, 1, cResolutionUnit);
TIFFField fieldXRes = new TIFFField(tagXRes, TIFFTag.TIFF_RATIONAL, 1, cDpiResolutionX);
TIFFField fieldYRes = new TIFFField(tagYRes, TIFFTag.TIFF_RATIONAL, 1, cDpiResolutionY);
ifd.addTIFFField(fieldResUnit);
ifd.addTIFFField(fieldXRes);
ifd.addTIFFField(fieldYRes);

/*
* Location of the Data
*/
TIFFTag tagRowsPerStrip = base.getTag(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP);
TIFFTag tagStripOffSets = base.getTag(BaselineTIFFTagSet.TAG_STRIP_OFFSETS);
TIFFTag tagStripByteCounts = base.getTag(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS);
TIFFField fieldRowsPerStrip = new TIFFField(tagRowsPerStrip, TIFFTag.TIFF_SHORT, 1, cRowsPerStrip);
TIFFField fieldStripOffsets = new TIFFField(tagStripOffSets, TIFFTag.TIFF_SHORT, 1, cStripOffsets);
TIFFField fieldStripByteCounts = new TIFFField(tagStripByteCounts, TIFFTag.TIFF_SHORT, 1, cStripByteCounts);
ifd.addTIFFField(fieldRowsPerStrip);
ifd.addTIFFField(fieldStripOffsets);
ifd.addTIFFField(fieldStripByteCounts);

TIFFTag tagSubFileType = base.getTag(BaselineTIFFTagSet.TAG_NEW_SUBFILE_TYPE);
TIFFTag tagBitsPerSample = base.getTag(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
TIFFField fieldSubFileType = new TIFFField(tagSubFileType, TIFFTag.TIFF_LONG, 1, cSubFileType);
TIFFField fieldBitsPerSample = new TIFFField(tagBitsPerSample, 1);
ifd.addTIFFField(fieldSubFileType);
ifd.addTIFFField(fieldBitsPerSample);

return imageMetadata;


}


}