(tileY < 0) || (tileY >= tilesY)) {
throw new IllegalArgumentException(JaiI18N.getString("TIFFImage12"));
}
// The tile to return.
WritableRaster tile = null;
// Synchronize the rest of the method in case other TIFFImage
// instances using the same stream were created by the same
// TIFFImageDecoder. This fixes 4690773.
synchronized(this.stream) {
// Get the data array out of the DataBuffer
byte bdata[] = null;
short sdata[] = null;
int idata[] = null;
float fdata[] = null;
DataBuffer buffer = sampleModel.createDataBuffer();
int dataType = sampleModel.getDataType();
if (dataType == DataBuffer.TYPE_BYTE) {
bdata = ((DataBufferByte)buffer).getData();
} else if (dataType == DataBuffer.TYPE_USHORT) {
sdata = ((DataBufferUShort)buffer).getData();
} else if (dataType == DataBuffer.TYPE_SHORT) {
sdata = ((DataBufferShort)buffer).getData();
} else if (dataType == DataBuffer.TYPE_INT) {
idata = ((DataBufferInt)buffer).getData();
} else if (dataType == DataBuffer.TYPE_FLOAT) {
if(buffer instanceof DataBufferFloat) {
fdata = ((DataBufferFloat)buffer).getData();
} else {
// This is a hack to make this work with JAI which in some
// cases downcasts the DataBuffer to a type-specific class.
// In the case of float data this current means the JAI class
// com.lightcrafts.mediax.jai.DataBufferFloat.
try {
Method getDataMethod =
buffer.getClass().getMethod("getData", null);
fdata = (float[])getDataMethod.invoke(buffer, null);
} catch(Exception e) {
String message = JaiI18N.getString("TIFFImage18");
ImagingListenerProxy.errorOccurred(message,
new ImagingException(message, e),
this, false);
// throw new RuntimeException(JaiI18N.getString("TIFFImage18"));
}
}
}
tile =
(WritableRaster)RasterFactory.createWritableRaster(sampleModel,
buffer,
new Point(tileXToX(tileX),
tileYToY(tileY)));
// Save original file pointer position and seek to tile data location.
long save_offset = 0;
try {
save_offset = stream.getFilePointer();
stream.seek(tileOffsets[tileY*tilesX + tileX]);
} catch (IOException ioe) {
String message = JaiI18N.getString("TIFFImage13");
ImagingListenerProxy.errorOccurred(message,
new ImagingException(message, ioe),
this, false);
// throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
}
// Number of bytes in this tile (strip) after compression.
int byteCount = (int)tileByteCounts[tileY*tilesX + tileX];
// Find out the number of bytes in the current tile. If the image is
// tiled this may include pixels which are outside of the image bounds
// if the image width and height are not multiples of the tile width
// and height respectively.
Rectangle tileRect = new Rectangle(tileXToX(tileX), tileYToY(tileY),
tileWidth, tileHeight);
Rectangle newRect = isTiled ?
tileRect : tileRect.intersection(getBounds());
int unitsInThisTile = newRect.width * newRect.height * numBands;
// Allocate read buffer if needed.
byte data[] = compression != COMP_NONE || imageType == TYPE_PALETTE ?
new byte[byteCount] : null;
// Read the data, uncompressing as needed. There are four cases:
// bilevel, palette-RGB, 4-bit grayscale, and everything else.
if(imageType == TYPE_BILEVEL) { // bilevel
try {
if (compression == COMP_PACKBITS) {
stream.readFully(data, 0, byteCount);
// Since the decompressed data will still be packed
// 8 pixels into 1 byte, calculate bytesInThisTile
int bytesInThisTile;
if ((newRect.width % 8) == 0) {
bytesInThisTile = (newRect.width/8) * newRect.height;
} else {
bytesInThisTile =
(newRect.width/8 + 1) * newRect.height;
}
decodePackbits(data, bytesInThisTile, bdata);
} else if (compression == COMP_LZW) {
stream.readFully(data, 0, byteCount);
lzwDecoder.decode(data, bdata, newRect.height);
} else if (compression == COMP_FAX_G3_1D) {
stream.readFully(data, 0, byteCount);
decoder.decode1D(bdata, data, 0, newRect.height);
} else if (compression == COMP_FAX_G3_2D) {
stream.readFully(data, 0, byteCount);
decoder.decode2D(bdata, data, 0, newRect.height,
tiffT4Options);
} else if (compression == COMP_FAX_G4_2D) {
stream.readFully(data, 0, byteCount);
decoder.decodeT6(bdata, data, 0, newRect.height,
tiffT6Options);
} else if (compression == COMP_DEFLATE) {
stream.readFully(data, 0, byteCount);
inflate(data, bdata);
} else if (compression == COMP_NONE) {
stream.readFully(bdata, 0, byteCount);
}
stream.seek(save_offset);
} catch (IOException ioe) {
String message = JaiI18N.getString("TIFFImage13");
ImagingListenerProxy.errorOccurred(message,
new ImagingException(message, ioe),
this, false);
// throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
}
} else if(imageType == TYPE_PALETTE) { // palette-RGB
if (sampleSize == 16) {
if (decodePaletteAsShorts) {
short tempData[]= null;
// At this point the data is 1 banded and will
// become 3 banded only after we've done the palette
// lookup, since unitsInThisTile was calculated with
// 3 bands, we need to divide this by 3.
int unitsBeforeLookup = unitsInThisTile / 3;
// Since unitsBeforeLookup is the number of shorts,
// but we do our decompression in terms of bytes, we
// need to multiply it by 2 in order to figure out
// how many bytes we'll get after decompression.
int entries = unitsBeforeLookup * 2;
// Read the data, if compressed, decode it, reset the pointer
try {
if (compression == COMP_PACKBITS) {
stream.readFully(data, 0, byteCount);
byte byteArray[] = new byte[entries];
decodePackbits(data, entries, byteArray);
tempData = new short[unitsBeforeLookup];
interpretBytesAsShorts(byteArray, tempData,
unitsBeforeLookup);
} else if (compression == COMP_LZW) {
// Read in all the compressed data for this tile
stream.readFully(data, 0, byteCount);
byte byteArray[] = new byte[entries];
lzwDecoder.decode(data, byteArray, newRect.height);
tempData = new short[unitsBeforeLookup];
interpretBytesAsShorts(byteArray, tempData,
unitsBeforeLookup);
} else if (compression == COMP_DEFLATE) {
stream.readFully(data, 0, byteCount);
byte byteArray[] = new byte[entries];
inflate(data, byteArray);
tempData = new short[unitsBeforeLookup];
interpretBytesAsShorts(byteArray, tempData,
unitsBeforeLookup);
} else if (compression == COMP_NONE) {
// byteCount tells us how many bytes are there
// in this tile, but we need to read in shorts,
// which will take half the space, so while
// allocating we divide byteCount by 2.
tempData = new short[byteCount/2];
readShorts(byteCount/2, tempData);
}
stream.seek(save_offset);
} catch (IOException ioe) {
String message = JaiI18N.getString("TIFFImage13");
ImagingListenerProxy.errorOccurred(message,
new ImagingException(message, ioe),
this, false);
// throw new RuntimeException(
// JaiI18N.getString("TIFFImage13"));
}
if (dataType == DataBuffer.TYPE_USHORT) {
// Expand the palette image into an rgb image with ushort
// data type.
int cmapValue;
int count = 0, lookup, len = colormap.length/3;
int len2 = len * 2;
for (int i=0; i<unitsBeforeLookup; i++) {
// Get the index into the colormap
lookup = tempData[i] & 0xffff;
// Get the blue value
cmapValue = colormap[lookup+len2];
sdata[count++] = (short)(cmapValue & 0xffff);
// Get the green value
cmapValue = colormap[lookup+len];
sdata[count++] = (short)(cmapValue & 0xffff);
// Get the red value
cmapValue = colormap[lookup];
sdata[count++] = (short)(cmapValue & 0xffff);
}
} else if (dataType == DataBuffer.TYPE_SHORT) {
// Expand the palette image into an rgb image with
// short data type.
int cmapValue;
int count = 0, lookup, len = colormap.length/3;
int len2 = len * 2;
for (int i=0; i<unitsBeforeLookup; i++) {
// Get the index into the colormap
lookup = tempData[i] & 0xffff;
// Get the blue value
cmapValue = colormap[lookup+len2];
sdata[count++] = (short)cmapValue;
// Get the green value
cmapValue = colormap[lookup+len];
sdata[count++] = (short)cmapValue;
// Get the red value
cmapValue = colormap[lookup];
sdata[count++] = (short)cmapValue;
}
}
} else {
// No lookup being done here, when RGB values are needed,
// the associated IndexColorModel can be used to get them.
try {
if (compression == COMP_PACKBITS) {
stream.readFully(data, 0, byteCount);
// Since unitsInThisTile is the number of shorts,
// but we do our decompression in terms of bytes, we
// need to multiply unitsInThisTile by 2 in order to
// figure out how many bytes we'll get after
// decompression.
int bytesInThisTile = unitsInThisTile * 2;
byte byteArray[] = new byte[bytesInThisTile];
decodePackbits(data, bytesInThisTile, byteArray);
interpretBytesAsShorts(byteArray, sdata,
unitsInThisTile);
} else if (compression == COMP_LZW) {
stream.readFully(data, 0, byteCount);
// Since unitsInThisTile is the number of shorts,
// but we do our decompression in terms of bytes, we
// need to multiply unitsInThisTile by 2 in order to
// figure out how many bytes we'll get after
// decompression.
byte byteArray[] = new byte[unitsInThisTile * 2];
lzwDecoder.decode(data, byteArray, newRect.height);
interpretBytesAsShorts(byteArray, sdata,
unitsInThisTile);
} else if (compression == COMP_DEFLATE) {
stream.readFully(data, 0, byteCount);
byte byteArray[] = new byte[unitsInThisTile * 2];
inflate(data, byteArray);
interpretBytesAsShorts(byteArray, sdata,
unitsInThisTile);
} else if (compression == COMP_NONE) {
readShorts(byteCount/2, sdata);
}
stream.seek(save_offset);
} catch (IOException ioe) {
String message = JaiI18N.getString("TIFFImage13");
ImagingListenerProxy.errorOccurred(message,
new ImagingException(message, ioe),
this, false);
// throw new RuntimeException(
// JaiI18N.getString("TIFFImage13"));
}
}
} else if (sampleSize == 8) {
if (decodePaletteAsShorts) {
byte tempData[]= null;
// At this point the data is 1 banded and will
// become 3 banded only after we've done the palette
// lookup, since unitsInThisTile was calculated with
// 3 bands, we need to divide this by 3.
int unitsBeforeLookup = unitsInThisTile / 3;
// Read the data, if compressed, decode it, reset the pointer
try {
if (compression == COMP_PACKBITS) {
stream.readFully(data, 0, byteCount);
tempData = new byte[unitsBeforeLookup];
decodePackbits(data, unitsBeforeLookup, tempData);
} else if (compression == COMP_LZW) {
stream.readFully(data, 0, byteCount);
tempData = new byte[unitsBeforeLookup];
lzwDecoder.decode(data, tempData, newRect.height);
} else if (compression == COMP_JPEG_TTN2) {
stream.readFully(data, 0, byteCount);
Raster tempTile = decodeJPEG(data,
decodeParam,
colorConvertJPEG,
tile.getMinX(),
tile.getMinY());
int[] tempPixels = new int[unitsBeforeLookup];
tempTile.getPixels(tile.getMinX(),
tile.getMinY(),
tile.getWidth(),
tile.getHeight(),
tempPixels);
tempData = new byte[unitsBeforeLookup];
for(int i = 0; i < unitsBeforeLookup; i++) {
tempData[i] = (byte)tempPixels[i];
}
} else if (compression == COMP_DEFLATE) {
stream.readFully(data, 0, byteCount);
tempData = new byte[unitsBeforeLookup];
inflate(data, tempData);
} else if (compression == COMP_NONE) {
tempData = new byte[byteCount];
stream.readFully(tempData, 0, byteCount);
}
stream.seek(save_offset);
} catch (IOException ioe) {
String message = JaiI18N.getString("TIFFImage13");
ImagingListenerProxy.errorOccurred(message,
new ImagingException(message, ioe),
this, false);
// throw new RuntimeException(
// JaiI18N.getString("TIFFImage13"));
}
// Expand the palette image into an rgb image with ushort
// data type.
int cmapValue;
int count = 0, lookup, len = colormap.length/3;
int len2 = len * 2;
for (int i=0; i<unitsBeforeLookup; i++) {
// Get the index into the colormap
lookup = tempData[i] & 0xff;
// Get the blue value
cmapValue = colormap[lookup+len2];
sdata[count++] = (short)(cmapValue & 0xffff);
// Get the green value
cmapValue = colormap[lookup+len];
sdata[count++] = (short)(cmapValue & 0xffff);
// Get the red value
cmapValue = colormap[lookup];
sdata[count++] = (short)(cmapValue & 0xffff);
}
} else {
// No lookup being done here, when RGB values are needed,
// the associated IndexColorModel can be used to get them.
try {
if (compression == COMP_PACKBITS) {
stream.readFully(data, 0, byteCount);
decodePackbits(data, unitsInThisTile, bdata);
} else if (compression == COMP_LZW) {
stream.readFully(data, 0, byteCount);
lzwDecoder.decode(data, bdata, newRect.height);
} else if (compression == COMP_JPEG_TTN2) {
stream.readFully(data, 0, byteCount);
tile.setRect(decodeJPEG(data,
decodeParam,
colorConvertJPEG,
tile.getMinX(),
tile.getMinY()));
} else if (compression == COMP_DEFLATE) {
stream.readFully(data, 0, byteCount);
inflate(data, bdata);
} else if (compression == COMP_NONE) {
stream.readFully(bdata, 0, byteCount);
}
stream.seek(save_offset);
} catch (IOException ioe) {
String message = JaiI18N.getString("TIFFImage13");
ImagingListenerProxy.errorOccurred(message,
new ImagingException(message, ioe),
this, false);
// throw new RuntimeException(
// JaiI18N.getString("TIFFImage13"));
}
}
} else if (sampleSize == 4) {
int padding = (newRect.width % 2 == 0) ? 0 : 1;
int bytesPostDecoding = ((newRect.width/2 + padding) *
newRect.height);
// Output short images
if (decodePaletteAsShorts) {
byte tempData[] = null;
try {
stream.readFully(data, 0, byteCount);
stream.seek(save_offset);
} catch (IOException ioe) {
String message = JaiI18N.getString("TIFFImage13");
ImagingListenerProxy.errorOccurred(message,
new ImagingException(message, ioe),
this, false);
// throw new RuntimeException(
// JaiI18N.getString("TIFFImage13"));
}
// If compressed, decode the data.
if (compression == COMP_PACKBITS) {
tempData = new byte[bytesPostDecoding];
decodePackbits(data, bytesPostDecoding, tempData);
} else if (compression == COMP_LZW) {
tempData = new byte[bytesPostDecoding];
lzwDecoder.decode(data, tempData, newRect.height);
} else if (compression == COMP_DEFLATE) {
tempData = new byte[bytesPostDecoding];
inflate(data, tempData);
} else if (compression == COMP_NONE) {
tempData = data;
}
int bytes = unitsInThisTile / 3;
// Unpack the 2 pixels packed into each byte.
data = new byte[bytes];
int srcCount = 0, dstCount = 0;
for (int j=0; j<newRect.height; j++) {
for (int i=0; i<newRect.width/2; i++) {
data[dstCount++] =
(byte)((tempData[srcCount] & 0xf0) >> 4);
data[dstCount++] =
(byte)(tempData[srcCount++] & 0x0f);
}
if (padding == 1) {
data[dstCount++] =
(byte)((tempData[srcCount++] & 0xf0) >> 4);
}
}
int len = colormap.length/3;
int len2 = len*2;
int cmapValue, lookup;
int count = 0;
for (int i=0; i<bytes; i++) {
lookup = data[i] & 0xff;
cmapValue = colormap[lookup+len2];
sdata[count++] = (short)(cmapValue & 0xffff);
cmapValue = colormap[lookup+len];
sdata[count++] = (short)(cmapValue & 0xffff);
cmapValue = colormap[lookup];
sdata[count++] = (short)(cmapValue & 0xffff);
}
} else {
// Output byte values, use IndexColorModel for unpacking
try {
// If compressed, decode the data.
if (compression == COMP_PACKBITS) {
stream.readFully(data, 0, byteCount);
decodePackbits(data, bytesPostDecoding, bdata);
} else if (compression == COMP_LZW) {
stream.readFully(data, 0, byteCount);
lzwDecoder.decode(data, bdata, newRect.height);
} else if (compression == COMP_DEFLATE) {
stream.readFully(data, 0, byteCount);
inflate(data, bdata);
} else if (compression == COMP_NONE) {
stream.readFully(bdata, 0, byteCount);
}
stream.seek(save_offset);
} catch (IOException ioe) {
String message = JaiI18N.getString("TIFFImage13");
ImagingListenerProxy.errorOccurred(message,
new ImagingException(message, ioe),
this, false);
// throw new RuntimeException(
// JaiI18N.getString("TIFFImage13"));
}
}
}
} else if(imageType == TYPE_GRAY_4BIT) { // 4-bit gray
try {
if (compression == COMP_PACKBITS) {
stream.readFully(data, 0, byteCount);
// Since the decompressed data will still be packed
// 2 pixels into 1 byte, calculate bytesInThisTile
int bytesInThisTile;
if ((newRect.width % 8) == 0) {
bytesInThisTile = (newRect.width/2) * newRect.height;
} else {
bytesInThisTile = (newRect.width/2 + 1) *
newRect.height;
}
decodePackbits(data, bytesInThisTile, bdata);
} else if (compression == COMP_LZW) {
stream.readFully(data, 0, byteCount);
lzwDecoder.decode(data, bdata, newRect.height);
} else if (compression == COMP_DEFLATE) {
stream.readFully(data, 0, byteCount);
inflate(data, bdata);
} else {
stream.readFully(bdata, 0, byteCount);
}
stream.seek(save_offset);
} catch (IOException ioe) {
String message = JaiI18N.getString("TIFFImage13");
ImagingListenerProxy.errorOccurred(message,
new ImagingException(message, ioe),
this, false);
// throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
}
} else { // everything else
try {
if (sampleSize == 8) {
if (compression == COMP_NONE) {
stream.readFully(bdata, 0, byteCount);
} else if (compression == COMP_LZW) {
stream.readFully(data, 0, byteCount);
lzwDecoder.decode(data, bdata, newRect.height);
} else if (compression == COMP_PACKBITS) {
stream.readFully(data, 0, byteCount);
decodePackbits(data, unitsInThisTile, bdata);
} else if (compression == COMP_JPEG_TTN2) {
stream.readFully(data, 0, byteCount);
tile.setRect(decodeJPEG(data,
decodeParam,
colorConvertJPEG,
tile.getMinX(),
tile.getMinY()));
} else if (compression == COMP_DEFLATE) {
stream.readFully(data, 0, byteCount);
inflate(data, bdata);
}
} else if (sampleSize == 16) {
if (compression == COMP_NONE) {
readShorts(byteCount/2, sdata);
} else if (compression == COMP_LZW) {
stream.readFully(data, 0, byteCount);
// Since unitsInThisTile is the number of shorts,
// but we do our decompression in terms of bytes, we
// need to multiply unitsInThisTile by 2 in order to
// figure out how many bytes we'll get after
// decompression.
byte byteArray[] = new byte[unitsInThisTile * 2];
lzwDecoder.decode(data, byteArray, newRect.height);
interpretBytesAsShorts(byteArray, sdata,
unitsInThisTile);
} else if (compression == COMP_PACKBITS) {
stream.readFully(data, 0, byteCount);
// Since unitsInThisTile is the number of shorts,
// but we do our decompression in terms of bytes, we
// need to multiply unitsInThisTile by 2 in order to
// figure out how many bytes we'll get after
// decompression.
int bytesInThisTile = unitsInThisTile * 2;
byte byteArray[] = new byte[bytesInThisTile];
decodePackbits(data, bytesInThisTile, byteArray);
interpretBytesAsShorts(byteArray, sdata,
unitsInThisTile);
} else if (compression == COMP_DEFLATE) {
stream.readFully(data, 0, byteCount);
byte byteArray[] = new byte[unitsInThisTile * 2];
inflate(data, byteArray);
interpretBytesAsShorts(byteArray, sdata,
unitsInThisTile);
}
} else if (sampleSize == 32 &&
dataType == DataBuffer.TYPE_INT) { // redundant
if (compression == COMP_NONE) {
readInts(byteCount/4, idata);
} else if (compression == COMP_LZW) {
stream.readFully(data, 0, byteCount);
// Since unitsInThisTile is the number of ints,
// but we do our decompression in terms of bytes, we
// need to multiply unitsInThisTile by 4 in order to
// figure out how many bytes we'll get after
// decompression.
byte byteArray[] = new byte[unitsInThisTile * 4];
lzwDecoder.decode(data, byteArray, newRect.height);
interpretBytesAsInts(byteArray, idata,
unitsInThisTile);
} else if (compression == COMP_PACKBITS) {
stream.readFully(data, 0, byteCount);
// Since unitsInThisTile is the number of ints,
// but we do our decompression in terms of bytes, we
// need to multiply unitsInThisTile by 4 in order to
// figure out how many bytes we'll get after
// decompression.
int bytesInThisTile = unitsInThisTile * 4;
byte byteArray[] = new byte[bytesInThisTile];
decodePackbits(data, bytesInThisTile, byteArray);
interpretBytesAsInts(byteArray, idata,
unitsInThisTile);
} else if (compression == COMP_DEFLATE) {
stream.readFully(data, 0, byteCount);
byte byteArray[] = new byte[unitsInThisTile * 4];
inflate(data, byteArray);
interpretBytesAsInts(byteArray, idata,
unitsInThisTile);
}
} else if (sampleSize == 32 &&
dataType == DataBuffer.TYPE_FLOAT) { // redundant
if (compression == COMP_NONE) {
readFloats(byteCount/4, fdata);
} else if (compression == COMP_LZW) {
stream.readFully(data, 0, byteCount);
// Since unitsInThisTile is the number of floats,
// but we do our decompression in terms of bytes, we
// need to multiply unitsInThisTile by 4 in order to
// figure out how many bytes we'll get after
// decompression.
byte byteArray[] = new byte[unitsInThisTile * 4];
lzwDecoder.decode(data, byteArray, newRect.height);
interpretBytesAsFloats(byteArray, fdata,
unitsInThisTile);
} else if (compression == COMP_PACKBITS) {
stream.readFully(data, 0, byteCount);
// Since unitsInThisTile is the number of floats,
// but we do our decompression in terms of bytes, we
// need to multiply unitsInThisTile by 4 in order to
// figure out how many bytes we'll get after
// decompression.
int bytesInThisTile = unitsInThisTile * 4;
byte byteArray[] = new byte[bytesInThisTile];
decodePackbits(data, bytesInThisTile, byteArray);
interpretBytesAsFloats(byteArray, fdata,
unitsInThisTile);
} else if (compression == COMP_DEFLATE) {
stream.readFully(data, 0, byteCount);
byte byteArray[] = new byte[unitsInThisTile * 4];
inflate(data, byteArray);
interpretBytesAsFloats(byteArray, fdata,
unitsInThisTile);
}
}
stream.seek(save_offset);
} catch (IOException ioe) {
String message = JaiI18N.getString("TIFFImage13");
ImagingListenerProxy.errorOccurred(message,
new ImagingException(message, ioe),
this, false);
// throw new RuntimeException(JaiI18N.getString("TIFFImage13"));
}
// Modify the data for certain special cases.
switch(imageType) {
case TYPE_GRAY:
case TYPE_GRAY_ALPHA:
if(isWhiteZero) {
// Since we are using a ComponentColorModel with this
// image, we need to change the WhiteIsZero data to
// BlackIsZero data so it will display properly.
if (dataType == DataBuffer.TYPE_BYTE &&
!(colorModel instanceof IndexColorModel)) {
for (int l = 0; l < bdata.length; l += numBands) {
bdata[l] = (byte)(255 - bdata[l]);
}
} else if (dataType == DataBuffer.TYPE_USHORT) {
int ushortMax = Short.MAX_VALUE - Short.MIN_VALUE;
for (int l = 0; l < sdata.length; l += numBands) {
sdata[l] = (short)(ushortMax - sdata[l]);
}
} else if (dataType == DataBuffer.TYPE_SHORT) {
for (int l = 0; l < sdata.length; l += numBands) {
sdata[l] = (short)(~sdata[l]);
}
} else if (dataType == DataBuffer.TYPE_INT) {
long uintMax = Integer.MAX_VALUE - Integer.MIN_VALUE;
for (int l = 0; l < idata.length; l += numBands) {
idata[l] = (int)(uintMax - (long)idata[l]);
}
}
}
break;
case TYPE_YCBCR_SUB:
// Post-processing for YCbCr with subsampled chrominance:
// simply replicate the chroma channels for displayability.
int pixelsPerDataUnit = chromaSubH*chromaSubV;
int numH = newRect.width/chromaSubH;
int numV = newRect.height/chromaSubV;
byte[] tempData = new byte[numH*numV*(pixelsPerDataUnit + 2)];
System.arraycopy(bdata, 0, tempData, 0, tempData.length);
int samplesPerDataUnit = pixelsPerDataUnit*3;
int[] pixels = new int[samplesPerDataUnit];
int bOffset = 0;
int offsetCb = pixelsPerDataUnit;
int offsetCr = offsetCb + 1;
int y = newRect.y;
for(int j = 0; j < numV; j++) {
int x = newRect.x;
for(int i = 0; i < numH; i++) {
int Cb = tempData[bOffset + offsetCb];
int Cr = tempData[bOffset + offsetCr];
int k = 0;
while(k < samplesPerDataUnit) {
pixels[k++] = tempData[bOffset++];
pixels[k++] = Cb;
pixels[k++] = Cr;
}
bOffset += 2;
tile.setPixels(x, y, chromaSubH, chromaSubV, pixels);
x += chromaSubH;
}
y += chromaSubV;
}