/* JAI-Ext - OpenSource Java Advanced Image Extensions Library
* http://www.geo-solutions.it/
* Copyright 2014 GeoSolutions
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package it.geosolutions.jaiext.rescale;
import it.geosolutions.jaiext.iterators.RandomIterFactory;
import it.geosolutions.jaiext.range.Range;
import java.awt.Rectangle;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.awt.image.renderable.ParameterBlock;
import java.util.Map;
import javax.media.jai.BorderExtender;
import javax.media.jai.ImageLayout;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.PointOpImage;
import javax.media.jai.ROI;
import javax.media.jai.RasterAccessor;
import javax.media.jai.RasterFormatTag;
import javax.media.jai.RenderedOp;
import javax.media.jai.iterator.RandomIter;
import com.sun.media.jai.util.ImageUtil;
/**
* This class is used for rescaling the source image pixels with the given scale and offset factors. At the instantiation time this class checks if
* the input parameters are suitable for the Rescale operation. If the image data type is Byte, the rescale operation on every pixel value is
* pre-calculated and stored inside a byte array and the rescaling is effectively a simple lookup operation. For the other data types the Rescale
* operation is performed at runtime. The rescale operation is executed for each tile independently. If input ROI or NoData values are founded, then
* they are not rescaled, but the input destination No Data value is returned.
*/
public class RescaleOpImage extends PointOpImage {
/** ROI extender */
protected final static BorderExtender ROI_EXTENDER = BorderExtender
.createInstance(BorderExtender.BORDER_ZERO);
/** Scale factors for each band */
private final double[] scaleFactors;
/** Offset factors for each band */
private final double[] offsetArray;
/** Boolean indicating if a No Data Range is used */
private final boolean hasNoData;
/** Boolean indicating if a ROI object is used */
private final boolean hasROI;
/** No Data Range */
private Range noData;
/** ROI image */
private PlanarImage srcROIImage;
/** Rectangle containing ROI bounds */
private Rectangle roiBounds;
/** Boolean indicating if a ROI RasterAccessor should be used */
private final boolean useROIAccessor;
/** Boolean lookuptable used if no data are present */
private boolean[] booleanLookupTable;
/** Boolean indicating that there No Data and ROI are not used */
private final boolean caseA;
/** Boolean indicating that only ROI is used */
private final boolean caseB;
/** Boolean indicating that only No Data are used */
private final boolean caseC;
/** Precalculated rescale lookup table for fast computations */
private byte[][] byteRescaleTable = null;
/** Destination value for No Data byte */
private byte destinationNoDataByte;
/** Destination value for No Data ushort/short */
private short destinationNoDataShort;
/** Destination value for No Data int */
private int destinationNoDataInt;
/** Destination value for No Data float */
private float destinationNoDataFloat;
/** Destination value for No Data double */
private double destinationNoDataDouble;
/** Extended ROI image */
private RenderedOp srcROIImgExt;
public RescaleOpImage(RenderedImage source, ImageLayout layout, Map configuration,
double[] valueScale, double[] valueOffsets, double destinationNoData, ROI roi,
Range noData, boolean useROIAccessor) {
super(source, layout, configuration, true);
// Selection of the band number
int numBands = getSampleModel().getNumBands();
// Check if the constants number is equal to the band number
// If they are not equal the first constant is used for all bands
if (valueScale.length < numBands && valueScale.length >= 1) {
this.scaleFactors = new double[numBands];
for (int i = 0; i < numBands; i++) {
this.scaleFactors[i] = valueScale[0];
}
} else if (valueScale.length < 1) {
// In this case an exception is thrown
throw new IllegalArgumentException(
"Input Scale factor array should have almost dimension 1");
} else {
// Else the constants are copied
this.scaleFactors = valueScale;
}
// Check if the offsets number is equal to the band number
// If they are not equal the first offset is used for all bands
if (valueOffsets.length < numBands && valueOffsets.length >= 1) {
this.offsetArray = new double[numBands];
for (int i = 0; i < numBands; i++) {
this.offsetArray[i] = valueOffsets[0];
}
} else if (valueOffsets.length < 1) {
// In this case an exception is thrown
throw new IllegalArgumentException("Input offset array should have almost dimension 1");
} else {
// Else the offsets are copied
this.offsetArray = valueOffsets;
}
// Set flag to permit in-place operation.
permitInPlaceOperation();
// Check if No Data control must be done
if (noData != null) {
hasNoData = true;
this.noData = noData;
} else {
hasNoData = false;
}
// Check if ROI control must be done
if (roi != null) {
hasROI = true;
// Roi object
ROI srcROI = roi;
// Creation of a PlanarImage containing the ROI data
srcROIImage = srcROI.getAsImage();
// Source Bounds
Rectangle srcRect = new Rectangle(source.getMinX(), source.getMinY(),
source.getWidth(), source.getHeight());
// Padding of the input ROI image in order to avoid the call of the getExtendedData() method
// ROI bounds are saved
roiBounds = srcROIImage.getBounds();
int deltaX0 = (roiBounds.x - srcRect.x);
int leftP = deltaX0 > 0 ? deltaX0 : 0;
int deltaY0 = (roiBounds.y - srcRect.y);
int topP = deltaY0 > 0 ? deltaY0 : 0;
int deltaX1 = (srcRect.x + srcRect.width - roiBounds.x + roiBounds.width);
int rightP = deltaX1 > 0 ? deltaX1 : 0;
int deltaY1 = (srcRect.y + srcRect.height - roiBounds.y + roiBounds.height);
int bottomP = deltaY1 > 0 ? deltaY1 : 0;
// Extend the ROI image
ParameterBlock pb = new ParameterBlock();
pb.setSource(srcROIImage, 0);
pb.set(leftP, 0);
pb.set(rightP, 1);
pb.set(topP, 2);
pb.set(bottomP, 3);
pb.set(ROI_EXTENDER, 4);
srcROIImgExt = JAI.create("border", pb);
// The useRoiAccessor parameter is set
this.useROIAccessor = useROIAccessor;
} else {
hasROI = false;
this.useROIAccessor = false;
roiBounds = null;
srcROIImage = null;
}
// Image dataType
int dataType = getSampleModel().getDataType();
// Boolean indicating if the image data type is byte
boolean isByte = dataType == DataBuffer.TYPE_BYTE;
// Creation of a lookuptable containing the values to use for no data
if (hasNoData && isByte) {
booleanLookupTable = new boolean[256];
for (int i = 0; i < booleanLookupTable.length; i++) {
byte value = (byte) i;
booleanLookupTable[i] = !noData.contains(value);
}
}
if (isByte) {
byteRescaleTable = new byte[numBands][256];
// Initialize table which implements Rescale and clamping
for (int b = 0; b < numBands; b++) {
byte[] band = byteRescaleTable[b];
double c = scaleFactors[b];
double o = offsetArray[b];
for (int i = 0; i < 256; i++) {
band[i] = ImageUtil.clampRoundByte(i * c + o);
}
}
}
// Definition of the possible cases that can be found
// caseA = no ROI nor No Data
// caseB = ROI present but No Data not present
// caseC = No Data present but ROI not present
// Last case not defined = both ROI and No Data are present
caseA = !hasNoData && !hasROI;
caseB = !hasNoData && hasROI;
caseC = hasNoData && !hasROI;
// DestinationNoData setting
switch (dataType) {
case DataBuffer.TYPE_BYTE:
destinationNoDataByte = ImageUtil.clampRoundByte(destinationNoData);
break;
case DataBuffer.TYPE_USHORT:
destinationNoDataShort = ImageUtil.clampRoundUShort(destinationNoData);
break;
case DataBuffer.TYPE_SHORT:
destinationNoDataShort = ImageUtil.clampRoundShort(destinationNoData);
break;
case DataBuffer.TYPE_INT:
destinationNoDataInt = ImageUtil.clampRoundInt(destinationNoData);
break;
case DataBuffer.TYPE_FLOAT:
destinationNoDataFloat = (float) destinationNoData;
break;
case DataBuffer.TYPE_DOUBLE:
destinationNoDataDouble = destinationNoData;
break;
default:
throw new IllegalArgumentException("Wrong data type");
}
}
/**
* Rescales to the pixel values within a specified rectangle.
*
* @param sources Cobbled sources, guaranteed to provide all the source data necessary for computing the rectangle.
* @param dest The tile containing the rectangle to be computed.
* @param destRect The rectangle within the tile to be computed.
*/
protected void computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect) {
Raster tile = sources[0];
// Retrieve format tags.
RasterFormatTag[] formatTags = getFormatTags();
Rectangle srcRect = mapDestRect(destRect, 0);
RasterAccessor srcAccessor = new RasterAccessor(tile, srcRect, formatTags[0],
getSourceImage(0).getColorModel());
RasterAccessor destAccessor = new RasterAccessor(dest, destRect, formatTags[1],
getColorModel());
// ROI calculations if roiAccessor is used
RasterAccessor roiAccessor = null;
RandomIter roiIter = null;
if (useROIAccessor) {
// Note that the getExtendedData() method is not called because the input images are padded.
// For each image there is a check if the rectangle is contained inside the source image;
// if this not happen, the data is taken from the padded image.
Raster roiRaster = null;
if (roiBounds.contains(srcRect)) {
roiRaster = srcROIImage.getData(srcRect);
} else {
roiRaster = srcROIImgExt.getData(srcRect);
}
// creation of the rasterAccessor
roiAccessor = new RasterAccessor(roiRaster, srcRect, RasterAccessor.findCompatibleTags(
new RenderedImage[] { srcROIImage }, srcROIImage)[0],
srcROIImage.getColorModel());
} else if(hasROI) {
roiIter = RandomIterFactory.create(srcROIImage, srcROIImage.getBounds(), true, true);
}
int dataType = destAccessor.getDataType();
switch (dataType) {
case DataBuffer.TYPE_BYTE:
byteLoop(srcAccessor, destAccessor, roiAccessor, roiIter);
break;
case DataBuffer.TYPE_USHORT:
ushortLoop(srcAccessor, destAccessor, roiAccessor, roiIter);
break;
case DataBuffer.TYPE_SHORT:
shortLoop(srcAccessor, destAccessor, roiAccessor, roiIter);
break;
case DataBuffer.TYPE_INT:
intLoop(srcAccessor, destAccessor, roiAccessor, roiIter);
break;
case DataBuffer.TYPE_FLOAT:
floatLoop(srcAccessor, destAccessor, roiAccessor, roiIter);
break;
case DataBuffer.TYPE_DOUBLE:
doubleLoop(srcAccessor, destAccessor, roiAccessor, roiIter);
break;
default:
throw new IllegalArgumentException("Wrong data type");
}
if (destAccessor.needsClamping()) {
/* Further clamp down to underlying raster data type. */
destAccessor.clampDataArrays();
}
destAccessor.copyDataToRaster();
}
private void byteLoop(RasterAccessor src, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
// Setup of the initial parameters
int dstWidth = dst.getWidth();
int dstHeight = dst.getHeight();
int dstBands = dst.getNumBands();
int dstLineStride = dst.getScanlineStride();
int dstPixelStride = dst.getPixelStride();
int[] dstBandOffsets = dst.getBandOffsets();
byte[][] dstData = dst.getByteDataArrays();
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
byte[][] srcData = src.getByteDataArrays();
int srcX = src.getX();
int srcY = src.getY();
final byte[] roiDataArray;
final int roiLineStride;
final int roiDataLength;
// If ROI RasterAccessor is used, some parameters must be set
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiLineStride = 0;
roiDataLength = 0;
}
// NO ROI NO NODATA
if (caseA) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Selection of the rescale table already created for the selected band
byte[] clamp = byteRescaleTable[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Rescale operation
dstData[b][dstPixelOffset] = clamp[srcData[b][srcPixelOffset] & 0xFF];
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI WITHOUT NODATA
} else if (caseB) {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Rescale operation
byte[] clamp = byteRescaleTable[b];
dstData[b][dstPixelOffset + dstBandOffsets[b]] = clamp[srcData[b][srcPixelOffset
+ srcBandOffsets[b]] & 0xFF];
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataByte;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Rescale operation
byte[] clamp = byteRescaleTable[b];
dstData[b][dstPixelOffset + dstBandOffsets[b]] = clamp[srcData[b][srcPixelOffset
+ srcBandOffsets[b]] & 0xFF];
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataByte;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataByte;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
// NODATA WITHOUT ROI
} else if (caseC) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Selection of the rescale table already created for the selected band
byte[] clamp = byteRescaleTable[b];
// Selection of the input band array
byte[] bandDataIn = srcData[b];
// Selection of the output band array
byte[] bandDataOut = dstData[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Selection of the value to calculate
int value = bandDataIn[srcPixelOffset] & 0xFF;
// Check if the value is not a NoData
if (booleanLookupTable[value]) {
// Rescale operation
bandDataOut[dstPixelOffset] = clamp[value];
} else {
// Else, destination No Data is set
bandDataOut[dstPixelOffset] = destinationNoDataByte;
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI AND NODATA
} else {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
int value = srcData[b][srcPixelOffset + srcBandOffsets[b]] & 0xFF;
// Check if the value is not a NoData
if (booleanLookupTable[value]) {
// Rescale operation
byte[] clamp = byteRescaleTable[b];
dstData[b][dstPixelOffset + dstBandOffsets[b]] = clamp[value];
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataByte;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataByte;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
int value = srcData[b][srcPixelOffset + srcBandOffsets[b]] & 0xFF;
// Check if the value is not a NoData
if (booleanLookupTable[value]) {
// Rescale operation
byte[] clamp = byteRescaleTable[b];
dstData[b][dstPixelOffset + dstBandOffsets[b]] = clamp[value];
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataByte;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataByte;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataByte;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
}
}
private void ushortLoop(RasterAccessor src, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
// Setup of the initial parameters
int dstWidth = dst.getWidth();
int dstHeight = dst.getHeight();
int dstBands = dst.getNumBands();
int dstLineStride = dst.getScanlineStride();
int dstPixelStride = dst.getPixelStride();
int[] dstBandOffsets = dst.getBandOffsets();
short[][] dstData = dst.getShortDataArrays();
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
short[][] srcData = src.getShortDataArrays();
int srcX = src.getX();
int srcY = src.getY();
final byte[] roiDataArray;
final int roiLineStride;
final int roiDataLength;
// If ROI RasterAccessor is used, some parameters must be set
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiLineStride = 0;
roiDataLength = 0;
}
// NO ROI NO NODATA
if (caseA) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Rescale operation
dstData[b][dstPixelOffset] = ImageUtil
.clampRoundUShort((srcData[b][srcPixelOffset] & 0xFFFF) * scale
+ offset);
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI WITHOUT NODATA
} else if (caseB) {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundUShort((srcData[b][srcPixelOffset
+ srcBandOffsets[b]] & 0xFFFF)
* scale + offset);
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundUShort((srcData[b][srcPixelOffset
+ srcBandOffsets[b]] & 0xFFFF)
* scale + offset);
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
// NODATA WITHOUT ROI
} else if (caseC) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Selection of the input band array
short[] bandDataIn = srcData[b];
// Selection of the output band array
short[] bandDataOut = dstData[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Selection of the value to calculate
short value = bandDataIn[srcPixelOffset];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
bandDataOut[dstPixelOffset] = ImageUtil
.clampRoundUShort((value & 0xFFFF) * scale + offset);
} else {
// Else, destination No Data is set
bandDataOut[dstPixelOffset] = destinationNoDataShort;
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI AND NODATA
} else {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
short value = srcData[b][srcPixelOffset + srcBandOffsets[b]];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundUShort((value & 0xFFFF) * scale + offset);
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
short value = srcData[b][srcPixelOffset + srcBandOffsets[b]];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundUShort((value & 0xFFFF) * scale + offset);
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
}
}
private void shortLoop(RasterAccessor src, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
// Setup of the initial parameters
int dstWidth = dst.getWidth();
int dstHeight = dst.getHeight();
int dstBands = dst.getNumBands();
int dstLineStride = dst.getScanlineStride();
int dstPixelStride = dst.getPixelStride();
int[] dstBandOffsets = dst.getBandOffsets();
short[][] dstData = dst.getShortDataArrays();
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
short[][] srcData = src.getShortDataArrays();
int srcX = src.getX();
int srcY = src.getY();
final byte[] roiDataArray;
final int roiLineStride;
final int roiDataLength;
// If ROI RasterAccessor is used, some parameters must be set
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiLineStride = 0;
roiDataLength = 0;
}
// NO ROI NO NODATA
if (caseA) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Rescale operation
dstData[b][dstPixelOffset] = ImageUtil
.clampRoundShort((srcData[b][srcPixelOffset]) * scale + offset);
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI WITHOUT NODATA
} else if (caseB) {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundShort((srcData[b][srcPixelOffset
+ srcBandOffsets[b]])
* scale + offset);
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundShort((srcData[b][srcPixelOffset
+ srcBandOffsets[b]])
* scale + offset);
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
// NODATA WITHOUT ROI
} else if (caseC) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Selection of the input band array
short[] bandDataIn = srcData[b];
// Selection of the output band array
short[] bandDataOut = dstData[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Selection of the value to calculate
short value = bandDataIn[srcPixelOffset];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
bandDataOut[dstPixelOffset] = ImageUtil.clampRoundShort((value) * scale
+ offset);
} else {
// Else, destination No Data is set
bandDataOut[dstPixelOffset] = destinationNoDataShort;
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI AND NODATA
} else {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
short value = srcData[b][srcPixelOffset + srcBandOffsets[b]];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundShort((value) * scale + offset);
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
short value = srcData[b][srcPixelOffset + srcBandOffsets[b]];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundShort((value) * scale + offset);
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataShort;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
}
}
private void intLoop(RasterAccessor src, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
// Setup of the initial parameters
int dstWidth = dst.getWidth();
int dstHeight = dst.getHeight();
int dstBands = dst.getNumBands();
int dstLineStride = dst.getScanlineStride();
int dstPixelStride = dst.getPixelStride();
int[] dstBandOffsets = dst.getBandOffsets();
int[][] dstData = dst.getIntDataArrays();
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
int[][] srcData = src.getIntDataArrays();
int srcX = src.getX();
int srcY = src.getY();
final byte[] roiDataArray;
final int roiLineStride;
final int roiDataLength;
// If ROI RasterAccessor is used, some parameters must be set
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiLineStride = 0;
roiDataLength = 0;
}
// NO ROI NO NODATA
if (caseA) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Rescale operation
dstData[b][dstPixelOffset] = ImageUtil
.clampRoundInt((srcData[b][srcPixelOffset]) * scale + offset);
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI WITHOUT NODATA
} else if (caseB) {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundInt((srcData[b][srcPixelOffset
+ srcBandOffsets[b]])
* scale + offset);
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataInt;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundInt((srcData[b][srcPixelOffset
+ srcBandOffsets[b]])
* scale + offset);
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataInt;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataInt;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
// NODATA WITHOUT ROI
} else if (caseC) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Selection of the input band array
int[] bandDataIn = srcData[b];
// Selection of the output band array
int[] bandDataOut = dstData[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Selection of the value to calculate
int value = bandDataIn[srcPixelOffset];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
bandDataOut[dstPixelOffset] = ImageUtil.clampRoundInt((value) * scale
+ offset);
} else {
// Else, destination No Data is set
bandDataOut[dstPixelOffset] = destinationNoDataInt;
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI AND NODATA
} else {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
int value = srcData[b][srcPixelOffset + srcBandOffsets[b]];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundInt((value) * scale + offset);
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataInt;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataInt;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
int value = srcData[b][srcPixelOffset + srcBandOffsets[b]];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = ImageUtil
.clampRoundInt((value) * scale + offset);
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataInt;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataInt;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataInt;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
}
}
private void floatLoop(RasterAccessor src, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
// Setup of the initial parameters
int dstWidth = dst.getWidth();
int dstHeight = dst.getHeight();
int dstBands = dst.getNumBands();
int dstLineStride = dst.getScanlineStride();
int dstPixelStride = dst.getPixelStride();
int[] dstBandOffsets = dst.getBandOffsets();
float[][] dstData = dst.getFloatDataArrays();
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
float[][] srcData = src.getFloatDataArrays();
int srcX = src.getX();
int srcY = src.getY();
final byte[] roiDataArray;
final int roiLineStride;
final int roiDataLength;
// If ROI RasterAccessor is used, some parameters must be set
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiLineStride = 0;
roiDataLength = 0;
}
// NO ROI NO NODATA
if (caseA) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Rescale operation
dstData[b][dstPixelOffset] = (float) ((srcData[b][srcPixelOffset]) * scale + offset);
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI WITHOUT NODATA
} else if (caseB) {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = (float) ((srcData[b][srcPixelOffset
+ srcBandOffsets[b]])
* scale + offset);
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataFloat;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = (float) ((srcData[b][srcPixelOffset
+ srcBandOffsets[b]])
* scale + offset);
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataFloat;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataFloat;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
// NODATA WITHOUT ROI
} else if (caseC) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Selection of the input band array
float[] bandDataIn = srcData[b];
// Selection of the output band array
float[] bandDataOut = dstData[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Selection of the value to calculate
float value = bandDataIn[srcPixelOffset];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
bandDataOut[dstPixelOffset] = (float) (value * scale + offset);
} else {
// Else, destination No Data is set
bandDataOut[dstPixelOffset] = destinationNoDataFloat;
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI AND NODATA
} else {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
float value = srcData[b][srcPixelOffset + srcBandOffsets[b]];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = (float) (value
* scale + offset);
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataFloat;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataFloat;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
float value = srcData[b][srcPixelOffset + srcBandOffsets[b]];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = (float) (value
* scale + offset);
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataFloat;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataFloat;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataFloat;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
}
}
private void doubleLoop(RasterAccessor src, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
// Setup of the initial parameters
int dstWidth = dst.getWidth();
int dstHeight = dst.getHeight();
int dstBands = dst.getNumBands();
int dstLineStride = dst.getScanlineStride();
int dstPixelStride = dst.getPixelStride();
int[] dstBandOffsets = dst.getBandOffsets();
double[][] dstData = dst.getDoubleDataArrays();
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
double[][] srcData = src.getDoubleDataArrays();
int srcX = src.getX();
int srcY = src.getY();
final byte[] roiDataArray;
final int roiLineStride;
final int roiDataLength;
// If ROI RasterAccessor is used, some parameters must be set
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiLineStride = roi.getScanlineStride();
roiDataLength = roiDataArray.length;
} else {
roiDataArray = null;
roiLineStride = 0;
roiDataLength = 0;
}
// NO ROI NO NODATA
if (caseA) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Rescale operation
dstData[b][dstPixelOffset] = (srcData[b][srcPixelOffset]) * scale + offset;
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI WITHOUT NODATA
} else if (caseB) {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = (srcData[b][srcPixelOffset
+ srcBandOffsets[b]])
* scale + offset;
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataDouble;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = (srcData[b][srcPixelOffset
+ srcBandOffsets[b]])
* scale + offset;
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataDouble;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataDouble;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
// NODATA WITHOUT ROI
} else if (caseC) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// creation of the line offsets
int dstLineOffset = dstBandOffsets[b];
int srcLineOffset = srcBandOffsets[b];
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstLineOffset;
int srcPixelOffset = srcLineOffset;
// update of the line offsets
dstLineOffset += dstLineStride;
srcLineOffset += srcLineStride;
// Selection of the input band array
double[] bandDataIn = srcData[b];
// Selection of the output band array
double[] bandDataOut = dstData[b];
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// Selection of the value to calculate
double value = bandDataIn[srcPixelOffset];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
bandDataOut[dstPixelOffset] = (value * scale) + offset;
} else {
// Else, destination No Data is set
bandDataOut[dstPixelOffset] = destinationNoDataDouble;
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
}
}
// ROI AND NODATA
} else {
// ROI RASTERACCESSOR USED
if (useROIAccessor) {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Selection of the y position in the ROI array
int posyROI = y * roiLineStride;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// ROI index position
int windex = x + posyROI;
// ROI value
int w = windex < roiDataLength ? roiDataArray[windex] & 0xff : 0;
// If the value is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
double value = srcData[b][srcPixelOffset + srcBandOffsets[b]];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = (value * scale)
+ offset;
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataDouble;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataDouble;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
// ROI RASTERACCESSOR NOT USED
} else {
// Initial offsets
int dstOffset = 0;
int srcOffset = 0;
// Cycle on the y-axis
for (int y = 0; y < dstHeight; y++) {
// creation of the pixel offsets
int dstPixelOffset = dstOffset;
int srcPixelOffset = srcOffset;
// Cycle on the x-axis
for (int x = 0; x < dstWidth; x++) {
// PixelPositions
int x0 = srcX + x;
int y0 = srcY + y;
// Check if the pixel is inside ROI
if (roiBounds.contains(x0, y0)) {
// ROI value
int w = roiIter.getSample(x0, y0, 0);
// If the pixel is inside the ROI, then the Rescale operation is executed, else
// destination No Data is returned
if (w != 0) {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
// Selection of the value to calculate
double value = srcData[b][srcPixelOffset + srcBandOffsets[b]];
// Check if the value is not a NoData
if (!noData.contains(value)) {
// Rescale operation
// Selection of the rescale parameters
double scale = scaleFactors[b];
double offset = offsetArray[b];
// Rescale operation
dstData[b][dstPixelOffset + dstBandOffsets[b]] = (value * scale)
+ offset;
} else {
// Else, destination No Data is set
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataDouble;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataDouble;
}
}
} else {
// Cycle on all the bands
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destinationNoDataDouble;
}
}
// update of the pixel offsets
dstPixelOffset += dstPixelStride;
srcPixelOffset += srcPixelStride;
}
// update of the initial offsets
dstOffset += dstLineStride;
srcOffset += srcLineStride;
}
}
}
}
@Override
public synchronized void dispose() {
if(srcROIImgExt != null) {
srcROIImgExt.dispose();
}
super.dispose();
}
}