DOWNLOAD
package Pixels; import Utils.ByteBufferPool;import java.io.IOException;import java.io.OutputStream;import java.util.Arrays; public class TiffWriter{ static final int HEADER_SIZE = 0x8c; public static void writeUncompressedImage( OutputStream outStream, int[] inputPixels, int width, int height ) throws IOException { if (width <= 0 || height <= 0) throw new IllegalArgumentException("Invalid dimensions " + width + " x " + height); int bytesPerPixel = 3; int outDataSize = width * height * bytesPerPixel; byte[] outputData = ByteBufferPool.acquireAsIs(HEADER_SIZE + outDataSize); try { writeUncompressedTiffHeader(outputData, width, height); writeUncompressedPixelData(outputData, HEADER_SIZE, inputPixels, width, height); outStream.write(outputData, 0, HEADER_SIZE + outDataSize); } finally { ByteBufferPool.release(outputData); } } private static void writeUncompressedTiffHeader( byte[] b, int width, int height ) { Arrays.fill(b, 0, HEADER_SIZE, (byte)0); int p = 0; // Tiff Type b[p++] = 'I'; b[p++] = 'I'; b[p++] = 0x2a; // First IFD offset (immediately after this field) p = 4; b[p++] = 8; // Number of tags = 10 p = 8; b[p++] = 0xa; p++; // 254: New Subfile Type = 0 b[p] = (byte)0xfe; b[p+2] = 4; b[p+4] = 1; p += 12; // 256: Width b[p+1] = 1; b[p+2] = 4; b[p+4] = 1; p += 8; b[p++] = (byte)width; b[p++] = (byte)(width >> 8); b[p++] = (byte)(width >> 16); b[p++] = (byte)(width >> 24); // 257: Height b[p] = 1; b[p+1] = 1; b[p+2] = 4; b[p+4] = 1; p += 8; b[p++] = (byte)height; b[p++] = (byte)(height >> 8); b[p++] = (byte)(height >> 16); b[p++] = (byte)(height >> 24); // 258: Bits Per Sample = 8,8,8: points to 0x86, 4 bytes after the last tag b[p] = 2; b[p+1] = 1; b[p+2] = 3; b[p+4] = 3; b[p+8] = (byte)(HEADER_SIZE - 6); p += 12; // 259: Compression = uncompressed b[p] = 3; b[p+1] = 1; b[p+2] = 3; b[p+4] = 1; b[p+8] = 1; p += 12; // 262: Photometric Interpretation = 2 (RGB) b[p] = 6; b[p+1] = 1; b[p+2] = 3; b[p+4] = 1; b[p+8] = 2; p += 12; // 273: Strip Offsets (aka image offset) b[p] = 17; b[p+1] = 1; b[p+2] = 4; b[p+4] = 1; b[p+8] = (byte)HEADER_SIZE; p += 12; // 277: Samples Per Pixel = 3 b[p] = 21; b[p+1] = 1; b[p+2] = 3; b[p+4] = 1; b[p+8] = 3; p += 12; // 278: Rows Per Strip = Height b[p] = 22; b[p+1] = 1; b[p+2] = 4; b[p+4] = 1; p += 8; b[p++] = (byte)height; b[p++] = (byte)(height >> 8); b[p++] = (byte)(height >> 16); b[p++] = (byte)(height >> 24); // 279: Strip Byte Counts = image data size, ie. width*height*3 int imageSize = width * height * 3; b[p] = 23; b[p+1] = 1; b[p+2] = 4; b[p+4] = 1; p += 8; b[p++] = (byte)imageSize; b[p++] = (byte)(imageSize >> 8); b[p++] = (byte)(imageSize >> 16); b[p++] = (byte)(imageSize >> 24); // 8,8,8 referenced by the "Bits Per Sample" tag b[p+4] = 8; b[p+6] = 8; b[p+8] = 8; } private static void writeUncompressedPixelData( byte[] outputBuffer, int offset, int[] inputPixels, int width, int height ) { int area = width * height; for (int in = 0, out = offset; in < area; in++, out += 3) { int rgb = inputPixels[in]; outputBuffer[out] = (byte)(rgb >> 16); outputBuffer[out+1] = (byte)(rgb >> 8); outputBuffer[out+2] = (byte)rgb; } }}