int page = 0;
if (paramBlock.getNumParameters() > 2) {
page = paramBlock.getIntParameter(2);
}
ImageDecoder dec = ImageCodec.createImageDecoder(type, source, param);
try {
int bound = OpImage.OP_IO_BOUND;
ImageLayout layout = RIFUtil.getImageLayoutHint(renderHints);
if (renderHints != null) {
RenderingHints.Key key;
key = JAI.KEY_OPERATION_BOUND;
if (renderHints.containsKey(key)) {
bound = ((Integer)renderHints.get(key)).intValue();
}
}
// Set flag indicating that a recovery may be attempted if
// an OutOfMemoryError occurs during the decodeAsRenderedImage()
// call - which is only possible if the stream can seek backwards.
boolean canAttemptRecovery = source.canSeekBackwards();
// Save the stream position prior to decodeAsRenderedImage().
long streamPosition = Long.MIN_VALUE;
if(canAttemptRecovery) {
try {
streamPosition = source.getFilePointer();
} catch(IOException ioe) {
listener.errorOccurred(JaiI18N.getString("StreamRIF1"),
ioe, CodecRIFUtil.class, false);
// Unset the recovery attempt flag but otherwise
// ignore the exception.
canAttemptRecovery = false;
}
}
OpImage image = null;
try {
// Attempt to create an OpImage from the decoder image.
image = new DisposableNullOpImage(dec.decodeAsRenderedImage(page),
layout,
renderHints,
bound);
} catch(OutOfMemoryError memoryError) {
// Ran out of memory - may be due to the decoder being
// obliged to read the entire image when it creates the
// RenderedImage it returns.
if(canAttemptRecovery) {
// First flush the cache if one is defined.
TileCache cache = image != null ?
image.getTileCache() :
RIFUtil.getTileCacheHint(renderHints);
if(cache != null) {
cache.flush();
}
// Force garbage collection.
System.gc(); //slow
// Reposition the stream before the previous decoding.
source.seek(streamPosition);
// Retry image decoding.
image = new DisposableNullOpImage(dec.decodeAsRenderedImage(page),
layout,
renderHints,
bound);
} else {
// Re-throw the error.