/* 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.algebra;
import it.geosolutions.jaiext.algebra.AlgebraDescriptor.Operator;
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.SampleModel;
import java.awt.image.WritableRaster;
import javax.media.jai.ImageLayout;
import javax.media.jai.PointOpImage;
import javax.media.jai.ROI;
import javax.media.jai.RasterAccessor;
import javax.media.jai.RasterFormatTag;
import javax.media.jai.RasterFactory;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Logger;
import com.sun.media.jai.util.ImageUtil;
import com.sun.media.jai.util.JDKWorkarounds;
/**
* An <code>OpImage</code> implementing any operation defined by the {@link Operator} enum on an image array.
*
* <p>
* This <code>OpImage</code> executes the operation on the pixel values of N source images on a per-band basis. In case the N source images have different number of
* bands, the number of bands for the destination image is the smaller band number of the N source images. That is
* <code>dstNumBands = Math.min(src1NumBands, src2NumBands,...)</code>. In case the source images have different data types, the data type
* for the destination image is the bigger data type of the two source images.
*
* <p>
* The value of the pixel (x, y) in the destination image is defined as:
*
* <pre>
* for (b = 0; b < numBands; b++) {
* dst[y][x][b] = op.calculate(src1[y][x][b],src2[y][x][b]);
* }
* </pre>
*
* <p>
* If the result of the operation overflows/underflows the maximum/minimum value supported by the destination image, then it will be clamped to the
* maximum/minimum value respectively. The data type <code>byte</code> is treated as unsigned, with maximum value as 255 and minimum value as 0.
*
*
*/
public class AlgebraOpImage extends PointOpImage {
private final static Logger LOGGER = Logger.getLogger(AlgebraOpImage.class.toString());
private final boolean hasNoData;
private Range noData;
private byte[] byteLookupTable;
private boolean[] booleanLookupTable;
private final boolean hasROI;
private ROI roi;
private final boolean caseA;
private final boolean caseB;
private final boolean caseC;
private Operator op;
private final int numSrc;
private byte destNoDataByte;
private short destNoDataShort;
private int destNoDataInt;
private float destNoDataFloat;
private double destNoDataDouble;
private byte nullValueByte;
private short nullValueShort;
private int nullValueInt;
private float nullValueFloat;
private double nullValueDouble;
private final int numTotalSrc;
/**
* Constructs an <code>AlgebraOpImage</code>.
*
* <p>
* The <code>layout</code> parameter may optionally contains the tile grid layout, sample model, and/or color model. The image dimension is
* determined by the intersection of the bounding boxes of the two source images.
*
* <p>
* The image layout of the first source image, <code>source1</code>, is used as the fall-back for the image layout of the destination image. Any
* layout parameters not specified in the <code>layout</code> argument are set to the same value as that of <code>source1</code>.
*
* @param config the hints
* @param layout The destination image layout.
* @param op Operation selected
* @param srcROI ROI used for reducing computation Area
* @param noData NoData Range used for checking noData
* @param destinationNoData value for replacing the source nodata values
* @param sources Array of Sources
*/
public AlgebraOpImage(Map config, ImageLayout layout, Operator op, ROI srcROI, Range noData,
double destinationNoData, RenderedImage... sources) {
super(vectorize(sources), layout, config, true);
if (op == null) {
throw new IllegalArgumentException("Operation Not Defined");
} else {
this.op = op;
}
// Get the source band counts.
int numSrc = sources.length;
// Check the number of sources
if (!op.supportsMultipleValues() && numSrc > 1) {
LOGGER.warning("Multiple sources found, only the first one will be used");
numSrc = 1;
}
this.numSrc = numSrc;
this.numTotalSrc = sources.length;
// DataType check
int srcDataType = sources[0].getSampleModel().getDataType();
int dataType = getSampleModel().getDataType();
// for (RenderedImage img : sources) {
// if (img.getSampleModel().getDataType() != srcDataType) {
// throw new IllegalArgumentException("Images must have the same data type");
// }
// }
// DataType check for the operation
if(!op.isDataTypeSupported(srcDataType)){
throw new IllegalArgumentException("This operation does not support DataType: " + srcDataType);
}
int[] numBandsSrc = new int[numSrc];
boolean srcBandsToFill = false;
int numBands0 = sources[0].getSampleModel().getNumBands();
for (int i = 1; i < numSrc; i++) {
numBandsSrc[i] = sources[i].getSampleModel().getNumBands();
if (numBandsSrc[i] != numBands0) {
srcBandsToFill = true;
break;
}
}
// Handle the special case of adding a single band image to
// each band of a multi-band image.
int numBandsDst;
if (layout != null && layout.isValid(ImageLayout.SAMPLE_MODEL_MASK)) {
SampleModel sm = layout.getSampleModel(null);
numBandsDst = sm.getNumBands();
// One of the sources must be single-banded and the other must
// have at most the number of bands in the SampleModel hint.
if (numBandsDst > 1 && srcBandsToFill) {
// Clamp the destination band count to the number of
// bands in the multi-band source.
int minBandsNum = Integer.MAX_VALUE;
for (int i = 0; i < numSrc; i++) {
int bands = numBandsSrc[i];
if (bands < minBandsNum) {
minBandsNum = bands;
}
}
numBandsDst = Math.min(minBandsNum, numBandsDst);
// Create a new SampleModel if necessary.
if (numBandsDst != sampleModel.getNumBands()) {
sampleModel = RasterFactory.createComponentSampleModel(sm,
sampleModel.getTransferType(), sampleModel.getWidth(),
sampleModel.getHeight(), numBandsDst);
if (colorModel != null
&& !JDKWorkarounds.areCompatibleDataModels(sampleModel, colorModel)) {
colorModel = ImageUtil.getCompatibleColorModel(sampleModel, config);
}
}
}
}
// Destination No Data value is clamped to the image data type
switch (dataType) {
case DataBuffer.TYPE_BYTE:
this.destNoDataByte = ImageUtil.clampRoundByte(destinationNoData);
this.nullValueByte = ImageUtil.clampRoundByte(op.getNullValue());
break;
case DataBuffer.TYPE_USHORT:
this.destNoDataShort = ImageUtil.clampRoundUShort(destinationNoData);
this.nullValueShort = ImageUtil.clampRoundUShort(op.getNullValue());
break;
case DataBuffer.TYPE_SHORT:
this.destNoDataShort = ImageUtil.clampRoundShort(destinationNoData);
this.nullValueShort = ImageUtil.clampRoundShort(op.getNullValue());
break;
case DataBuffer.TYPE_INT:
this.destNoDataInt = ImageUtil.clampRoundInt(destinationNoData);
this.nullValueInt = ImageUtil.clampRoundInt(op.getNullValue());
break;
case DataBuffer.TYPE_FLOAT:
this.destNoDataFloat = ImageUtil.clampFloat(destinationNoData);
this.nullValueFloat = ImageUtil.clampFloat(op.getNullValue());
break;
case DataBuffer.TYPE_DOUBLE:
this.destNoDataDouble = destinationNoData;
this.nullValueDouble = op.getNullValue();
break;
default:
throw new IllegalArgumentException("Wrong image data type");
}
// Check if No Data control must be done
if (noData != null) {
hasNoData = true;
this.noData = noData;
// Creation of a lookuptable containing the values to use for no data
if (dataType == DataBuffer.TYPE_BYTE) {
booleanLookupTable = new boolean[256];
byteLookupTable = new byte[256];
for (int i = 0; i < byteLookupTable.length; i++) {
byte value = (byte) i;
booleanLookupTable[i] = !noData.contains(value);
if (booleanLookupTable[i]) {
byteLookupTable[i] = value;
} else {
byteLookupTable[i] = nullValueByte;
}
}
}
} else {
hasNoData = false;
}
// Check if ROI control must be done
if (srcROI != null) {
hasROI = true;
// Roi object
roi = srcROI;
} else {
hasROI = false;
roi = null;
}
// 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;
// Set flag to permit in-place operation.
permitInPlaceOperation();
}
/**
* Computes the final pixel from N source images 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) {
if (!hasROI || (hasROI && roi.intersects(destRect))) {
// Retrieve format tags.
RasterFormatTag[] formatTags = getFormatTags();
RasterAccessor[] rasterArray = new RasterAccessor[numSrc];
for (int i = 0; i < numSrc; i++) {
rasterArray[i] = new RasterAccessor(sources[i], destRect, formatTags[i],
getSourceImage(i).getColorModel());
}
RasterAccessor d = new RasterAccessor(dest, destRect, formatTags[numTotalSrc],
getColorModel());
switch (d.getDataType()) {
case DataBuffer.TYPE_BYTE:
computeRectByte(rasterArray, d);
break;
case DataBuffer.TYPE_USHORT:
computeRectUShort(rasterArray, d);
break;
case DataBuffer.TYPE_SHORT:
computeRectShort(rasterArray, d);
break;
case DataBuffer.TYPE_INT:
computeRectInt(rasterArray, d);
break;
case DataBuffer.TYPE_FLOAT:
computeRectFloat(rasterArray, d);
break;
case DataBuffer.TYPE_DOUBLE:
computeRectDouble(rasterArray, d);
break;
}
if (d.needsClamping()) {
d.clampDataArrays();
}
d.copyDataToRaster();
} else {
int numBands = dest.getNumBands();
int destDataType = dest.getSampleModel().getDataType();
double[] destNoData = new double[numBands];
for (int i = 0; i < numBands; i++) {
switch (destDataType) {
case DataBuffer.TYPE_BYTE:
destNoData[i] = destNoDataByte;
break;
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
destNoData[i] = destNoDataShort;
break;
case DataBuffer.TYPE_INT:
destNoData[i] = destNoDataInt;
break;
case DataBuffer.TYPE_FLOAT:
destNoData[i] = destNoDataFloat;
break;
case DataBuffer.TYPE_DOUBLE:
destNoData[i] = destNoDataDouble;
break;
}
}
ImageUtil.fillBackground(dest, destRect, destNoData);
}
}
private void computeRectByte(RasterAccessor[] rasterArray, RasterAccessor dst) {
int[] srcLineStride = new int[numSrc];
int[] srcPixelStride = new int[numSrc];
int[][] srcBandOffsets = new int[numSrc][];
int[] srcLineOffset = new int[numSrc];
int[] srcPixelOffset = new int[numSrc];
for (int i = 0; i < numSrc; i++) {
srcLineStride[i] = rasterArray[i].getScanlineStride();
srcPixelStride[i] = rasterArray[i].getPixelStride();
srcBandOffsets[i] = rasterArray[i].getBandOffsets();
}
int result = 0;
int inputData = 0;
int dwidth = dst.getWidth();
int dheight = dst.getHeight();
int bands = dst.getNumBands();
int dLineStride = dst.getScanlineStride();
int dPixelStride = dst.getPixelStride();
int[] dBandOffsets = dst.getBandOffsets();
byte[][] dData = dst.getByteDataArrays();
byte[][] srcData = new byte[numSrc][];
byte[] d;
int x0 = 0;
int y0 = 0;
int srcX = rasterArray[0].getX();
int srcY = rasterArray[0].getY();
if (caseA) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getByteDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
result = op.calculate(srcData[0][srcPixelOffset[0]]) & 0xFF;
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]] & 0xFF;
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
//
// The next two lines are a fast way to do
// an operation with saturation on U8 elements.
// It eliminates the need to do clamping.
//
// result = op.calculate(inputData);
d[dPixelOffset] = (byte) ((((result << 23) >> 31) | result) & 0xFF);
dPixelOffset += dPixelStride;
}
}
}
} else if (caseB) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getByteDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
d[dPixelOffset] = destNoDataByte;
dPixelOffset += dPixelStride;
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
continue;
}
result = op.calculate(srcData[0][srcPixelOffset[0]]) & 0xFF;
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]] & 0xFF;
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
//
// The next two lines are a fast way to do
// an operation with saturation on U8 elements.
// It eliminates the need to do clamping.
//
// result = op.calculate(inputData);
d[dPixelOffset] = (byte) ((((result << 23) >> 31) | result) & 0xFF);
dPixelOffset += dPixelStride;
}
}
}
} else if (caseC) {
int sourceValue = 0;
boolean isValidData = false;
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getByteDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
sourceValue = srcData[0][srcPixelOffset[0]] & 0xFF;
result = byteLookupTable[sourceValue] & 0xFF;
isValidData |= booleanLookupTable[sourceValue];
if (isValidData) {
result = op.calculate(srcData[0][srcPixelOffset[0]]) & 0xFF;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]] & 0xFF;
isValidData |= booleanLookupTable[sourceValue];
inputData = byteLookupTable[sourceValue] & 0xFF;
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataByte;
dPixelOffset += dPixelStride;
continue;
}
//
// The next two lines are a fast way to do
// an operation with saturation on U8 elements.
// It eliminates the need to do clamping.
//
// result = op.calculate(inputData);
d[dPixelOffset] = (byte) ((((result << 23) >> 31) | result) & 0xFF);
dPixelOffset += dPixelStride;
}
}
}
} else {
int sourceValue = 0;
boolean isValidData = false;
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getByteDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
d[dPixelOffset] = destNoDataByte;
dPixelOffset += dPixelStride;
continue;
}
sourceValue = srcData[0][srcPixelOffset[0]] & 0xFF;
result = byteLookupTable[sourceValue] & 0xFF;
isValidData |= booleanLookupTable[sourceValue];
if (isValidData) {
result = op.calculate(srcData[0][srcPixelOffset[0]]) & 0xFF;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]] & 0xFF;
isValidData |= booleanLookupTable[sourceValue];
inputData = byteLookupTable[sourceValue] & 0xFF;
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataByte;
dPixelOffset += dPixelStride;
continue;
}
//
// The next two lines are a fast way to do
// an operation with saturation on U8 elements.
// It eliminates the need to do clamping.
//
// result = op.calculate(inputData);
d[dPixelOffset] = (byte) ((((result << 23) >> 31) | result) & 0xFF);
dPixelOffset += dPixelStride;
}
}
}
}
}
private void computeRectUShort(RasterAccessor[] rasterArray, RasterAccessor dst) {
int[] srcLineStride = new int[numSrc];
int[] srcPixelStride = new int[numSrc];
int[][] srcBandOffsets = new int[numSrc][];
int[] srcLineOffset = new int[numSrc];
int[] srcPixelOffset = new int[numSrc];
for (int i = 0; i < numSrc; i++) {
srcLineStride[i] = rasterArray[i].getScanlineStride();
srcPixelStride[i] = rasterArray[i].getPixelStride();
srcBandOffsets[i] = rasterArray[i].getBandOffsets();
}
int result = 0;
int inputData = 0;
int dwidth = dst.getWidth();
int dheight = dst.getHeight();
int bands = dst.getNumBands();
int dLineStride = dst.getScanlineStride();
int dPixelStride = dst.getPixelStride();
int[] dBandOffsets = dst.getBandOffsets();
short[][] dData = dst.getShortDataArrays();
short[][] srcData = new short[numSrc][];
short[] d;
int x0 = 0;
int y0 = 0;
int srcX = rasterArray[0].getX();
int srcY = rasterArray[0].getY();
short sourceValue = 0;
boolean isValidData = false;
if (caseA) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getShortDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
result = op
.calculate(op.isUshortSupported(), srcData[0][srcPixelOffset[0]]) & 0xFFFF;
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]] & 0xFFFF;
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampUShort(result);
dPixelOffset += dPixelStride;
}
}
}
} else if (caseB) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getShortDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
d[dPixelOffset] = destNoDataShort;
dPixelOffset += dPixelStride;
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
continue;
}
result = op
.calculate(op.isUshortSupported(), srcData[0][srcPixelOffset[0]]) & 0xFFFF;
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]] & 0xFFFF;
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampUShort(result);
dPixelOffset += dPixelStride;
}
}
}
} else if (caseC) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getShortDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
sourceValue = srcData[0][srcPixelOffset[0]];
if (!noData.contains(sourceValue)) {
result = op.calculate(op.isUshortSupported(),
srcData[0][srcPixelOffset[0]]) & 0xFFFF;
isValidData = true;
} else {
result = nullValueShort;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]];
if (!noData.contains(sourceValue)) {
inputData = sourceValue & 0xFFFF;
isValidData = true;
} else {
inputData = nullValueShort;
}
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataShort;
dPixelOffset += dPixelStride;
continue;
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampUShort(result);
dPixelOffset += dPixelStride;
}
}
}
} else {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getShortDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
d[dPixelOffset] = destNoDataShort;
dPixelOffset += dPixelStride;
continue;
}
sourceValue = srcData[0][srcPixelOffset[0]];
if (!noData.contains(sourceValue)) {
result = op.calculate(op.isUshortSupported(),
srcData[0][srcPixelOffset[0]]) & 0xFFFF;
isValidData = true;
} else {
result = nullValueShort;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]];
if (!noData.contains(sourceValue)) {
inputData = sourceValue & 0xFFFF;
isValidData = true;
} else {
inputData = nullValueShort;
}
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataShort;
dPixelOffset += dPixelStride;
continue;
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampUShort(result);
dPixelOffset += dPixelStride;
}
}
}
}
}
private void computeRectShort(RasterAccessor[] rasterArray, RasterAccessor dst) {
int[] srcLineStride = new int[numSrc];
int[] srcPixelStride = new int[numSrc];
int[][] srcBandOffsets = new int[numSrc][];
int[] srcLineOffset = new int[numSrc];
int[] srcPixelOffset = new int[numSrc];
for (int i = 0; i < numSrc; i++) {
srcLineStride[i] = rasterArray[i].getScanlineStride();
srcPixelStride[i] = rasterArray[i].getPixelStride();
srcBandOffsets[i] = rasterArray[i].getBandOffsets();
}
int result = 0;
short inputData = 0;
int dwidth = dst.getWidth();
int dheight = dst.getHeight();
int bands = dst.getNumBands();
int dLineStride = dst.getScanlineStride();
int dPixelStride = dst.getPixelStride();
int[] dBandOffsets = dst.getBandOffsets();
short[][] dData = dst.getShortDataArrays();
short[][] srcData = new short[numSrc][];
short[] d;
int x0 = 0;
int y0 = 0;
int srcX = rasterArray[0].getX();
int srcY = rasterArray[0].getY();
short sourceValue = 0;
boolean isValidData = false;
if (caseA) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getShortDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
result = op.calculate(false, srcData[0][srcPixelOffset[0]]);
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]];
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampShort(result);
dPixelOffset += dPixelStride;
}
}
}
} else if (caseB) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getShortDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
d[dPixelOffset] = destNoDataShort;
dPixelOffset += dPixelStride;
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
continue;
}
result = op.calculate(false, srcData[0][srcPixelOffset[0]]);
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]];
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampShort(result);
dPixelOffset += dPixelStride;
}
}
}
} else if (caseC) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getShortDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
sourceValue = srcData[0][srcPixelOffset[0]];
if (!noData.contains(sourceValue)) {
result = op.calculate(false, sourceValue);
isValidData = true;
} else {
result = nullValueShort;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]];
if (!noData.contains(sourceValue)) {
inputData = sourceValue;
isValidData = true;
} else {
inputData = nullValueShort;
}
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataShort;
dPixelOffset += dPixelStride;
continue;
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampShort(result);
dPixelOffset += dPixelStride;
}
}
}
} else {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getShortDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
d[dPixelOffset] = destNoDataShort;
dPixelOffset += dPixelStride;
continue;
}
sourceValue = srcData[0][srcPixelOffset[0]];
if (!noData.contains(sourceValue)) {
result = op.calculate(false, sourceValue);
isValidData = true;
} else {
result = nullValueShort;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]];
if (!noData.contains(sourceValue)) {
inputData = sourceValue;
isValidData = true;
} else {
inputData = nullValueShort;
}
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataShort;
dPixelOffset += dPixelStride;
continue;
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampShort(result);
dPixelOffset += dPixelStride;
}
}
}
}
}
private void computeRectInt(RasterAccessor[] rasterArray, RasterAccessor dst) {
int[] srcLineStride = new int[numSrc];
int[] srcPixelStride = new int[numSrc];
int[][] srcBandOffsets = new int[numSrc][];
int[] srcLineOffset = new int[numSrc];
int[] srcPixelOffset = new int[numSrc];
for (int i = 0; i < numSrc; i++) {
srcLineStride[i] = rasterArray[i].getScanlineStride();
srcPixelStride[i] = rasterArray[i].getPixelStride();
srcBandOffsets[i] = rasterArray[i].getBandOffsets();
}
long result = 0;
int inputData = 0;
int dwidth = dst.getWidth();
int dheight = dst.getHeight();
int bands = dst.getNumBands();
int dLineStride = dst.getScanlineStride();
int dPixelStride = dst.getPixelStride();
int[] dBandOffsets = dst.getBandOffsets();
int[][] dData = dst.getIntDataArrays();
int[][] srcData = new int[numSrc][];
int[] d;
int x0 = 0;
int y0 = 0;
int srcX = rasterArray[0].getX();
int srcY = rasterArray[0].getY();
int sourceValue = 0;
boolean isValidData = false;
if (caseA) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getIntDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
result = op.calculate(srcData[0][srcPixelOffset[0]]);
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]];
result = op.calculateL(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampInt(result);
dPixelOffset += dPixelStride;
}
}
}
} else if (caseB) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getIntDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
d[dPixelOffset] = destNoDataInt;
dPixelOffset += dPixelStride;
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
continue;
}
result = op.calculate(srcData[0][srcPixelOffset[0]]);
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]];
result = op.calculateL(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampInt(result);
dPixelOffset += dPixelStride;
}
}
}
} else if (caseC) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getIntDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
sourceValue = srcData[0][srcPixelOffset[0]];
if (!noData.contains(sourceValue)) {
result = op.calculate(sourceValue);
isValidData = true;
} else {
result = nullValueInt;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]];
if (!noData.contains(sourceValue)) {
inputData = sourceValue;
isValidData = true;
} else {
inputData = nullValueInt;
}
result = op.calculateL(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataInt;
dPixelOffset += dPixelStride;
continue;
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampInt(result);
dPixelOffset += dPixelStride;
}
}
}
} else {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getIntDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
d[dPixelOffset] = destNoDataInt;
dPixelOffset += dPixelStride;
continue;
}
sourceValue = srcData[0][srcPixelOffset[0]];
if (!noData.contains(sourceValue)) {
result = op.calculate(sourceValue);
isValidData = true;
} else {
result = nullValueInt;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]];
if (!noData.contains(sourceValue)) {
inputData = sourceValue;
isValidData = true;
} else {
inputData = nullValueInt;
}
result = op.calculateL(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataInt;
dPixelOffset += dPixelStride;
continue;
}
// result = op.calculate(inputData);
d[dPixelOffset] = ImageUtil.clampInt(result);
dPixelOffset += dPixelStride;
}
}
}
}
}
private void computeRectFloat(RasterAccessor[] rasterArray, RasterAccessor dst) {
int[] srcLineStride = new int[numSrc];
int[] srcPixelStride = new int[numSrc];
int[][] srcBandOffsets = new int[numSrc][];
int[] srcLineOffset = new int[numSrc];
int[] srcPixelOffset = new int[numSrc];
for (int i = 0; i < numSrc; i++) {
srcLineStride[i] = rasterArray[i].getScanlineStride();
srcPixelStride[i] = rasterArray[i].getPixelStride();
srcBandOffsets[i] = rasterArray[i].getBandOffsets();
}
float result = 0;
float inputData = 0;
int dwidth = dst.getWidth();
int dheight = dst.getHeight();
int bands = dst.getNumBands();
int dLineStride = dst.getScanlineStride();
int dPixelStride = dst.getPixelStride();
int[] dBandOffsets = dst.getBandOffsets();
float[][] dData = dst.getFloatDataArrays();
float[][] srcData = new float[numSrc][];
float[] d;
int x0 = 0;
int y0 = 0;
int srcX = rasterArray[0].getX();
int srcY = rasterArray[0].getY();
float sourceValue = 0;
boolean isValidData = false;
if (caseA) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getFloatDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
result = op.calculate(srcData[0][srcPixelOffset[0]]);
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]];
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
// result = op.calculate(inputData);
d[dPixelOffset] = result;
dPixelOffset += dPixelStride;
}
}
}
} else if (caseB) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getFloatDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
d[dPixelOffset] = destNoDataFloat;
dPixelOffset += dPixelStride;
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
continue;
}
result = op.calculate(srcData[0][srcPixelOffset[0]]);
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]];
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
// result = op.calculate(inputData);
d[dPixelOffset] = result;
dPixelOffset += dPixelStride;
}
}
}
} else if (caseC) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getFloatDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
sourceValue = srcData[0][srcPixelOffset[0]];
if (!noData.contains(sourceValue)) {
result = op.calculate(sourceValue);
isValidData = true;
} else {
result = nullValueFloat;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]];
if (!noData.contains(sourceValue)) {
inputData = sourceValue;
isValidData = true;
} else {
inputData = nullValueFloat;
}
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataFloat;
dPixelOffset += dPixelStride;
continue;
}
// result = op.calculate(inputData);
d[dPixelOffset] = result;
dPixelOffset += dPixelStride;
}
}
}
} else {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getFloatDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
d[dPixelOffset] = destNoDataFloat;
dPixelOffset += dPixelStride;
continue;
}
sourceValue = srcData[0][srcPixelOffset[0]];
if (!noData.contains(sourceValue)) {
result = op.calculate(sourceValue);
isValidData = true;
} else {
result = nullValueFloat;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]];
if (!noData.contains(sourceValue)) {
inputData = sourceValue;
isValidData = true;
} else {
inputData = nullValueFloat;
}
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataFloat;
dPixelOffset += dPixelStride;
continue;
}
// result = op.calculate(inputData);
d[dPixelOffset] = result;
dPixelOffset += dPixelStride;
}
}
}
}
}
private void computeRectDouble(RasterAccessor[] rasterArray, RasterAccessor dst) {
int[] srcLineStride = new int[numSrc];
int[] srcPixelStride = new int[numSrc];
int[][] srcBandOffsets = new int[numSrc][];
int[] srcLineOffset = new int[numSrc];
int[] srcPixelOffset = new int[numSrc];
for (int i = 0; i < numSrc; i++) {
srcLineStride[i] = rasterArray[i].getScanlineStride();
srcPixelStride[i] = rasterArray[i].getPixelStride();
srcBandOffsets[i] = rasterArray[i].getBandOffsets();
}
double result = 0;
double inputData = 0;
int dwidth = dst.getWidth();
int dheight = dst.getHeight();
int bands = dst.getNumBands();
int dLineStride = dst.getScanlineStride();
int dPixelStride = dst.getPixelStride();
int[] dBandOffsets = dst.getBandOffsets();
double[][] dData = dst.getDoubleDataArrays();
double[][] srcData = new double[numSrc][];
double[] d;
int x0 = 0;
int y0 = 0;
int srcX = rasterArray[0].getX();
int srcY = rasterArray[0].getY();
double sourceValue = 0;
boolean isValidData = false;
if (caseA) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getDoubleDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
result = op.calculate(srcData[0][srcPixelOffset[0]]);
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]];
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
// result = op.calculate(inputData);
d[dPixelOffset] = result;
dPixelOffset += dPixelStride;
}
}
}
} else if (caseB) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getDoubleDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
d[dPixelOffset] = destNoDataDouble;
dPixelOffset += dPixelStride;
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
continue;
}
result = op.calculate(srcData[0][srcPixelOffset[0]]);
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
inputData = srcData[i][srcPixelOffset[i]];
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
// result = op.calculate(inputData);
d[dPixelOffset] = result;
dPixelOffset += dPixelStride;
}
}
}
} else if (caseC) {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getDoubleDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
sourceValue = srcData[0][srcPixelOffset[0]];
if (!noData.contains(sourceValue)) {
result = op.calculate(sourceValue);
isValidData = true;
} else {
result = nullValueDouble;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]];
if (!noData.contains(sourceValue)) {
inputData = sourceValue;
isValidData = true;
} else {
inputData = nullValueDouble;
}
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataDouble;
dPixelOffset += dPixelStride;
continue;
}
// result = op.calculate(inputData);
d[dPixelOffset] = result;
dPixelOffset += dPixelStride;
}
}
}
} else {
for (int b = 0; b < bands; b++) {
for (int i = 0; i < numSrc; i++) {
srcData[i] = rasterArray[i].getDoubleDataArray(b);
srcLineOffset[i] = srcBandOffsets[i][b];
}
d = dData[b];
int dLineOffset = dBandOffsets[b];
for (int h = 0; h < dheight; h++) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] = srcLineOffset[i];
srcLineOffset[i] += srcLineStride[i];
}
int dPixelOffset = dLineOffset;
dLineOffset += dLineStride;
for (int w = 0; w < dwidth; w++) {
isValidData = false;
x0 = srcX + w;
y0 = srcY + h;
if (!roi.contains(x0, y0)) {
for (int i = 0; i < numSrc; i++) {
srcPixelOffset[i] += srcPixelStride[i];
}
d[dPixelOffset] = destNoDataDouble;
dPixelOffset += dPixelStride;
continue;
}
sourceValue = srcData[0][srcPixelOffset[0]];
if (!noData.contains(sourceValue)) {
result = op.calculate(sourceValue);
isValidData = true;
} else {
result = nullValueDouble;
}
srcPixelOffset[0] += srcPixelStride[0];
for (int i = 1; i < numSrc; i++) {
sourceValue = srcData[i][srcPixelOffset[i]];
if (!noData.contains(sourceValue)) {
inputData = sourceValue;
isValidData = true;
} else {
inputData = nullValueDouble;
}
result = op.calculate(result, inputData);
srcPixelOffset[i] += srcPixelStride[i];
}
if (!isValidData) {
d[dPixelOffset] = destNoDataDouble;
dPixelOffset += dPixelStride;
continue;
}
// result = op.calculate(inputData);
d[dPixelOffset] = result;
dPixelOffset += dPixelStride;
}
}
}
}
}
private static Vector<RenderedImage> vectorize(RenderedImage[] sources) {
Vector<RenderedImage> vec = new Vector<RenderedImage>(sources.length);
for (RenderedImage image : sources) {
if (image != null) {
vec.add(image);
}
}
if (vec.isEmpty()) {
return null;
}
return vec;
}
}