/** * Writes raster data from the given in-memory source buffer into the data sink specified by the * given source band and region. * * <p> * * <h3>Source band</h3> * * The source band is used to identify the data sink in which this method transfers the sample * values given in the source buffer. The method does not modify the pixel data of the given * source band at all. * * <p> * * <h3>Source buffer</h3> * * The first element of the source buffer corresponds to the given <code>sourceOffsetX</code> and * <code>sourceOffsetY</code> of the source region. These parameters are an offset within the * band's raster data and <b>not</b> an offset within the source buffer.<br> * The number of elements in the buffer must be exactly be <code>sourceWidth * sourceHeight</code> * . The pixel values to be writte are considered to be stored in line-by-line order, so the * raster X co-ordinate varies faster than the Y. * * <p> * * <h3>Source region</h3> * * The given destination region specified by the <code>sourceOffsetX</code>, <code>sourceOffsetY * </code>, <code>sourceWidth</code> and <code>sourceHeight</code> parameters is given in the * source band's raster co-ordinates. These co-ordinates are identical with the destination raster * co-ordinates since product writers do not support spectral or spatial subsets. * * @param sourceBand the source band which identifies the data sink to which to write the sample * values * @param regionData the data buffer which provides the sample values to be written * @param regionX the X-offset in the band's raster co-ordinates * @param regionY the Y-offset in the band's raster co-ordinates * @param regionWidth the width of region to be written given in the band's raster co-ordinates * @param regionHeight the height of region to be written given in the band's raster co-ordinates * @throws java.io.IOException if an I/O error occurs * @throws IllegalArgumentException if the number of elements source buffer not equals <code> * sourceWidth * * sourceHeight</code> or the source region is out of the band's * raster * @see Band#getRasterWidth() * @see Band#getRasterHeight() */ public void writeBandRasterData( final Band sourceBand, final int regionX, final int regionY, final int regionWidth, final int regionHeight, final ProductData regionData, ProgressMonitor pm) throws IOException { if (!tempProduct.containsBand(sourceBand.getName())) { throw new IllegalArgumentException( "'" + sourceBand.getName() + "' is not a band of the product"); } final int bandDataType = ifd.getBandDataType(); final int stripIndex = getStripIndex(sourceBand); final TiffValue[] offsetValues = ifd.getEntry(TiffTag.STRIP_OFFSETS).getValues(); final long stripOffset = ((TiffLong) offsetValues[stripIndex]).getValue(); final TiffValue[] bitsPerSampleValues = ifd.getEntry(TiffTag.BITS_PER_SAMPLE).getValues(); final long elemSize = ((TiffShort) bitsPerSampleValues[stripIndex]).getValue() / 8; final long sourceWidthBytes = sourceBand.getSceneRasterWidth() * elemSize; final long regionOffsetXInBytes = regionX * elemSize; final long pixelOffset = sourceWidthBytes * regionY + regionOffsetXInBytes; final long startOffset = stripOffset + pixelOffset; pm.beginTask("Writing band '" + sourceBand.getName() + "'...", regionHeight); try { for (int y = 0; y < regionHeight; y++) { ios.seek(startOffset + y * sourceWidthBytes); final int stride = y * regionWidth; if (bandDataType == ProductData.TYPE_UINT8) { final byte[] data = new byte[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = (byte) regionData.getElemUIntAt(stride + x); } ios.write(data); } else if (bandDataType == ProductData.TYPE_INT8) { final byte[] data = new byte[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = (byte) regionData.getElemIntAt(stride + x); } ios.write(data); } else if (bandDataType == ProductData.TYPE_UINT16) { final short[] data = new short[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = (short) regionData.getElemUIntAt(stride + x); } ios.writeShorts(data, 0, regionWidth); } else if (bandDataType == ProductData.TYPE_INT16) { final short[] data = new short[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = (short) regionData.getElemIntAt(stride + x); } ios.writeShorts(data, 0, regionWidth); } else if (bandDataType == ProductData.TYPE_UINT32) { final int[] data = new int[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = (int) regionData.getElemUIntAt(stride + x); } ios.writeInts(data, 0, regionWidth); } else if (bandDataType == ProductData.TYPE_INT32) { final int[] data = new int[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = regionData.getElemIntAt(stride + x); } ios.writeInts(data, 0, regionWidth); } else if (bandDataType == ProductData.TYPE_FLOAT32) { final float[] data = new float[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = regionData.getElemFloatAt(stride + x); } ios.writeFloats(data, 0, regionWidth); } else if (bandDataType == ProductData.TYPE_FLOAT64) { final double[] data = new double[regionWidth]; for (int x = 0; x < regionWidth; x++) { data[x] = regionData.getElemDoubleAt(stride + x); } ios.writeDoubles(data, 0, regionWidth); } pm.worked(1); } } finally { pm.done(); } }
/** * Called by the framework in order to compute a tile for the given target band. * * <p>The default implementation throws a runtime exception with the message "not implemented". * * @param targetBand The target band. * @param targetTile The current tile associated with the target band to be computed. * @param pm A progress monitor which should be used to determine computation cancelation * requests. * @throws OperatorException If an error occurs during computation of the target raster. */ @Override public void computeTile(Band targetBand, Tile targetTile, ProgressMonitor pm) throws OperatorException { try { final Band sourceBand = sourceProduct.getBand(targetBand.getName()); final Tile srcTile = getSourceTile(sourceBand, targetTile.getRectangle()); final Stx stx = sourceBand.getStx(); double origMin = stx.getMinimum(); double origMax = stx.getMaximum(); ScalingType scaling = verifyScaling(targetScaling, dataType); final double newMin = getMin(dataType); final double newMax = getMax(dataType); final double newRange = newMax - newMin; if (origMax <= newMax && origMin >= newMin && sourceBand.getDataType() < ProductData.TYPE_FLOAT32) scaling = ScalingType.NONE; final ProductData srcData = srcTile.getRawSamples(); final ProductData dstData = targetTile.getRawSamples(); final double srcNoDataValue = sourceBand.getNoDataValue(); final double destNoDataValue = targetBand.getNoDataValue(); if (scaling == ScalingType.LINEAR_PEAK_CLIPPED) { final Histogram histogram = new Histogram(stx.getHistogramBins(), origMin, origMax); final int[] bitCounts = histogram.getBinCounts(); double rightPct = 0.025; for (int i = bitCounts.length - 1; i > 0; --i) { if (bitCounts[i] > 10) { rightPct = i / (double) bitCounts.length; break; } } final Range autoStretchRange = histogram.findRange(0.025, rightPct); origMin = autoStretchRange.getMin(); origMax = autoStretchRange.getMax(); } else if (scaling == ScalingType.LINEAR_CLIPPED) { final Histogram histogram = new Histogram(stx.getHistogramBins(), origMin, origMax); final Range autoStretchRange = histogram.findRangeFor95Percent(); origMin = autoStretchRange.getMin(); origMax = autoStretchRange.getMax(); } final double origRange = origMax - origMin; final int numElem = dstData.getNumElems(); double srcValue; for (int i = 0; i < numElem; ++i) { srcValue = srcData.getElemDoubleAt(i); if (srcValue == srcNoDataValue) { dstData.setElemDoubleAt(i, destNoDataValue); } else { if (scaling == ScalingType.NONE) dstData.setElemDoubleAt(i, srcValue); else if (scaling == ScalingType.TRUNC) dstData.setElemDoubleAt(i, truncate(srcValue, newMin, newMax)); else if (scaling == ScalingType.LOGARITHMIC) dstData.setElemDoubleAt(i, logScale(srcValue, origMin, newMin, origRange, newRange)); else { if (srcValue > origMax) srcValue = origMax; if (srcValue < origMin) srcValue = origMin; dstData.setElemDoubleAt(i, scale(srcValue, origMin, newMin, origRange, newRange)); } } } targetTile.setRawSamples(dstData); } catch (Exception e) { throw new OperatorException(e.getMessage()); } }