private Jp2File getOpenJ2pFile(File outputFile) throws IOException { Jp2File jp2File = openFiles.get(outputFile); if (jp2File == null) { jp2File = new Jp2File(); jp2File.file = outputFile; jp2File.stream = new FileImageInputStream(outputFile); jp2File.header = jp2File.stream.readLine(); jp2File.dataPos = jp2File.stream.getStreamPosition(); final String[] tokens = jp2File.header.split(" "); if (tokens.length != 6) { throw new IOException("Unexpected tile format"); } // String pg = tokens[0]; // PG // String ml = tokens[1]; // ML // String plus = tokens[2]; // + int jp2Width; int jp2Height; try { // int jp2File.nbits = Integer.parseInt(tokens[3]); jp2File.width = Integer.parseInt(tokens[4]); jp2File.height = Integer.parseInt(tokens[5]); } catch (NumberFormatException e) { throw new IOException("Unexpected tile format"); } openFiles.put(outputFile, jp2File); } return jp2File; }
@Override public synchronized void dispose() { for (Map.Entry<File, Jp2File> entry : openFiles.entrySet()) { System.out.println("closing " + entry.getKey()); try { final Jp2File jp2File = entry.getValue(); if (jp2File.stream != null) { jp2File.stream.close(); jp2File.stream = null; } } catch (IOException e) { // warn } } for (File file : openFiles.keySet()) { System.out.println("deleting " + file); if (!file.delete()) { // warn } } openFiles.clear(); if (!cacheDir.delete()) { // warn } }
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 Product readProductNodesImpl() throws IOException { final String s = getInput().toString(); final File file0 = new File(s); final File dir = file0.getParentFile(); final S2FilenameInfo fni0 = S2FilenameInfo.create(file0.getName()); if (fni0 == null) { throw new IOException(); } Header metadataHeader = null; final Map<Integer, BandInfo> fileMap = new HashMap<Integer, BandInfo>(); if (dir != null) { File[] files = dir.listFiles( new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(Sentinel2ProductReaderPlugIn.JP2_EXT); } }); if (files != null) { for (File file : files) { int bandIndex = fni0.getBand(file.getName()); if (bandIndex >= 0 && bandIndex < WAVEBAND_INFOS.length) { final S2WavebandInfo wavebandInfo = WAVEBAND_INFOS[bandIndex]; BandInfo bandInfo = new BandInfo( file, bandIndex, wavebandInfo, imageLayouts[wavebandInfo.resolution.id]); fileMap.put(bandIndex, bandInfo); } } } File[] metadataFiles = dir.listFiles( new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.startsWith("MTD_") && name.endsWith(".xml"); } }); if (metadataFiles != null && metadataFiles.length > 0) { File metadataFile = metadataFiles[0]; try { metadataHeader = Header.parseHeader(metadataFile); } catch (JDOMException e) { BeamLogManager.getSystemLogger() .warning("Failed to parse metadata file: " + metadataFile); } } else { BeamLogManager.getSystemLogger().warning("No metadata file found"); } } final ArrayList<Integer> bandIndexes = new ArrayList<Integer>(fileMap.keySet()); Collections.sort(bandIndexes); if (bandIndexes.isEmpty()) { throw new IOException("No valid bands found."); } String prodType = "S2_MSI_" + fni0.procLevel; final Product product = new Product( String.format("%s_%s_%s", prodType, fni0.orbitNo, fni0.tileId), prodType, imageLayouts[S2Resolution.R10M.id].width, imageLayouts[S2Resolution.R10M.id].height); try { product.setStartTime(ProductData.UTC.parse(fni0.start, "yyyyMMddHHmmss")); } catch (ParseException e) { // warn } try { product.setEndTime(ProductData.UTC.parse(fni0.stop, "yyyyMMddHHmmss")); } catch (ParseException e) { // warn } if (metadataHeader != null) { SceneDescription sceneDescription = SceneDescription.create(metadataHeader); int tileIndex = sceneDescription.getTileIndex(fni0.tileId); Envelope2D tileEnvelope = sceneDescription.getTileEnvelope(tileIndex); Header.Tile tile = metadataHeader.getTileList().get(tileIndex); try { product.setGeoCoding( new CrsGeoCoding( tileEnvelope.getCoordinateReferenceSystem(), imageLayouts[S2Resolution.R10M.id].width, imageLayouts[S2Resolution.R10M.id].height, tile.tileGeometry10M.upperLeftX, tile.tileGeometry10M.upperLeftY, tile.tileGeometry10M.xDim, -tile.tileGeometry10M.yDim, 0.0, 0.0)); } catch (FactoryException e) { // todo - handle e } catch (TransformException e) { // todo - handle e } } for (Integer bandIndex : bandIndexes) { final BandInfo bandInfo = fileMap.get(bandIndex); final Band band = product.addBand(bandInfo.wavebandInfo.bandName, ProductData.TYPE_UINT16); band.setSpectralWavelength((float) bandInfo.wavebandInfo.centralWavelength); band.setSpectralBandwidth((float) bandInfo.wavebandInfo.bandWidth); band.setSpectralBandIndex(bandIndex); band.setSourceImage(new DefaultMultiLevelImage(new Jp2MultiLevelSource(bandInfo))); } product.setNumResolutionLevels(imageLayouts[0].numResolutions); return product; }