xtiffimageencoder.java
来自「OpenMap是一个基于JavaBeansTM的开发工具包。利用OpenMap你」· Java 代码 · 共 816 行 · 第 1/2 页
JAVA
816 行
package org.libtiff.jai.codecimpl;/* * XTIFF: eXtensible TIFF libraries for JAI. * * The contents of this file are subject to the JAVA ADVANCED IMAGING * SAMPLE INPUT-OUTPUT CODECS AND WIDGET HANDLING SOURCE CODE License * Version 1.0 (the "License"); You may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.sun.com/software/imaging/JAI/index.html * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is JAVA ADVANCED IMAGING SAMPLE INPUT-OUTPUT CODECS * AND WIDGET HANDLING SOURCE CODE. * The Initial Developer of the Original Code is: Sun Microsystems, Inc.. * Portions created by: Niles Ritter * are Copyright (C): Niles Ritter, GeoTIFF.org, 1999,2000. * All Rights Reserved. * Contributor(s): Niles Ritter */import java.awt.Rectangle;import java.awt.color.ColorSpace;import java.awt.image.ColorModel;import java.awt.image.DataBuffer;import java.awt.image.IndexColorModel;import java.awt.image.RenderedImage;import java.awt.image.SampleModel;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import java.util.Vector;import org.libtiff.jai.codec.XTIFF;import org.libtiff.jai.codec.XTIFFDirectory;import org.libtiff.jai.codec.XTIFFEncodeParam;import org.libtiff.jai.codec.XTIFFField;import org.libtiff.jai.codec.XTIFFTileCodec;import org.libtiff.jai.util.JaiI18N;import com.sun.media.jai.codec.ImageEncodeParam;import com.sun.media.jai.codec.TIFFEncodeParam;import com.sun.media.jai.codec.TIFFField;import com.sun.media.jai.codecimpl.TIFFImageDecoder;import com.sun.media.jai.codecimpl.TIFFImageEncoder;/** * A baseline TIFF writer. The writer outputs TIFF images in either Bilevel, * Greyscale, Palette color or Full Color modes. * */public class XTIFFImageEncoder extends TIFFImageEncoder { long firstIFDOffset = 0; XTIFFDirectory directory; XTIFFEncodeParam tparam; int width; int length; SampleModel sampleModel; int numBands; int sampleSize[]; int dataType; boolean dataTypeIsShort; ColorModel colorModel; int numTiles; int compression; boolean isTiled; long tileLength; long tileWidth; byte[] bpixels = null; long stripTileByteCounts[]; long stripTileOffsets[]; long currentOffset = 0; // Image Types public static final int XTIFF_BILEVEL_WHITE_IS_ZERO = 0; public static final int XTIFF_BILEVEL_BLACK_IS_ZERO = 1; public static final int XTIFF_PALETTE = 2; public static final int XTIFF_FULLCOLOR = 3; public static final int XTIFF_GREYSCALE = 4; /** * Standard constructor */ public XTIFFImageEncoder(OutputStream output, ImageEncodeParam param) { super(output, param); if (this.param == null || !(param instanceof XTIFFEncodeParam)) { this.param = new XTIFFEncodeParam((TIFFEncodeParam) param); } tparam = (XTIFFEncodeParam) this.param; directory = tparam.getDirectory(); } private File createTemp() throws IOException { String tmpdir = System.getProperty("tiff.io.tmpdir"); File file = null; if (tmpdir != null) file = File.createTempFile("libtiff.jai.", ".dat", new File(tmpdir)); else file = File.createTempFile("libtiff.jai.", ".dat"); file.deleteOnExit(); return file; } private void copyImageData(File tmp, OutputStream out, int total) throws IOException { int bufsize = 1024; int bytes = 0; byte[] buf = new byte[bufsize]; FileInputStream in = new FileInputStream(tmp); do { bytes = in.read(buf); out.write(buf, 0, bytes); total -= bytes; } while (total > 0); in.close(); } /** * Encodes a RenderedImage and writes the output to the OutputStream * associated with this ImageEncoder. */ public void encode(RenderedImage im) throws IOException { // Set comp into directory compression = tparam.getCompression(); // see if tiled isTiled = ((TIFFEncodeParam) param).getWriteTiled(); // Setup Directory fields. getImageFields(im); if (compression == XTIFF.COMPRESSION_NONE) { computeIFDOffset(); writeFileHeader(firstIFDOffset); currentOffset = 8; writeImageData(im, output); writeDirectory(directory.getFields(), 0); } else { // We have to write compressed data out to // a temp file to compute the IFD offset. // The only alternative is to compress the // data twice, which is just about as bad. currentOffset = 8; File tmp = null; try { tmp = createTemp(); OutputStream tmpOut = new FileOutputStream(tmp); int total = writeImageData(im, tmpOut); tmpOut.close(); writeFileHeader(currentOffset + currentOffset % 2); copyImageData(tmp, output, total); writeDirectory(directory.getFields(), 0); } finally { if (tmp != null) tmp.delete(); } } } /** * Precomputes the IFD Offset for uncompressed data. */ private void computeIFDOffset() { long bytesPerRow = (long) Math.ceil((sampleSize[0] / 8.0) * tileWidth * numBands); long bytesPerTile = bytesPerRow * tileLength; long lastTile = bytesPerTile; if (!isTiled) { // Last strip may have lesser rows long lastStripRows = length - (tileLength * (numTiles - 1)); lastTile = lastStripRows * bytesPerRow; } long totalBytesOfData = bytesPerTile * (numTiles - 1) + lastTile; // File header always occupies 8 bytes and we write the image data // after that. firstIFDOffset = 8 + totalBytesOfData; // Must begin on a word boundary if ((firstIFDOffset % 2) != 0) { firstIFDOffset++; } } private void writeFileHeader(long firstIFDOffset) throws IOException { // 8 byte image file header // Byte order used within the file - Big Endian output.write('M'); output.write('M'); // Magic value output.write(0); output.write(42); // Offset in bytes of the first IFD, must begin on a word boundary writeLong(firstIFDOffset); } // method for adding tags that haven't been set by user private void addIfAbsent(int tag, int type, int count, Object obj) { if (directory.getField(tag) == null) directory.addField(tag, type, count, obj); } private void getImageFields(RenderedImage im) /* throws IOException */{ width = im.getWidth(); length = im.getHeight(); // TIFF calls it length sampleModel = im.getSampleModel(); numBands = sampleModel.getNumBands(); sampleSize = sampleModel.getSampleSize(); dataType = sampleModel.getDataType(); if (dataType != DataBuffer.TYPE_BYTE && dataType != DataBuffer.TYPE_SHORT && dataType != DataBuffer.TYPE_USHORT) { // Support only byte and (unsigned) short. throw new Error(JaiI18N.getString("TIFFImageEncoder0")); } dataTypeIsShort = dataType == DataBuffer.TYPE_SHORT || dataType == DataBuffer.TYPE_USHORT; colorModel = im.getColorModel(); if (colorModel != null && colorModel instanceof IndexColorModel && dataTypeIsShort) { // Don't support (unsigned) short palette-color images. throw new Error(JaiI18N.getString("TIFFImageEncoder2")); } IndexColorModel icm = null; int sizeOfColormap = 0; char colormap[] = null; // Basic fields - have to be in increasing numerical order BILEVEL // ImageWidth 256 // ImageLength 257 // BitsPerSample 258 // Compression 259 // PhotoMetricInterpretation 262 // StripOffsets 273 // RowsPerStrip 278 // StripByteCounts 279 // XResolution 282 // YResolution 283 // ResolutionUnit 296 int photometricInterpretation = XTIFF.PHOTOMETRIC_RGB; int imageType = XTIFF_FULLCOLOR; // IMAGE TYPES POSSIBLE // Bilevel // BitsPerSample = 1 // Compression = 1, 2, or 32773 // PhotometricInterpretation either 0 or 1 // Greyscale // BitsPerSample = 4 or 8 // Compression = 1, 32773 // PhotometricInterpretation either 0 or 1 // Palette // ColorMap 320 // BitsPerSample = 4 or 8 // PhotometrciInterpretation = 3 // Full color // BitsPerSample = 8, 8, 8 // SamplesPerPixel = 3 or more 277 // Compression = 1, 32773 // PhotometricInterpretation = 2 if (colorModel instanceof IndexColorModel) { icm = (IndexColorModel) colorModel; int mapSize = icm.getMapSize(); if (sampleSize[0] == 1) { // Bilevel image if (mapSize != 2) { throw new IllegalArgumentException(JaiI18N.getString("TIFFImageEncoder1")); } byte r[] = new byte[mapSize]; icm.getReds(r); byte g[] = new byte[mapSize]; icm.getGreens(g); byte b[] = new byte[mapSize]; icm.getBlues(b); if ((r[0] & 0xff) == 0 && (r[1] & 0xff) == 255 && (g[0] & 0xff) == 0 && (g[1] & 0xff) == 255 && (b[0] & 0xff) == 0 && (b[1] & 0xff) == 255) { imageType = XTIFF_BILEVEL_BLACK_IS_ZERO; } else if ((r[0] & 0xff) == 255 && (r[1] & 0xff) == 0 && (g[0] & 0xff) == 255 && (g[1] & 0xff) == 0 && (b[0] & 0xff) == 255 && (b[1] & 0xff) == 0) { imageType = XTIFF_BILEVEL_WHITE_IS_ZERO; } else { imageType = XTIFF_PALETTE; } } else { // Palette color image. imageType = XTIFF_PALETTE; } } else { // If it is not an IndexColorModel, it can either be a greyscale // image or a full color image if ((colorModel == null || colorModel.getColorSpace().getType() == ColorSpace.TYPE_GRAY) && numBands == 1) { // Greyscale image imageType = XTIFF_GREYSCALE; } else { // Full color image imageType = XTIFF_FULLCOLOR; } } switch (imageType) { case XTIFF_BILEVEL_WHITE_IS_ZERO: photometricInterpretation = XTIFF.PHOTOMETRIC_WHITE_IS_ZERO; break; case XTIFF_BILEVEL_BLACK_IS_ZERO: photometricInterpretation = XTIFF.PHOTOMETRIC_BLACK_IS_ZERO; break; case XTIFF_GREYSCALE: // Since the CS_GRAY colorspace is always of type black_is_zero photometricInterpretation = XTIFF.PHOTOMETRIC_BLACK_IS_ZERO; break; case XTIFF_PALETTE: photometricInterpretation = XTIFF.PHOTOMETRIC_PALETTE; icm = (IndexColorModel) colorModel; sizeOfColormap = icm.getMapSize(); byte r[] = new byte[sizeOfColormap]; icm.getReds(r); byte g[] = new byte[sizeOfColormap]; icm.getGreens(g); byte b[] = new byte[sizeOfColormap]; icm.getBlues(b); int redIndex = 0, greenIndex = sizeOfColormap; int blueIndex = 2 * sizeOfColormap; colormap = new char[sizeOfColormap * 3]; for (int i = 0; i < sizeOfColormap; i++) { colormap[redIndex++] = (char) (r[i] << 8); colormap[greenIndex++] = (char) (g[i] << 8); colormap[blueIndex++] = (char) (b[i] << 8); } sizeOfColormap *= 3; // Since we will be writing the colormap field. break; case XTIFF_FULLCOLOR: photometricInterpretation = XTIFF.PHOTOMETRIC_RGB; break; } if (isTiled) { tileWidth = 16L; tileLength = 16L; XTIFFField fld = directory.getField(XTIFF.TIFFTAG_TILE_WIDTH); if (fld != null) tileWidth = (int) fld.getAsLong(0); fld = directory.getField(XTIFF.TIFFTAG_TILE_LENGTH); if (fld != null) tileLength = (int) fld.getAsLong(0); } else { // Default strip is 8 rows. tileLength = 8L; // tileWidth of strip is width tileWidth = width; XTIFFField fld = directory.getField(TIFFImageDecoder.TIFF_ROWS_PER_STRIP); if (fld != null) tileLength = fld.getAsLong(0); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?