private void decodeTile(int ti, int tj, int band) throws IOException { if (DEBUG) { System.out.println("decodeTile(" + ti + "," + tj + "," + band + ")"); } // Compute the region covered by the strip or tile Rectangle tileRect = new Rectangle( ti * tileOrStripWidth, tj * tileOrStripHeight, tileOrStripWidth, tileOrStripHeight); // Clip against the image bounds if the image is not tiled. If it // is tiled, the tile may legally extend beyond the image bounds. if (!isImageTiled(currIndex)) { tileRect = tileRect.intersection(new Rectangle(0, 0, width, height)); } // Return if the intersection is empty. if (tileRect.width <= 0 || tileRect.height <= 0) { return; } int srcMinX = tileRect.x; int srcMinY = tileRect.y; int srcWidth = tileRect.width; int srcHeight = tileRect.height; // Determine dest region that can be derived from the // source region dstMinX = iceil(srcMinX - sourceXOffset, srcXSubsampling); int dstMaxX = ifloor(srcMinX + srcWidth - 1 - sourceXOffset, srcXSubsampling); dstMinY = iceil(srcMinY - sourceYOffset, srcYSubsampling); int dstMaxY = ifloor(srcMinY + srcHeight - 1 - sourceYOffset, srcYSubsampling); dstWidth = dstMaxX - dstMinX + 1; dstHeight = dstMaxY - dstMinY + 1; dstMinX += dstXOffset; dstMinY += dstYOffset; // Clip against image bounds Rectangle dstRect = new Rectangle( dstMinX, dstMinY, dstWidth, dstHeight); dstRect = dstRect.intersection(theImage.getRaster().getBounds()); dstMinX = dstRect.x; dstMinY = dstRect.y; dstWidth = dstRect.width; dstHeight = dstRect.height; if (dstWidth <= 0 || dstHeight <= 0) { return; } // Backwards map dest region to source to determine // active source region int activeSrcMinX = (dstMinX - dstXOffset) * srcXSubsampling + sourceXOffset; int sxmax = (dstMinX + dstWidth - 1 - dstXOffset) * srcXSubsampling + sourceXOffset; int activeSrcWidth = sxmax - activeSrcMinX + 1; int activeSrcMinY = (dstMinY - dstYOffset) * srcYSubsampling + sourceYOffset; int symax = (dstMinY + dstHeight - 1 - dstYOffset) * srcYSubsampling + sourceYOffset; int activeSrcHeight = symax - activeSrcMinY + 1; decompressor.setSrcMinX(srcMinX); decompressor.setSrcMinY(srcMinY); decompressor.setSrcWidth(srcWidth); decompressor.setSrcHeight(srcHeight); decompressor.setDstMinX(dstMinX); decompressor.setDstMinY(dstMinY); decompressor.setDstWidth(dstWidth); decompressor.setDstHeight(dstHeight); decompressor.setActiveSrcMinX(activeSrcMinX); decompressor.setActiveSrcMinY(activeSrcMinY); decompressor.setActiveSrcWidth(activeSrcWidth); decompressor.setActiveSrcHeight(activeSrcHeight); int tileIndex = tj * tilesAcross + ti; if (planarConfiguration == BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) { tileIndex += band * tilesAcross * tilesDown; } long offset = getTileOrStripOffset(tileIndex); long byteCount = getTileOrStripByteCount(tileIndex); // // Attempt to handle truncated streams, i.e., where reading the // compressed strip or tile would result in an EOFException. The // number of bytes to read is clamped to the number available // from the stream starting at the indicated position in the hope // that the decompressor will handle it. // long streamLength = stream.length(); if (streamLength > 0 && offset + byteCount > streamLength) { processWarningOccurred("Attempting to process truncated stream."); if (Math.max(byteCount = streamLength - offset, 0) == 0) { processWarningOccurred("No bytes in strip/tile: skipping."); return; } } decompressor.setStream(stream); decompressor.setOffset(offset); decompressor.setByteCount((int) byteCount); decompressor.beginDecoding(); stream.mark(); decompressor.decode(); stream.reset(); }