in src/main/java/org/apache/commons/imaging/formats/tiff/TiffImageParser.java [248:398]
protected BufferedImage getBufferedImage(final TiffDirectory directory,
final ByteOrder byteOrder, final TiffImagingParameters params)
throws ImagingException, IOException {
final short compressionFieldValue;
if (directory.findField(TiffTagConstants.TIFF_TAG_COMPRESSION) != null) {
compressionFieldValue = directory.getFieldValue(TiffTagConstants.TIFF_TAG_COMPRESSION);
} else {
compressionFieldValue = TIFF_COMPRESSION_UNCOMPRESSED_1;
}
final int compression = 0xffff & compressionFieldValue;
final int width = directory.getSingleFieldValue(TiffTagConstants.TIFF_TAG_IMAGE_WIDTH);
final int height = directory.getSingleFieldValue(TiffTagConstants.TIFF_TAG_IMAGE_LENGTH);
final Rectangle subImage = checkForSubImage(params);
if (subImage != null) {
// Check for valid subimage specification. The following checks
// are consistent with BufferedImage.getSubimage()
if (subImage.width <= 0) {
throw new ImagingException("Negative or zero subimage width.");
}
if (subImage.height <= 0) {
throw new ImagingException("Negative or zero subimage height.");
}
if (subImage.x < 0 || subImage.x >= width) {
throw new ImagingException("Subimage x is outside raster.");
}
if (subImage.x + subImage.width > width) {
throw new ImagingException("Subimage (x+width) is outside raster.");
}
if (subImage.y < 0 || subImage.y >= height) {
throw new ImagingException("Subimage y is outside raster.");
}
if (subImage.y + subImage.height > height) {
throw new ImagingException("Subimage (y+height) is outside raster.");
}
}
int samplesPerPixel = 1;
final TiffField samplesPerPixelField = directory.findField(
TiffTagConstants.TIFF_TAG_SAMPLES_PER_PIXEL);
if (samplesPerPixelField != null) {
samplesPerPixel = samplesPerPixelField.getIntValue();
}
int[] bitsPerSample = { 1 };
int bitsPerPixel = samplesPerPixel;
final TiffField bitsPerSampleField = directory.findField(
TiffTagConstants.TIFF_TAG_BITS_PER_SAMPLE);
if (bitsPerSampleField != null) {
bitsPerSample = bitsPerSampleField.getIntArrayValue();
bitsPerPixel = bitsPerSampleField.getIntValueOrArraySum();
}
// int bitsPerPixel = getTagAsValueOrArraySum(entries,
// TIFF_TAG_BITS_PER_SAMPLE);
int predictor = -1;
{
// dumpOptionalNumberTag(entries, TIFF_TAG_FILL_ORDER);
// dumpOptionalNumberTag(entries, TIFF_TAG_FREE_BYTE_COUNTS);
// dumpOptionalNumberTag(entries, TIFF_TAG_FREE_OFFSETS);
// dumpOptionalNumberTag(entries, TIFF_TAG_ORIENTATION);
// dumpOptionalNumberTag(entries, TIFF_TAG_PLANAR_CONFIGURATION);
final TiffField predictorField = directory.findField(
TiffTagConstants.TIFF_TAG_PREDICTOR);
if (null != predictorField) {
predictor = predictorField.getIntValueOrArraySum();
}
}
if (samplesPerPixel != bitsPerSample.length) {
throw new ImagingException("Tiff: samplesPerPixel ("
+ samplesPerPixel + ")!=fBitsPerSample.length ("
+ bitsPerSample.length + ")");
}
final int photometricInterpretation = 0xffff & directory.getFieldValue(
TiffTagConstants.TIFF_TAG_PHOTOMETRIC_INTERPRETATION);
boolean hasAlpha = false;
boolean isAlphaPremultiplied = false;
if (photometricInterpretation == TiffTagConstants.PHOTOMETRIC_INTERPRETATION_VALUE_RGB
&& samplesPerPixel == 4) {
final TiffField extraSamplesField
= directory.findField(TiffTagConstants.TIFF_TAG_EXTRA_SAMPLES);
if (extraSamplesField == null) {
// this state is not defined in the TIFF specification
// and so this code will interpret it as meaning that the
// proper handling would be ARGB.
hasAlpha = true;
isAlphaPremultiplied = false;
} else {
final int extraSamplesValue = extraSamplesField.getIntValue();
switch (extraSamplesValue) {
case TiffTagConstants.EXTRA_SAMPLE_UNASSOCIATED_ALPHA:
hasAlpha = true;
isAlphaPremultiplied = false;
break;
case TiffTagConstants.EXTRA_SAMPLE_ASSOCIATED_ALPHA:
hasAlpha = true;
isAlphaPremultiplied = true;
break;
case 0:
default:
hasAlpha = false;
isAlphaPremultiplied = false;
break;
}
}
}
PhotometricInterpreter photometricInterpreter = params.getCustomPhotometricInterpreter();
if (photometricInterpreter == null) {
photometricInterpreter = getPhotometricInterpreter(
directory, photometricInterpretation, bitsPerPixel,
bitsPerSample, predictor, samplesPerPixel, width, height);
}
// Obtain the planar configuration
final TiffField pcField = directory.findField(
TiffTagConstants.TIFF_TAG_PLANAR_CONFIGURATION);
final TiffPlanarConfiguration planarConfiguration
= pcField == null
? TiffPlanarConfiguration.CHUNKY
: TiffPlanarConfiguration.lenientValueOf(pcField.getIntValue());
if (planarConfiguration == TiffPlanarConfiguration.PLANAR) {
// currently, we support the non-interleaved (non-chunky)
// option only in the case of a 24-bit RBG photometric interpreter
// and for strips (not for tiles).
if (photometricInterpretation
!= TiffTagConstants.PHOTOMETRIC_INTERPRETATION_VALUE_RGB
|| bitsPerPixel != 24) {
throw new ImagingException("For planar configuration 2, only 24 bit RGB is currently supported");
}
if (null == directory.findField(TiffTagConstants.TIFF_TAG_STRIP_OFFSETS)) {
throw new ImagingException("For planar configuration 2, only strips-organization is supported");
}
}
final TiffImageData imageData = directory.getTiffImageData();
final ImageDataReader dataReader = imageData.getDataReader(directory,
photometricInterpreter, bitsPerPixel, bitsPerSample, predictor,
samplesPerPixel, width, height, compression,
planarConfiguration, byteOrder);
final ImageBuilder iBuilder = dataReader.readImageData(
subImage, hasAlpha, isAlphaPremultiplied);
return iBuilder.getBufferedImage();
}