package mil.nga.giat.geowave.adapter.raster.adapter.warp;
import it.geosolutions.jaiext.iterators.RandomIterFactory;
import it.geosolutions.jaiext.range.Range;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.IndexColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.util.Map;
import javax.media.jai.ImageLayout;
import javax.media.jai.Interpolation;
import javax.media.jai.PlanarImage;
import javax.media.jai.ROI;
import javax.media.jai.RasterAccessor;
import javax.media.jai.Warp;
import javax.media.jai.iterator.RandomIter;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* This is code entirely intended to get around an issue on line 265 of
* WarpOpImage in jai-ext. The following code does not work if the source is
* significant lower resolution than the destination and seems unnecessary in
* general:
*
* roiTile = roi.intersect(new ROIShape(srcRectExpanded));
*
* An <code>OpImage</code> implementing the general "Warp" operation as
* described in <code>javax.media.jai.operator.WarpDescriptor</code>. It
* supports the nearest-neighbor interpolation.
*
* <p>
* The layout for the destination image may be specified via the
* <code>ImageLayout</code> parameter. However, only those settings suitable for
* this operation will be used. The unsuitable settings will be replaced by
* default suitable values. An optional ROI object and a NoData Range can be
* used. If a backward mapped pixel lies outside ROI or it is a NoData, then the
* destination pixel value is a background value.
*
* @since EA2
* @see javax.media.jai.Warp
* @see javax.media.jai.WarpOpImage
* @see javax.media.jai.operator.WarpDescriptor
* @see WarpRIF
*
*/
@SuppressWarnings("unchecked")
@SuppressFBWarnings
final class WarpNearestOpImage extends
WarpOpImage
{
/** LookupTable used for a faster NoData check */
private byte[][] byteLookupTable;
/**
* Constructs a WarpNearestOpImage.
*
* @param source
* The source image.
* @param config
* RenderingHints used in calculations.
* @param layout
* The destination image layout.
* @param warp
* An object defining the warp algorithm.
* @param interp
* An object describing the interpolation method.
* @param roi
* input ROI object used.
* @param noData
* NoData Range object used for checking if NoData are present.
*
*/
public WarpNearestOpImage(
final RenderedImage source,
final Map<?, ?> config,
final ImageLayout layout,
final Warp warp,
final Interpolation interp,
final ROI sourceROI,
Range noData,
double[] bkg ) {
super(
source,
layout,
config,
false,
null, // extender not needed in
// nearest-neighbor
// interpolation
interp,
warp,
bkg,
sourceROI,
noData);
/*
* If the source has IndexColorModel, override the default setting in
* OpImage. The dest shall have exactly the same SampleModel and
* ColorModel as the source. Note, in this case, the source should have
* an integral data type.
*/
final ColorModel srcColorModel = source.getColorModel();
if (srcColorModel instanceof IndexColorModel) {
sampleModel = source.getSampleModel().createCompatibleSampleModel(
tileWidth,
tileHeight);
colorModel = srcColorModel;
}
/*
* Selection of a destinationNoData value for each datatype
*/
SampleModel sm = source.getSampleModel();
// Source image data Type
int srcDataType = sm.getDataType();
// Creation of a lookuptable containing the values to use for no data
if (srcDataType == DataBuffer.TYPE_BYTE && hasNoData) {
int numBands = getNumBands();
byteLookupTable = new byte[numBands][256];
for (int b = 0; b < numBands; b++) {
for (int i = 0; i < byteLookupTable[0].length; i++) {
byte value = (byte) i;
if (noDataRange.contains(value)) {
byteLookupTable[b][i] = (byte) backgroundValues[b];
}
else {
byteLookupTable[b][i] = value;
}
}
}
}
}
protected void computeRectByte(
final PlanarImage src,
final RasterAccessor dst,
final RandomIter roiIter,
boolean roiContainsTile ) {
// Random Iterator on the source image bounds
final RandomIter iter = RandomIterFactory.create(
src,
src.getBounds(),
TILE_CACHED,
ARRAY_CALC);
// Initial settings
final int minX = src.getMinX();
final int maxX = src.getMaxX();
final int minY = src.getMinY();
final int maxY = src.getMaxY();
final int dstWidth = dst.getWidth();
final int dstHeight = dst.getHeight();
final int dstBands = dst.getNumBands();
final int lineStride = dst.getScanlineStride();
final int pixelStride = dst.getPixelStride();
final int[] bandOffsets = dst.getBandOffsets();
final byte[][] data = dst.getByteDataArrays();
final float[] warpData = new float[2 * dstWidth];
int lineOffset = 0;
// NO ROI AND NODATA
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
// If the pixel is outside the input image bounds
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b];
}
}
}
else {
// Nearest interpolation
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (byte) (iter.getSample(
sx,
sy,
b) & 0xFF);
}
}
pixelOffset += pixelStride;
}
}
// ONLY ROI
}
else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b];
}
}
}
else {
// Else the related source pixel is set
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (byte) (iter.getSample(
sx,
sy,
b) & 0xFF);
}
}
}
pixelOffset += pixelStride;
}
}
// ONLY NODATA
}
else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a nodata
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = byteLookupTable[b][iter.getSample(
sx,
sy,
b)];
}
}
pixelOffset += pixelStride;
}
}
// BOTH ROI AND NODATA
}
else {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a
// nodata
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = byteLookupTable[b][iter.getSample(
sx,
sy,
b)];
}
}
}
pixelOffset += pixelStride;
}
}
}
iter.done();
}
protected void computeRectUShort(
final PlanarImage src,
final RasterAccessor dst,
final RandomIter roiIter,
boolean roiContainsTile ) {
// Random Iterator on the source image bounds
final RandomIter iter = RandomIterFactory.create(
src,
src.getBounds(),
TILE_CACHED,
ARRAY_CALC);
// Initial settings
final int minX = src.getMinX();
final int maxX = src.getMaxX();
final int minY = src.getMinY();
final int maxY = src.getMaxY();
final int dstWidth = dst.getWidth();
final int dstHeight = dst.getHeight();
final int dstBands = dst.getNumBands();
final int lineStride = dst.getScanlineStride();
final int pixelStride = dst.getPixelStride();
final int[] bandOffsets = dst.getBandOffsets();
final short[][] data = dst.getShortDataArrays();
final float[] warpData = new float[2 * dstWidth];
int lineOffset = 0;
// NO ROI AND NODATA
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
// If the pixel is outside the input image bounds
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// Nearest interpolation
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) (iter.getSample(
sx,
sy,
b) & 0xFFFF);
}
}
pixelOffset += pixelStride;
}
}
// ONLY ROI
}
else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// Else the related source pixel is set
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) (iter.getSample(
sx,
sy,
b) & 0xFFFF);
}
}
}
pixelOffset += pixelStride;
}
}
// ONLY NODATA
}
else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
short inputValue = 0;
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a nodata
for (int b = 0; b < dstBands; b++) {
// Input value selected
inputValue = (short) (iter.getSample(
sx,
sy,
b) & 0xFFFF);
if (noDataRange.contains(inputValue)) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
else {
data[b][pixelOffset + bandOffsets[b]] = inputValue;
}
}
}
pixelOffset += pixelStride;
}
}
// BOTH ROI AND NODATA
}
else {
short inputValue = 0;
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a
// nodata
for (int b = 0; b < dstBands; b++) {
// Input value selected
inputValue = (short) (iter.getSample(
sx,
sy,
b) & 0xFFFF);
if (noDataRange.contains(inputValue)) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
else {
data[b][pixelOffset + bandOffsets[b]] = inputValue;
}
}
}
}
pixelOffset += pixelStride;
}
}
}
iter.done();
}
protected void computeRectShort(
final PlanarImage src,
final RasterAccessor dst,
final RandomIter roiIter,
boolean roiContainsTile ) {
// Random Iterator on the source image bounds
final RandomIter iter = RandomIterFactory.create(
src,
src.getBounds(),
TILE_CACHED,
ARRAY_CALC);
// Initial settings
final int minX = src.getMinX();
final int maxX = src.getMaxX();
final int minY = src.getMinY();
final int maxY = src.getMaxY();
final int dstWidth = dst.getWidth();
final int dstHeight = dst.getHeight();
final int dstBands = dst.getNumBands();
final int lineStride = dst.getScanlineStride();
final int pixelStride = dst.getPixelStride();
final int[] bandOffsets = dst.getBandOffsets();
final short[][] data = dst.getShortDataArrays();
final float[] warpData = new float[2 * dstWidth];
int lineOffset = 0;
// NO ROI AND NODATA
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
// If the pixel is outside the input image bounds
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// Nearest interpolation
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) iter.getSample(
sx,
sy,
b);
}
}
pixelOffset += pixelStride;
}
}
// ONLY ROI
}
else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// Else the related source pixel is set
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) iter.getSample(
sx,
sy,
b);
}
}
}
pixelOffset += pixelStride;
}
}
// ONLY NODATA
}
else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
short inputValue = 0;
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a nodata
for (int b = 0; b < dstBands; b++) {
// Input value selected
inputValue = (short) iter.getSample(
sx,
sy,
b);
if (noDataRange.contains(inputValue)) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
else {
data[b][pixelOffset + bandOffsets[b]] = inputValue;
}
}
}
pixelOffset += pixelStride;
}
}
// BOTH ROI AND NODATA
}
else {
short inputValue = 0;
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a
// nodata
for (int b = 0; b < dstBands; b++) {
// Input value selected
inputValue = (short) iter.getSample(
sx,
sy,
b);
if (noDataRange.contains(inputValue)) {
data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b];
}
else {
data[b][pixelOffset + bandOffsets[b]] = inputValue;
}
}
}
}
pixelOffset += pixelStride;
}
}
}
iter.done();
}
protected void computeRectInt(
final PlanarImage src,
final RasterAccessor dst,
final RandomIter roiIter,
boolean roiContainsTile ) {
// Random Iterator on the source image bounds
final RandomIter iter = RandomIterFactory.create(
src,
src.getBounds(),
TILE_CACHED,
ARRAY_CALC);
// Initial settings
final int minX = src.getMinX();
final int maxX = src.getMaxX();
final int minY = src.getMinY();
final int maxY = src.getMaxY();
final int dstWidth = dst.getWidth();
final int dstHeight = dst.getHeight();
final int dstBands = dst.getNumBands();
final int lineStride = dst.getScanlineStride();
final int pixelStride = dst.getPixelStride();
final int[] bandOffsets = dst.getBandOffsets();
final int[][] data = dst.getIntDataArrays();
final float[] warpData = new float[2 * dstWidth];
int lineOffset = 0;
// NO ROI AND NODATA
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
// If the pixel is outside the input image bounds
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (int) backgroundValues[b];
}
}
}
else {
// Nearest interpolation
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = iter.getSample(
sx,
sy,
b);
}
}
pixelOffset += pixelStride;
}
}
// ONLY ROI
}
else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (int) backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (int) backgroundValues[b];
}
}
}
else {
// Else the related source pixel is set
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = iter.getSample(
sx,
sy,
b);
}
}
}
pixelOffset += pixelStride;
}
}
// ONLY NODATA
}
else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
int inputValue = 0;
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (int) backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a nodata
for (int b = 0; b < dstBands; b++) {
// Input value selected
inputValue = iter.getSample(
sx,
sy,
b);
if (noDataRange.contains(inputValue)) {
data[b][pixelOffset + bandOffsets[b]] = (int) backgroundValues[b];
}
else {
data[b][pixelOffset + bandOffsets[b]] = inputValue;
}
}
}
pixelOffset += pixelStride;
}
}
// BOTH ROI AND NODATA
}
else {
int inputValue = 0;
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (int) backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (int) backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a
// nodata
for (int b = 0; b < dstBands; b++) {
// Input value selected
inputValue = iter.getSample(
sx,
sy,
b);
if (noDataRange.contains(inputValue)) {
data[b][pixelOffset + bandOffsets[b]] = (int) backgroundValues[b];
}
else {
data[b][pixelOffset + bandOffsets[b]] = inputValue;
}
}
}
}
pixelOffset += pixelStride;
}
}
}
iter.done();
}
protected void computeRectFloat(
final PlanarImage src,
final RasterAccessor dst,
final RandomIter roiIter,
boolean roiContainsTile ) {
// Random Iterator on the source image bounds
final RandomIter iter = RandomIterFactory.create(
src,
src.getBounds(),
TILE_CACHED,
ARRAY_CALC);
// Initial settings
final int minX = src.getMinX();
final int maxX = src.getMaxX();
final int minY = src.getMinY();
final int maxY = src.getMaxY();
final int dstWidth = dst.getWidth();
final int dstHeight = dst.getHeight();
final int dstBands = dst.getNumBands();
final int lineStride = dst.getScanlineStride();
final int pixelStride = dst.getPixelStride();
final int[] bandOffsets = dst.getBandOffsets();
final float[][] data = dst.getFloatDataArrays();
final float[] warpData = new float[2 * dstWidth];
int lineOffset = 0;
// NO ROI AND NODATA
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
// If the pixel is outside the input image bounds
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (float) backgroundValues[b];
}
}
}
else {
// Nearest interpolation
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = iter.getSampleFloat(
sx,
sy,
b);
}
}
pixelOffset += pixelStride;
}
}
// ONLY ROI
}
else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (float) backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (float) backgroundValues[b];
}
}
}
else {
// Else the related source pixel is set
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = iter.getSampleFloat(
sx,
sy,
b);
}
}
}
pixelOffset += pixelStride;
}
}
// ONLY NODATA
}
else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
float inputValue = 0;
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (float) backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a nodata
for (int b = 0; b < dstBands; b++) {
// Input value selected
inputValue = iter.getSampleFloat(
sx,
sy,
b);
if (noDataRange.contains(inputValue)) {
data[b][pixelOffset + bandOffsets[b]] = (float) backgroundValues[b];
}
else {
data[b][pixelOffset + bandOffsets[b]] = inputValue;
}
}
}
pixelOffset += pixelStride;
}
}
// BOTH ROI AND NODATA
}
else {
float inputValue = 0;
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (float) backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = (float) backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a
// nodata
for (int b = 0; b < dstBands; b++) {
// Input value selected
inputValue = iter.getSampleFloat(
sx,
sy,
b);
if (noDataRange.contains(inputValue)) {
data[b][pixelOffset + bandOffsets[b]] = (float) backgroundValues[b];
}
else {
data[b][pixelOffset + bandOffsets[b]] = inputValue;
}
}
}
}
pixelOffset += pixelStride;
}
}
}
iter.done();
}
protected void computeRectDouble(
final PlanarImage src,
final RasterAccessor dst,
final RandomIter roiIter,
boolean roiContainsTile ) {
// Random Iterator on the source image bounds
final RandomIter iter = RandomIterFactory.create(
src,
src.getBounds(),
TILE_CACHED,
ARRAY_CALC);
// Initial settings
final int minX = src.getMinX();
final int maxX = src.getMaxX();
final int minY = src.getMinY();
final int maxY = src.getMaxY();
final int dstWidth = dst.getWidth();
final int dstHeight = dst.getHeight();
final int dstBands = dst.getNumBands();
final int lineStride = dst.getScanlineStride();
final int pixelStride = dst.getPixelStride();
final int[] bandOffsets = dst.getBandOffsets();
final double[][] data = dst.getDoubleDataArrays();
final float[] warpData = new float[2 * dstWidth];
int lineOffset = 0;
// NO ROI AND NODATA
if (caseA || (caseB && roiContainsTile)) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
// If the pixel is outside the input image bounds
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b];
}
}
}
else {
// Nearest interpolation
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = iter.getSampleDouble(
sx,
sy,
b);
}
}
pixelOffset += pixelStride;
}
}
// ONLY ROI
}
else if (caseB) {
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b];
}
}
}
else {
// Else the related source pixel is set
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = iter.getSampleDouble(
sx,
sy,
b);
}
}
}
pixelOffset += pixelStride;
}
}
// ONLY NODATA
}
else if (caseC || (hasROI && hasNoData && roiContainsTile)) {
double inputValue = 0;
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a nodata
for (int b = 0; b < dstBands; b++) {
// Input value selected
inputValue = iter.getSampleDouble(
sx,
sy,
b);
if (noDataRange.contains(inputValue)) {
data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b];
}
else {
data[b][pixelOffset + bandOffsets[b]] = inputValue;
}
}
}
pixelOffset += pixelStride;
}
}
// BOTH ROI AND NODATA
}
else {
double inputValue = 0;
for (int h = 0; h < dstHeight; h++) {
int pixelOffset = lineOffset;
lineOffset += lineStride;
// Calculation of the warp for the selected row
warp.warpRect(
dst.getX(),
dst.getY() + h,
dstWidth,
1,
warpData);
int count = 0;
for (int w = 0; w < dstWidth; w++) {
/*
* The warp object subtract 0.5 from backward mapped source
* coordinate. Need to do a round to get the nearest
* neighbor. This is different from the standard nearest
* implementation.
*/
final int sx = round(warpData[count++]);
final int sy = round(warpData[count++]);
if (sx < minX || sx >= maxX || sy < minY || sy >= maxY) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b];
}
}
}
else {
// SG if we falls outside the roi we use the background
// value
if (!(roiBounds.contains(
sx,
sy) && roiIter.getSample(
sx,
sy,
0) > 0)) {
/* Fill with a background color. */
if (setBackground) {
for (int b = 0; b < dstBands; b++) {
data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b];
}
}
}
else {
// The related source pixel is set if it isn't a
// nodata
for (int b = 0; b < dstBands; b++) {
// Input value selected
inputValue = iter.getSampleDouble(
sx,
sy,
b);
if (noDataRange.contains(inputValue)) {
data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b];
}
else {
data[b][pixelOffset + bandOffsets[b]] = inputValue;
}
}
}
}
pixelOffset += pixelStride;
}
}
}
iter.done();
}
}