< prev index next >
src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java
Print this page
@@ -154,10 +154,15 @@
* {@code true} if the image is encoded using separate planes.
*/
protected boolean planar;
/**
+ * The planar band to decode; ignored for chunky (interleaved) images.
+ */
+ protected int planarBand = 0;
+
+ /**
* The value of the {@code SamplesPerPixel} tag.
*/
protected int samplesPerPixel;
/**
@@ -444,28 +449,23 @@
/**
* Create a {@code ComponentColorModel} for use in creating
* an {@code ImageTypeSpecifier}.
*/
- // This code was copied from javax.imageio.ImageTypeSpecifier.
+ // This code was inspired by the method of the same name in
+ // javax.imageio.ImageTypeSpecifier
static ColorModel createComponentCM(ColorSpace colorSpace,
int numBands,
+ int[] bitsPerSample,
int dataType,
boolean hasAlpha,
boolean isAlphaPremultiplied) {
int transparency =
hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;
- int[] numBits = new int[numBands];
- int bits = DataBuffer.getDataTypeSize(dataType);
-
- for (int i = 0; i < numBands; i++) {
- numBits[i] = bits;
- }
-
return new ComponentColorModel(colorSpace,
- numBits,
+ bitsPerSample,
hasAlpha,
isAlphaPremultiplied,
transparency,
dataType);
}
@@ -579,18 +579,19 @@
/**
* Determines whether the {@code DataBuffer} is filled without
* any interspersed padding bits.
*/
- private static boolean isDataBufferBitContiguous(SampleModel sm)
+ private static boolean isDataBufferBitContiguous(SampleModel sm,
+ int[] bitsPerSample)
throws IIOException {
int dataTypeSize = getDataTypeSize(sm.getDataType());
if(sm instanceof ComponentSampleModel) {
int numBands = sm.getNumBands();
for(int i = 0; i < numBands; i++) {
- if(sm.getSampleSize(i) != dataTypeSize) {
+ if(bitsPerSample[i] != dataTypeSize) {
// Sample does not fill data element.
return false;
}
}
} else if(sm instanceof MultiPixelPackedSampleModel) {
@@ -680,20 +681,20 @@
/**
* Reformats bit-discontiguous data into the {@code DataBuffer}
* of the supplied {@code WritableRaster}.
*/
private static void reformatDiscontiguousData(byte[] buf,
+ int[] bitsPerSample,
int stride,
int w,
int h,
WritableRaster raster)
throws IOException {
// Get SampleModel info.
SampleModel sm = raster.getSampleModel();
int numBands = sm.getNumBands();
- int[] sampleSize = sm.getSampleSize();
// Initialize input stream.
ByteArrayInputStream is = new ByteArrayInputStream(buf);
ImageInputStream iis = new MemoryCacheImageInputStream(is);
@@ -703,11 +704,11 @@
for(int j = 0; j < h; j++, y++) {
iis.seek(iisPosition);
int x = raster.getMinX();
for(int i = 0; i < w; i++, x++) {
for(int b = 0; b < numBands; b++) {
- long bits = iis.readBits(sampleSize[b]);
+ long bits = iis.readBits(bitsPerSample[b]);
raster.setSample(x, y, b, (int)bits);
}
}
iisPosition += stride;
}
@@ -804,12 +805,19 @@
redLut[i] = (byte)((colorMap[i]*255)/65535);
greenLut[i] = (byte)((colorMap[mapSize + i]*255)/65535);
blueLut[i] = (byte)((colorMap[2*mapSize + i]*255)/65535);
}
- int dataType = bitsPerSample[0] == 8 ?
- DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT;
+ int dataType;
+ if (bitsPerSample[0] <= 8) {
+ dataType = DataBuffer.TYPE_BYTE;
+ } else if (sampleFormat[0] ==
+ BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) {
+ dataType = DataBuffer.TYPE_SHORT;
+ } else {
+ dataType = DataBuffer.TYPE_USHORT;
+ }
return ImageTypeSpecifier.createIndexed(redLut,
greenLut,
blueLut,
alphaLut,
bitsPerSample[0],
@@ -1080,17 +1088,19 @@
alphaPremultiplied = true;
}
cm = createComponentCM(cs,
samplesPerPixel,
+ bitsPerSample,
dataType,
hasAlpha,
alphaPremultiplied);
} else {
ColorSpace cs = new BogusColorSpace(samplesPerPixel);
cm = createComponentCM(cs,
samplesPerPixel,
+ bitsPerSample,
dataType,
false, // hasAlpha
false); // alphaPremultiplied
}
return new ImageTypeSpecifier(cm, sm);
@@ -1117,21 +1127,27 @@
boolean isSigned =
(sampleFormat[0] ==
BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER);
// Grayscale
- if(samplesPerPixel == 1) {
- int dataType =
- getDataTypeFromNumBits(maxBitsPerSample, isSigned);
+ if(samplesPerPixel == 1 &&
+ (bitsPerSample[0] == 1 || bitsPerSample[0] == 2 ||
+ bitsPerSample[0] == 4 || bitsPerSample[0] == 8 ||
+ bitsPerSample[0] == 16)) {
+ int dataType = getDataTypeFromNumBits(maxBitsPerSample, isSigned);
- return ImageTypeSpecifier.createGrayscale(maxBitsPerSample,
+ return ImageTypeSpecifier.createGrayscale(bitsPerSample[0],
dataType,
isSigned);
}
// Gray-alpha
- if (samplesPerPixel == 2) {
+ if (samplesPerPixel == 2 &&
+ bitsPerSample[0] == bitsPerSample[1] &&
+ (bitsPerSample[0] == 1 || bitsPerSample[0] == 2 ||
+ bitsPerSample[0] == 4 || bitsPerSample[0] == 8 ||
+ bitsPerSample[0] == 16)) {
boolean alphaPremultiplied = false;
if (extraSamples != null &&
extraSamples[0] ==
BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
alphaPremultiplied = true;
@@ -1145,10 +1161,17 @@
false,
alphaPremultiplied);
}
if (samplesPerPixel == 3 || samplesPerPixel == 4) {
+ int dataType = getDataTypeFromNumBits(maxBitsPerSample, isSigned);
+ int dataTypeSize;
+ try {
+ dataTypeSize = getDataTypeSize(dataType);
+ } catch (IIOException ignored) {
+ dataTypeSize = maxBitsPerSample;
+ }
if(totalBits <= 32 && !isSigned) {
// Packed RGB or RGBA
int redMask = createMask(bitsPerSample, 0);
int greenMask = createMask(bitsPerSample, 1);
int blueMask = createMask(bitsPerSample, 2);
@@ -1167,25 +1190,28 @@
greenMask,
blueMask,
alphaMask,
transferType,
alphaPremultiplied);
- } else if(samplesPerPixel == 3) {
+ } else if(samplesPerPixel == 3 &&
+ dataTypeSize == bitsPerSample[0] &&
+ bitsPerSample[0] == bitsPerSample[1] &&
+ bitsPerSample[1] == bitsPerSample[2]) {
// Interleaved RGB
int[] bandOffsets = new int[] {0, 1, 2};
- int dataType =
- getDataTypeFromNumBits(maxBitsPerSample, isSigned);
return ImageTypeSpecifier.createInterleaved(rgb,
bandOffsets,
dataType,
false,
false);
- } else if(samplesPerPixel == 4) {
+ } else if(samplesPerPixel == 4 &&
+ dataTypeSize == bitsPerSample[0] &&
+ bitsPerSample[0] == bitsPerSample[1] &&
+ bitsPerSample[1] == bitsPerSample[2] &&
+ bitsPerSample[2] == bitsPerSample[3]) {
// Interleaved RGBA
int[] bandOffsets = new int[] {0, 1, 2, 3};
- int dataType =
- getDataTypeFromNumBits(maxBitsPerSample, isSigned);
boolean alphaPremultiplied = false;
if (extraSamples != null &&
extraSamples[0] ==
BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
alphaPremultiplied = true;
@@ -1194,25 +1220,33 @@
bandOffsets,
dataType,
true,
alphaPremultiplied);
}
- } else {
+ }
+
// Arbitrary Interleaved.
int dataType =
getDataTypeFromNumBits(maxBitsPerSample, isSigned);
SampleModel sm = createInterleavedSM(dataType,
samplesPerPixel);
- ColorSpace cs = new BogusColorSpace(samplesPerPixel);
+ ColorSpace cs;
+ if (samplesPerPixel <= 2) {
+ cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
+ } else if (samplesPerPixel <= 4) {
+ cs = rgb;
+ } else {
+ cs = new BogusColorSpace(samplesPerPixel);
+ }
ColorModel cm = createComponentCM(cs,
samplesPerPixel,
+ bitsPerSample,
dataType,
false, // hasAlpha
false); // alphaPremultiplied
return new ImageTypeSpecifier(cm, sm);
}
- }
return null;
}
/**
@@ -1283,10 +1317,18 @@
public void setPlanar(boolean planar) {
this.planar = planar;
}
/**
+ * Sets the index of the planar configuration band to be decoded. This value
+ * is ignored for chunky (interleaved) images.
+ *
+ * @param the index of the planar band to decode
+ */
+ public void setPlanarBand(int planarBand) { this.planarBand = planarBand; }
+
+ /**
* Sets the value of the {@code samplesPerPixel} field.
*
* <p> If this method is called, the {@code beginDecoding}
* method must be called prior to calling any of the decode
* methods.
@@ -2486,11 +2528,11 @@
SampleModel sm = ras.getSampleModel();
// Branch based on whether data are bit-contiguous, i.e.,
// data are packaed as tightly as possible leaving no unused
// bits except at the end of a row.
- if(isDataBufferBitContiguous(sm)) {
+ if(isDataBufferBitContiguous(sm, bitsPerSample)) {
// Use byte or float data directly.
if (byteData != null) {
decodeRaw(byteData, dstOffset,
pixelBitStride, scanlineStride);
} else if (floatData != null) {
@@ -2535,15 +2577,23 @@
}
}
} else {
// Read discontiguous data into bytes and set the samples
// into the Raster.
- int bpp = getBitsPerPixel(sm);
+ int bpp;
+ if (planar) {
+ bpp = bitsPerSample[planarBand];
+ } else {
+ bpp = 0;
+ for (int bps : bitsPerSample) {
+ bpp += bps;
+ }
+ }
int bytesPerRow = (bpp*srcWidth + 7)/8;
byte[] buf = new byte[bytesPerRow*srcHeight];
decodeRaw(buf, 0, bpp, bytesPerRow);
- reformatDiscontiguousData(buf, bytesPerRow,
+ reformatDiscontiguousData(buf, bitsPerSample, bytesPerRow,
srcWidth, srcHeight,
ras);
}
}
< prev index next >