private void readTileData( File outputFile, int tileX, int tileY, int tileWidth, int tileHeight, int jp2TileX, int jp2TileY, int jp2TileWidth, int jp2TileHeight, short[] tileData, Rectangle destRect) throws IOException { synchronized (this) { if (!locks.containsKey(outputFile)) { locks.put(outputFile, new Object()); } } final Object lock = locks.get(outputFile); synchronized (lock) { Jp2File jp2File = getOpenJ2pFile(outputFile); int jp2Width = jp2File.width; int jp2Height = jp2File.height; if (jp2Width > jp2TileWidth || jp2Height > jp2TileHeight) { throw new IllegalStateException( String.format( "width (=%d) > tileWidth (=%d) || height (=%d) > tileHeight (=%d)", jp2Width, jp2TileWidth, jp2Height, jp2TileHeight)); } int jp2X = destRect.x - jp2TileX * jp2TileWidth; int jp2Y = destRect.y - jp2TileY * jp2TileHeight; if (jp2X < 0 || jp2Y < 0) { throw new IllegalStateException( String.format("jp2X (=%d) < 0 || jp2Y (=%d) < 0", jp2X, jp2Y)); } final ImageInputStream stream = jp2File.stream; if (jp2X == 0 && jp2Width == tileWidth && jp2Y == 0 && jp2Height == tileHeight && tileWidth * tileHeight == tileData.length) { stream.seek(jp2File.dataPos); stream.readFully(tileData, 0, tileData.length); } else { final Rectangle jp2FileRect = new Rectangle(0, 0, jp2Width, jp2Height); final Rectangle tileRect = new Rectangle(jp2X, jp2Y, tileWidth, tileHeight); final Rectangle intersection = jp2FileRect.intersection(tileRect); System.out.printf( "%s: tile=(%d,%d): jp2FileRect=%s, tileRect=%s, intersection=%s\n", jp2File.file, tileX, tileY, jp2FileRect, tileRect, intersection); if (!intersection.isEmpty()) { long seekPos = jp2File.dataPos + NUM_SHORT_BYTES * (intersection.y * jp2Width + intersection.x); int tilePos = 0; for (int y = 0; y < intersection.height; y++) { stream.seek(seekPos); stream.readFully(tileData, tilePos, intersection.width); seekPos += NUM_SHORT_BYTES * jp2Width; tilePos += tileWidth; for (int x = intersection.width; x < tileWidth; x++) { tileData[y * tileWidth + x] = (short) 0; } } for (int y = intersection.height; y < tileWidth; y++) { for (int x = 0; x < tileWidth; x++) { tileData[y * tileWidth + x] = (short) 0; } } } else { Arrays.fill(tileData, (short) 0); } } } }
@Override protected void computeRect(PlanarImage[] sources, WritableRaster dest, Rectangle destRect) { final DataBufferUShort dataBuffer = (DataBufferUShort) dest.getDataBuffer(); final short[] tileData = dataBuffer.getData(); final int tileWidth = this.getTileWidth(); final int tileHeight = this.getTileHeight(); final int tileX = destRect.x / tileWidth; final int tileY = destRect.y / tileHeight; if (tileWidth * tileHeight != tileData.length) { throw new IllegalStateException( String.format( "tileWidth (=%d) * tileHeight (=%d) != tileData.length (=%d)", tileWidth, tileHeight, tileData.length)); } final int resolution = getLevel(); final Dimension jp2TileDim = getJp2TileDim(bandInfo, resolution); final int jp2TileWidth = jp2TileDim.width; final int jp2TileHeight = jp2TileDim.height; final int jp2TileX = destRect.x / jp2TileWidth; final int jp2TileY = destRect.y / jp2TileHeight; // Res - Img Size - Tile W // 0 - 10960 - 4096 // 1 - 5480 - 2048 // 2 - 2740 - 1024 // 3 - 1370 - 512 // 4 - 685 - 256 // 5 - 343 - 128 final File outputFile = new File( cacheDir, FileUtils.exchangeExtension( imageFile.getName(), String.format("_R%d_TX%d_TY%d.pgx", resolution, jp2TileX, jp2TileY))); final File outputFile0 = getFirstComponentOutputFile(outputFile); if (!outputFile0.exists()) { System.out.printf( "Jp2ExeImage.readTileData(): recomputing res=%d, tile=(%d,%d)\n", resolution, jp2TileX, jp2TileY); try { decompressTile(outputFile, jp2TileX, jp2TileY); } catch (IOException e) { // warn outputFile0.delete(); } if (!outputFile0.exists()) { Arrays.fill(tileData, (short) 0); return; } } try { System.out.printf( "Jp2ExeImage.readTileData(): reading res=%d, tile=(%d,%d)\n", resolution, jp2TileX, jp2TileY); readTileData( outputFile0, tileX, tileY, tileWidth, tileHeight, jp2TileX, jp2TileY, jp2TileWidth, jp2TileHeight, tileData, destRect); } catch (IOException e) { // warn } }