blob: c5f47796b5e64b795a8c61ff2e92b846905f1510 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* $Id$ */
package org.apache.xmlgraphics.image.writer.internal;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.xmlgraphics.image.codec.tiff.TIFFEncodeParam;
import org.apache.xmlgraphics.image.codec.tiff.TIFFField;
import org.apache.xmlgraphics.image.codec.tiff.TIFFImageDecoder;
import org.apache.xmlgraphics.image.codec.tiff.TIFFImageEncoder;
import org.apache.xmlgraphics.image.writer.AbstractImageWriter;
import org.apache.xmlgraphics.image.writer.ImageWriter;
import org.apache.xmlgraphics.image.writer.ImageWriterParams;
import org.apache.xmlgraphics.image.writer.MultiImageWriter;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
/**
* ImageWriter implementation that uses the internal TIFF codec to
* write TIFF files.
*
* @version $Id$
*/
public class TIFFImageWriter extends AbstractImageWriter {
/**
* @see ImageWriter#writeImage(java.awt.image.RenderedImage, java.io.OutputStream)
*/
public void writeImage(RenderedImage image, OutputStream out)
throws IOException {
writeImage(image, out, null);
}
/**
* @see ImageWriter#writeImage(java.awt.image.RenderedImage, java.io.OutputStream, ImageWriterParams)
*/
public void writeImage(RenderedImage image, OutputStream out,
ImageWriterParams params) throws IOException {
TIFFEncodeParam encodeParams = createTIFFEncodeParams(params);
updateParams(encodeParams, params, image);
TIFFImageEncoder encoder = new TIFFImageEncoder(out, encodeParams);
encoder.encode(image);
}
/**
* This method updates the encode parameters based on the image to be encoded. One thing done
* here is to initialize the JPEG encoding parameters if JPEG compression is selected.
* @param encodeParams the TIFF encoding parameters
* @param image the image to be encoded
*/
private void updateParams(TIFFEncodeParam encodeParams, ImageWriterParams params,
RenderedImage image) {
if (encodeParams.getCompression() == TIFFEncodeParam.COMPRESSION_JPEG_TTN2) {
ColorModel cm = image.getColorModel();
int imageType = cm.getColorSpace().getType();
int colorID;
//The following translation table is taken from the Javadoc for JPEGEncodeParam.
switch (imageType) {
case ColorSpace.TYPE_GRAY:
colorID = JPEGEncodeParam.COLOR_ID_GRAY;
break;
case ColorSpace.TYPE_RGB:
if (cm.hasAlpha()) {
colorID = JPEGEncodeParam.COLOR_ID_YCbCrA;
} else {
colorID = JPEGEncodeParam.COLOR_ID_YCbCr;
}
break;
case ColorSpace.TYPE_YCbCr:
if (cm.hasAlpha()) {
colorID = JPEGEncodeParam.COLOR_ID_YCbCrA;
} else {
colorID = JPEGEncodeParam.COLOR_ID_YCbCr;
}
break;
case ColorSpace.TYPE_CMYK:
colorID = JPEGEncodeParam.COLOR_ID_CMYK;
break;
default:
//TODO Don't know how to determine whether image is PYCC or not
//(see JPEGEncodeParam)
colorID = JPEGEncodeParam.COLOR_ID_UNKNOWN;
}
JPEGEncodeParam jpegParam = JPEGCodec.getDefaultJPEGEncodeParam(
image.getData(), colorID);
if (params.getJPEGQuality() != null || params.getJPEGForceBaseline() != null) {
float qual = (params.getJPEGQuality() != null
? params.getJPEGQuality().floatValue() : 0.75f);
boolean force = (params.getJPEGForceBaseline() != null
? params.getJPEGForceBaseline().booleanValue() : false);
jpegParam.setQuality(qual, force);
}
encodeParams.setJPEGEncodeParam(jpegParam);
}
}
private TIFFEncodeParam createTIFFEncodeParams(ImageWriterParams params) {
TIFFEncodeParam encodeParams = new TIFFEncodeParam();
if (params == null) {
encodeParams.setCompression(TIFFEncodeParam.COMPRESSION_NONE);
} else {
if (params.getCompressionMethod() == null) {
//PackBits as default
encodeParams.setCompression(TIFFEncodeParam.COMPRESSION_PACKBITS);
} else if ("PackBits".equalsIgnoreCase(params.getCompressionMethod())) {
encodeParams.setCompression(TIFFEncodeParam.COMPRESSION_PACKBITS);
} else if ("NONE".equalsIgnoreCase(params.getCompressionMethod())) {
encodeParams.setCompression(TIFFEncodeParam.COMPRESSION_NONE);
} else if ("JPEG".equalsIgnoreCase(params.getCompressionMethod())) {
encodeParams.setCompression(TIFFEncodeParam.COMPRESSION_JPEG_TTN2);
} else if ("Deflate".equalsIgnoreCase(params.getCompressionMethod())) {
encodeParams.setCompression(TIFFEncodeParam.COMPRESSION_DEFLATE);
} else {
throw new UnsupportedOperationException("Compression method not supported: "
+ params.getCompressionMethod());
}
if (params.getResolution() != null) {
// Set target resolution
float pixSzMM = 25.4f / params.getResolution().floatValue();
// num Pixs in 100 Meters
int numPix = (int)(((1000 * 100) / pixSzMM) + 0.5);
int denom = 100 * 100; // Centimeters per 100 Meters;
long [] rational = {numPix, denom};
TIFFField [] fields = {
new TIFFField(TIFFImageDecoder.TIFF_RESOLUTION_UNIT,
TIFFField.TIFF_SHORT, 1,
new char[] {(char)3}),
new TIFFField(TIFFImageDecoder.TIFF_X_RESOLUTION,
TIFFField.TIFF_RATIONAL, 1,
new long[][] {rational}),
new TIFFField(TIFFImageDecoder.TIFF_Y_RESOLUTION,
TIFFField.TIFF_RATIONAL, 1,
new long[][] {rational})
};
encodeParams.setExtraFields(fields);
}
}
return encodeParams;
}
/**
* @see ImageWriter#getMIMEType()
*/
public String getMIMEType() {
return "image/tiff";
}
/**
* @see org.apache.xmlgraphics.image.writer.ImageWriter#createMultiImageWriter(
* java.io.OutputStream)
*/
public MultiImageWriter createMultiImageWriter(OutputStream out) throws IOException {
return new TIFFMultiImageWriter(out);
}
/** @see org.apache.xmlgraphics.image.writer.ImageWriter#supportsMultiImageWriter() */
public boolean supportsMultiImageWriter() {
return true;
}
private class TIFFMultiImageWriter implements MultiImageWriter {
private OutputStream out;
private TIFFEncodeParam encodeParams;
private TIFFImageEncoder encoder;
private Object context;
public TIFFMultiImageWriter(OutputStream out) throws IOException {
this.out = out;
}
public void writeImage(RenderedImage image, ImageWriterParams params) throws IOException {
if (encoder == null) {
encodeParams = createTIFFEncodeParams(params);
updateParams(encodeParams, params, image);
encoder = new TIFFImageEncoder(out, encodeParams);
}
context = encoder.encodeMultiple(context, image);
}
public void close() throws IOException {
if (encoder != null) {
encoder.finishMultiple(context);
}
encoder = null;
encodeParams = null;
out.flush();
}
}
}