/* JAI-Ext - OpenSource Java Advanced Image Extensions Library
* http://www.geo-solutions.it/
* Copyright 2016 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.threshold;
import it.geosolutions.jaiext.range.Range;
import java.awt.Rectangle;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.IndexColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import java.util.Arrays;
import java.util.Map;
import javax.media.jai.ImageLayout;
import javax.media.jai.PlanarImage;
import javax.media.jai.PointOpImage;
import javax.media.jai.ROI;
import javax.media.jai.ROIShape;
import javax.media.jai.RasterAccessor;
import javax.media.jai.RasterFormatTag;
import com.sun.media.jai.util.ImageUtil;
public class ThresholdOpImage extends PointOpImage {
/** The lower bound, one for each band. */
private final double[] low;
/** The upper bound, one for each band. */
private final double[] high;
/** The constant, one for each band. */
private final double[] constant;
/** List of ColorModels required for IndexColorModel support */
ColorModel colorModel;
/** Array containing all the No Data Ranges */
private Range noData;
/** Boolean indicating if ROI is present */
private final boolean hasROI;
/** ROI bounds as a Shape */
private Rectangle roiBounds;
/** Boolean indicating if No Data are present */
private final boolean hasNoData;
/** Destination No Data value used for Byte images */
private byte destNoDataByte;
/** Destination No Data value used for Short/Unsigned Short images */
private short destNoDataShort;
/** Destination No Data value used for Integer images */
private int destNoDataInt;
/** Destination No Data value used for Float images */
private float destNoDataFloat;
/** Destination No Data value used for Double images */
private double destNoDataDouble;
/** Boolean indicating if No Data and ROI are not used */
protected boolean caseA;
/** Boolean indicating if only the ROI is used */
protected boolean caseB;
/** Boolean indicating if only the No Data are used */
protected boolean caseC;
private ROI roi;
public ThresholdOpImage(RenderedImage source, Map config, Range noData, ROI roi,
double destinationNoData, ImageLayout layout, double[] low, double[] high,
double[] constant) {
super(source, layout, config, true);
// Set flag to permit in-place operation.
permitInPlaceOperation();
int numBands = source.getSampleModel().getNumBands();
// if arrays contain only one element
if (low.length == 1 && high.length == 1 && constant.length == 1) {
this.low = new double[numBands];
this.high = new double[numBands];
this.constant = new double[numBands];
for (int i = 0; i < numBands; i++) {
this.low[i] = low[0];
this.high[i] = high[0];
this.constant[i] = constant[0];
}
} else {
this.low = (double[]) low.clone();
this.high = (double[]) high.clone();
this.constant = (double[]) constant.clone();
}
colorModel = source.getColorModel();
// Destination Image data Type
int dataType = source.getSampleModel().getDataType();
// Destination No Data value is clamped to the image data type
switch (dataType) {
case DataBuffer.TYPE_BYTE:
this.destNoDataByte = ImageUtil.clampRoundByte(destinationNoData);
break;
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
this.destNoDataShort = ImageUtil.clampRoundShort(destinationNoData);
break;
case DataBuffer.TYPE_INT:
this.destNoDataInt = ImageUtil.clampRoundInt(destinationNoData);
break;
case DataBuffer.TYPE_FLOAT:
this.destNoDataFloat = ImageUtil.clampFloat(destinationNoData);
break;
case DataBuffer.TYPE_DOUBLE:
this.destNoDataDouble = destinationNoData;
break;
default:
throw new IllegalArgumentException("Wrong image data type");
}
// Check if ROI control must be done
if (roi != null) {
hasROI = true;
// ROI object
this.roi = roi;
roiBounds = roi.getBounds();
} else {
hasROI = false;
this.roi = null;
roiBounds = null;
}
// Check if No Data control must be done
if (noData != null) {
hasNoData = true;
this.noData = noData;
} else {
hasNoData = false;
}
// 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 = !hasROI && !hasNoData;
caseB = hasROI && !hasNoData;
caseC = !hasROI && hasNoData;
}
/**
* @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) {
// Destination data type
int destType = dest.getTransferType();
// ROI fields
ROI roiTile = null;
boolean roiContainsTile = false; // roi contains sources
boolean roiDisjointTile = false; // source no intersects the roi
// ROI check
if (hasROI) {
Rectangle srcRectExpanded = mapDestRect(destRect, 0);
// The tile dimension is extended for avoiding border errors
srcRectExpanded.setRect(srcRectExpanded.getMinX() - 1, srcRectExpanded.getMinY() - 1,
srcRectExpanded.getWidth() + 2, srcRectExpanded.getHeight() + 2);
roiTile = roi.intersect(new ROIShape(srcRectExpanded));
// Check if the Tile bounds intersects the roi otherwise the computation is skipped
if (!roiBounds.intersects(srcRectExpanded)) {
roiDisjointTile = true;
} else {
roiContainsTile = roiTile.contains(srcRectExpanded);
if (!roiContainsTile) {
if (!roiTile.intersects(srcRectExpanded)) {
roiDisjointTile = true;
}
}
}
}
if (!hasROI || !roiDisjointTile) {
// Loop on the image raster
RasterFormatTag[] formatTags = getFormatTags();
Rectangle srcRect = mapDestRect(destRect, 0);
RasterAccessor src = new RasterAccessor(sources[0], srcRect, formatTags[0],
getSourceImage(0).getColorModel());
RasterAccessor dst = new RasterAccessor(dest, destRect, formatTags[1], getColorModel());
switch (dst.getDataType()) {
case DataBuffer.TYPE_BYTE:
byteLoop(src, dst, roiTile, roiContainsTile);
break;
case DataBuffer.TYPE_USHORT:
ushortLoop(src, dst, roiTile, roiContainsTile);
break;
case DataBuffer.TYPE_SHORT:
shortLoop(src, dst, roiTile, roiContainsTile);
break;
case DataBuffer.TYPE_INT:
intLoop(src, dst, roiTile, roiContainsTile);
break;
case DataBuffer.TYPE_FLOAT:
floatLoop(src, dst, roiTile, roiContainsTile);
break;
case DataBuffer.TYPE_DOUBLE:
doubleLoop(src, dst, roiTile, roiContainsTile);
break;
default:
throw new RuntimeException("Wrong image data type");
}
dst.copyDataToRaster();
} else {
// Setting all as NoData
int numBands = getSampleModel().getNumBands();
double[] background = new double[numBands];
switch (destType) {
case DataBuffer.TYPE_BYTE:
Arrays.fill(background, destNoDataByte);
break;
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
Arrays.fill(background, destNoDataShort);
break;
case DataBuffer.TYPE_INT:
Arrays.fill(background, destNoDataInt);
break;
case DataBuffer.TYPE_FLOAT:
Arrays.fill(background, destNoDataFloat);
break;
case DataBuffer.TYPE_DOUBLE:
Arrays.fill(background, destNoDataDouble);
break;
default:
throw new RuntimeException("Wrong image data type");
}
ImageUtil.fillBackground(dest, destRect, background);
}
}
private void byteLoop(RasterAccessor src, RasterAccessor dst, ROI roiTile,
boolean roiContainsTile) {
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
byte[][] srcData = src.getByteDataArrays();
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 srcLineOffset = 0;
int dstLineOffset = 0;
int x0 = 0;
int y0 = 0;
int srcX = src.getX();
int srcY = src.getY();
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
byte flo = (byte) lo;
byte fhi = (byte) hi;
byte fco = (byte) co;
byte sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataByte;
}
} else {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
byte flo = (byte) lo;
byte fhi = (byte) hi;
byte fco = (byte) co;
byte sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
byte sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
byte flo = (byte) lo;
byte fhi = (byte) hi;
byte fco = (byte) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataByte;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataByte;
}
} else {
for (int b = 0; b < dstBands; b++) {
byte sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
byte flo = (byte) lo;
byte fhi = (byte) hi;
byte fco = (byte) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataByte;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
}
}
private void ushortLoop(RasterAccessor src, RasterAccessor dst, ROI roiTile,
boolean roiContainsTile) {
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
short[][] srcData = src.getShortDataArrays();
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 srcLineOffset = 0;
int dstLineOffset = 0;
int x0 = 0;
int y0 = 0;
int srcX = src.getX();
int srcY = src.getY();
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
short flo = (short) lo;
short fhi = (short) hi;
short fco = (short) co;
short sample = ImageUtil
.clampRoundUShort(srcData[b][srcPixelOffset + srcBandOffsets[b]]);
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataShort;
}
} else {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
short flo = (short) lo;
short fhi = (short) hi;
short fco = (short) co;
short sample = ImageUtil.clampRoundUShort(
srcData[b][srcPixelOffset + srcBandOffsets[b]]);
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
short sample = ImageUtil
.clampRoundUShort(srcData[b][srcPixelOffset + srcBandOffsets[b]]);
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
short flo = (short) lo;
short fhi = (short) hi;
short fco = (short) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataShort;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataShort;
}
} else {
for (int b = 0; b < dstBands; b++) {
short sample = ImageUtil.clampRoundUShort(
srcData[b][srcPixelOffset + srcBandOffsets[b]]);
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
short flo = (short) lo;
short fhi = (short) hi;
short fco = (short) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataShort;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
}
}
private void shortLoop(RasterAccessor src, RasterAccessor dst, ROI roiTile,
boolean roiContainsTile) {
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
short[][] srcData = src.getShortDataArrays();
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 srcLineOffset = 0;
int dstLineOffset = 0;
int x0 = 0;
int y0 = 0;
int srcX = src.getX();
int srcY = src.getY();
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
short flo = (short) lo;
short fhi = (short) hi;
short fco = (short) co;
short sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataShort;
}
} else {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
short flo = (short) lo;
short fhi = (short) hi;
short fco = (short) co;
short sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
short sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
short flo = (short) lo;
short fhi = (short) hi;
short fco = (short) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataShort;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataShort;
}
} else {
for (int b = 0; b < dstBands; b++) {
short sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
short flo = (short) lo;
short fhi = (short) hi;
short fco = (short) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataShort;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
}
}
private void intLoop(RasterAccessor src, RasterAccessor dst, ROI roiTile,
boolean roiContainsTile) {
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
int[][] srcData = src.getIntDataArrays();
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 srcLineOffset = 0;
int dstLineOffset = 0;
int x0 = 0;
int y0 = 0;
int srcX = src.getX();
int srcY = src.getY();
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
int flo = (int) lo;
int fhi = (int) hi;
int fco = (int) co;
int sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataInt;
}
} else {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
int flo = (int) lo;
int fhi = (int) hi;
int fco = (int) co;
int sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
int sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
int flo = (int) lo;
int fhi = (int) hi;
int fco = (int) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataInt;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataInt;
}
} else {
for (int b = 0; b < dstBands; b++) {
int sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
int flo = (int) lo;
int fhi = (int) hi;
int fco = (int) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataInt;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
}
}
private void floatLoop(RasterAccessor src, RasterAccessor dst, ROI roiTile,
boolean roiContainsTile) {
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
float[][] srcData = src.getFloatDataArrays();
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 srcLineOffset = 0;
int dstLineOffset = 0;
int x0 = 0;
int y0 = 0;
int srcX = src.getX();
int srcY = src.getY();
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
float flo = (float) lo;
float fhi = (float) hi;
float fco = (float) co;
float sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataFloat;
}
} else {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
float flo = (float) lo;
float fhi = (float) hi;
float fco = (float) co;
float sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
float sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
float flo = (float) lo;
float fhi = (float) hi;
float fco = (float) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataFloat;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataFloat;
}
} else {
for (int b = 0; b < dstBands; b++) {
float sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
float flo = (float) lo;
float fhi = (float) hi;
float fco = (float) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataFloat;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
}
}
private void doubleLoop(RasterAccessor src, RasterAccessor dst, ROI roiTile,
boolean roiContainsTile) {
int srcLineStride = src.getScanlineStride();
int srcPixelStride = src.getPixelStride();
int[] srcBandOffsets = src.getBandOffsets();
double[][] srcData = src.getDoubleDataArrays();
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 srcLineOffset = 0;
int dstLineOffset = 0;
int x0 = 0;
int y0 = 0;
int srcX = src.getX();
int srcY = src.getY();
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
double flo = (double) lo;
double fhi = (double) hi;
double fco = (double) co;
double sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataDouble;
}
} else {
for (int b = 0; b < dstBands; b++) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
double flo = (double) lo;
double fhi = (double) hi;
double fco = (double) co;
double sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
for (int b = 0; b < dstBands; b++) {
double sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
double flo = (double) lo;
double fhi = (double) hi;
double fco = (double) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataDouble;
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
} else {
for (int h = 0; h < dstHeight; h++) {
int srcPixelOffset = srcLineOffset;
int dstPixelOffset = dstLineOffset;
for (int w = 0; w < dstWidth; w++) {
x0 = srcX + w;
y0 = srcY + h;
if (!(roiBounds.contains(x0, y0))) {
for (int b = 0; b < dstBands; b++) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataDouble;
}
} else {
for (int b = 0; b < dstBands; b++) {
double sample = srcData[b][srcPixelOffset + srcBandOffsets[b]];
if (!noData.contains(sample)) {
double lo = low[b];
double hi = high[b];
double co = constant[b];
double flo = (double) lo;
double fhi = (double) hi;
double fco = (double) co;
if (sample >= flo && sample <= fhi) {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = fco;
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = sample;
}
} else {
dstData[b][dstPixelOffset + dstBandOffsets[b]] = destNoDataDouble;
}
}
}
srcPixelOffset += srcPixelStride;
dstPixelOffset += dstPixelStride;
}
srcLineOffset += srcLineStride;
dstLineOffset += dstLineStride;
}
}
}
}