/* 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.affine;
import it.geosolutions.jaiext.interpolators.InterpolationBicubic;
import it.geosolutions.jaiext.iterators.RandomIterFactory;
import it.geosolutions.jaiext.range.Range;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
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.SampleModel;
import java.awt.image.WritableRaster;
import java.util.Arrays;
import java.util.Map;
import javax.media.jai.BorderExtender;
import javax.media.jai.ImageLayout;
import javax.media.jai.Interpolation;
import javax.media.jai.RasterAccessor;
import javax.media.jai.RasterFormatTag;
import javax.media.jai.iterator.RandomIter;
import com.sun.media.jai.util.ImageUtil;
public class AffineBicubicOpImage extends AffineOpImage {
private static final int KERNEL_LINE_DIM = 4;
private static final float OVERFLOW = 1.0F;
private static final float AVOID_OVERFLOW = 0.999999F;
/** Nearest-Neighbor interpolator */
protected InterpolationBicubic interpBN = null;
/** Byte lookuptable used if no data are present */
protected byte[][] byteLookupTable;
/** ROI extender */
final static BorderExtender roiExtender = BorderExtender
.createInstance(BorderExtender.BORDER_ZERO);
/** Value indicating if destination No Data must be set if the pixel is outside the source rectangle */
private boolean setDestinationNoData;
/** Bicubic Horizontal coefficients for integer type */
private int[] dataHi;
/** Bicubic Vertical coefficients for integer type */
private int[] dataVi;
/** Bicubic Horizontal coefficients for float type */
private float[] dataHf;
/** Bicubic Vertical coefficients for float type */
private float[] dataVf;
/** Bicubic Horizontal coefficients for double type */
private double[] dataHd;
/** Bicubic Vertical coefficients for double type */
private double[] dataVd;
/** Subsample bits used for bicubic interpolation */
protected int subsampleBits;
private int shift;
private int round;
private int precisionBits;
public AffineBicubicOpImage(RenderedImage source, BorderExtender extender, Map config,
ImageLayout layout, AffineTransform transform, Interpolation interp,
double[] backgroundValues, boolean setDestinationNoData, boolean useROIAccessor, Range nodata) {
super(source, extender, config, layout, transform, interp, backgroundValues);
affineOpInitialization(source, interp, layout, backgroundValues, useROIAccessor, setDestinationNoData, nodata);
}
private void affineOpInitialization(RenderedImage source, Interpolation interp,
ImageLayout layout, double[] backgroundValues, boolean useROIAccessor, boolean setDestinationNoData, Range nodata) {
SampleModel sm = source.getSampleModel();
// If the source has an 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.
ColorModel srcColorModel = source.getColorModel();
if (srcColorModel instanceof IndexColorModel && ImageUtil.isBinary(sm)) {
sampleModel = source.getSampleModel()
.createCompatibleSampleModel(tileWidth, tileHeight);
colorModel = srcColorModel;
}
// NumBands
int numBands = getSampleModel().getNumBands();
// Source image data Type
int srcDataType = sm.getDataType();
// If both roiBounds and roiIter are not null, they are used in calculation
Range nod = nodata;
double[] destNod = null;
if (backgroundValues != null && backgroundValues.length > 0) {
destNod = backgroundValues;
}
if (interp instanceof InterpolationBicubic) {
interpBN = (InterpolationBicubic) interp;
this.interp = interpBN;
interpBN.setROIBounds(roiBounds);
noData = interpBN.getNoDataRange();
switch (srcDataType) {
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
case DataBuffer.TYPE_INT:
dataHi = interpBN.getHorizontalTableData();
dataVi = interpBN.getVerticalTableData();
break;
case DataBuffer.TYPE_FLOAT:
dataHf = interpBN.getHorizontalTableDataFloat();
dataVf = interpBN.getVerticalTableDataFloat();
break;
case DataBuffer.TYPE_DOUBLE:
dataHd = interpBN.getHorizontalTableDataDouble();
dataVd = interpBN.getVerticalTableDataDouble();
break;
default:
throw new IllegalArgumentException("Wrong data Type");
}
subsampleBits = interpBN.getSubsampleBitsH();
shift = 1 << subsampleBits;
precisionBits = interpBN.getPrecisionBits();
if (precisionBits > 0) {
round = 1 << (precisionBits - 1);
}
if (nod == null) {
nod = interpBN.getNoDataRange();
}
if (destNod == null) {
destNod = new double[]{interpBN.getDestinationNoData()};
}
}
// Nodata definition
if (nod != null) {
hasNoData = true;
noData = nod;
}
if (destNod != null) {
destinationNoDataDouble = destNod;
} else if (this.backgroundValues != null && this.backgroundValues.length > 0) {
destinationNoDataDouble = this.backgroundValues;
}
// Expand the destination nodata values if not defined
if(destinationNoDataDouble != null && destinationNoDataDouble.length < numBands){
double[] tmp = new double[numBands];
Arrays.fill(tmp, destinationNoDataDouble[0]);
destinationNoDataDouble = tmp;
}
// ROIAccessor definition
if (hasROI) {
this.useROIAccessor = useROIAccessor;
}
// destination No Data set
this.setDestinationNoData = setDestinationNoData;
this.setBackground = setDestinationNoData;
// Create the destination No data arrays
destinationNoDataByte = new byte[numBands];
destinationNoDataShort = new short[numBands];
destinationNoDataUShort = new short[numBands];
destinationNoDataInt = new int[numBands];
destinationNoDataFloat = new float[numBands];
// Populate the arrays
for (int i = 0; i < numBands; i++) {
destinationNoDataByte[i] = (byte) ((int) destinationNoDataDouble[i] & 0xFF);
destinationNoDataUShort[i] = (short) (((short) destinationNoDataDouble[i]) & 0xffff);
destinationNoDataShort[i] = (short) destinationNoDataDouble[i];
destinationNoDataInt[i] = (int) destinationNoDataDouble[i];
destinationNoDataFloat[i] = (float) destinationNoDataDouble[i];
}
// special byte case
if (srcDataType == DataBuffer.TYPE_BYTE && hasNoData) {
// Creation of a lookuptable containing the values to use for no data
byteLookupTable = new byte[numBands][256];
for (int i = 0; i < byteLookupTable[0].length; i++) {
byte value = (byte) i;
for (int b = 0; b < numBands; b++) {
if (noData.contains(value)) {
if (setDestinationNoData) {
byteLookupTable[b][i] = destinationNoDataByte[b];
} else {
byteLookupTable[b][i] = 0;
if(i !=0){
byteLookupTable[b][0] = 1;
}
}
} else {
byteLookupTable[b][i] = value;
}
}
}
}
// 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;
}
/** Method for evaluating the destination image tile without ROI */
protected void computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect) {
RasterFormatTag[] formatTags = getFormatTags();
// Source image
Raster source = sources[0];
// Source rectangle
Rectangle srcRect = source.getBounds();
// Src upper left pixel coordinates
int srcRectX = srcRect.x;
int srcRectY = srcRect.y;
// Get data for the source rectangle & the destination rectangle
// In the first version source Rectangle is the whole source
// image always.
RasterAccessor srcAccessor = new RasterAccessor(source, srcRect, formatTags[0],
getSourceImage(0).getColorModel());
RasterAccessor dstAccessor = new RasterAccessor(dest, destRect, formatTags[1],
getColorModel());
// Roi rasterAccessor initialization
RasterAccessor roiAccessor = null;
// Roi raster initialization
Raster roi = null;
RandomIter roiIter = null;
// ROI calculation only if the roi raster is present
if (hasROI) {
if (useROIAccessor) {
if(srcROIImage.getBounds().contains(srcRect)){
roi = srcROIImage.getData(srcRect);
} else{
roi = srcROIImgExt.getData(srcRect);
}
roiAccessor = new RasterAccessor(roi, srcRect, RasterAccessor.findCompatibleTags(
new RenderedImage[] { srcROIImage }, srcROIImage)[0],
srcROIImage.getColorModel());
} else {
roiIter = RandomIterFactory.create(srcROIImgExt, roiRect, true, true);
}
}
int dataType = dest.getSampleModel().getDataType();
// If the image is not binary, then for every kind of dataType, the image affine transformation
// is performed.
switch (dataType) {
case DataBuffer.TYPE_BYTE:
byteLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor, roiAccessor, roiIter);
break;
case DataBuffer.TYPE_INT:
intLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor, roiAccessor, roiIter);
break;
case DataBuffer.TYPE_SHORT:
shortLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor, roiAccessor, roiIter);
break;
case DataBuffer.TYPE_USHORT:
ushortLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor,
roiAccessor, roiIter);
break;
case DataBuffer.TYPE_FLOAT:
floatLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor, roiAccessor, roiIter);
break;
case DataBuffer.TYPE_DOUBLE:
doubleLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor,
roiAccessor, roiIter);
break;
}
// If the RasterAccessor object set up a temporary buffer for the
// op to write to, tell the RasterAccessor to write that data
// to the raster, that we're done with it.
if (dstAccessor.isDataCopy()) {
dstAccessor.clampDataArrays();
dstAccessor.copyDataToRaster();
}
}
private void byteLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX,
int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
final float src_rect_x1 = src.getX();
final float src_rect_y1 = src.getY();
final float src_rect_x2 = src_rect_x1 + src.getWidth();
final float src_rect_y2 = src_rect_y1 + src.getHeight();
final float src_rect_x11 = src_rect_x1 + 1;
final float src_rect_y11 = src_rect_y1 + 1;
final float src_rect_x22 = src_rect_x2 - 2;
final float src_rect_y22 = src_rect_y2 - 2;
double fracx = 0, fracy = 0;
int dstPixelOffset;
int dstOffset = 0;
final Point2D dst_pt = new Point2D.Float();
final Point2D src_pt = new Point2D.Float();
final byte dstDataArrays[][] = dst.getByteDataArrays();
final int dstBandOffsets[] = dst.getBandOffsets();
final int dstPixelStride = dst.getPixelStride();
final int dstScanlineStride = dst.getScanlineStride();
final byte srcDataArrays[][] = src.getByteDataArrays();
final int bandOffsets[] = src.getBandOffsets();
final int srcPixelStride = src.getPixelStride();
final int srcScanlineStride = src.getScanlineStride();
final int dst_num_bands = dst.getNumBands();
final int dst_min_x = destRect.x;
final int dst_min_y = destRect.y;
final int dst_max_x = destRect.x + destRect.width;
final int dst_max_y = destRect.y + destRect.height;
// ROI scanline stride
final byte[] roiDataArray;
final int roiDataLength;
final int roiScanlineStride;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiDataLength = roiDataArray.length;
roiScanlineStride = roi.getScanlineStride();
} else {
roiDataArray = null;
roiDataLength = 0;
roiScanlineStride = 0;
}
if (caseA) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long temp = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
int pixelValue = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]] & 0xff;
// Update of the temporary sum
temp += (pixelValue * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((temp + round) >> precisionBits) * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
if (result > 255) {
result = 255;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (result & 0xff);
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else if (caseB) {
if (useROIAccessor) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
final int[][] pixelKernel = new int[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]] & 0xff;
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((tempSum + round) >> precisionBits)
* dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > 255) {
result = 255;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (result & 0xff);
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// PixelPositions
int x0 = src.getX() + posx / srcPixelStride;
int y0 = src.getY() + posy / srcScanlineStride;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
final int[][] pixelKernel = new int[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride + bandOffsets[k2] ] & 0xff;
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((tempSum + round) >> precisionBits)
* dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > 255) {
result = 255;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (result & 0xff);
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
} else if (caseC) {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
long[] tempData;
short weight = 0;
byte weightVert = 0;
byte temp = 0;
// Row temporary sum initialization
long tempSum = 0;
long sum = 0;
// final result initialization
long result = 0;
// initial x value definition
final double dst_min_x_d = dst_min_x + HALF_PIXEL;
// Band data array creation
byte[] bandDataArray;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x_d, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
double s_x = src_pt.getX();
double s_y = src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
bandDataArray = srcDataArrays[k2];
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and check if every kernel pixel is a No Data
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
int sample = bandDataArray[pos + (z - 1) * srcPixelStride
+ (h - 1) * srcScanlineStride + bandOffsets[k2] ] & 0xff;
pixelKernel[h][z] = sample;
if (byteLookupTable[k2][sample] != destinationNoDataByte[k2]) {
weight |= (1 << (4 * h + z));
// weightArray[h][z] = 1;
} else {
// weightArray[h][z] = 0;
weight &= (0xffff - (1 << 4 * h + z));
}
}
temp = (byte) ((weight >> 4 * h) & 0x0F);
tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray);
tempSum = tempData[0] * dataHi[offsetX] +
tempData[1] * dataHi[offsetX + 1] +
tempData[2] * dataHi[offsetX + 2] +
tempData[3] * dataHi[offsetX + 3];
if (temp > 0) {
weightVert |= (1 << h);
// weightArrayVertical[h] = 1;
} else {
weightVert &= (0x0F - (1 << h));
// weightArrayVertical[h] = 0;
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
// Control if the 16 pixel are all No Data
if (weight == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
} else {
tempData = bicubicInpainting(sumArray, weightVert, emptyArray);
// Vertical sum update
sum = tempData[0] * dataVi[offsetY] + tempData[1]
* dataVi[offsetY + 1] + tempData[2] * dataVi[offsetY + 2]
+ tempData[3] * dataVi[offsetY + 3];
// Interpolation
result = ((sum + round) >> precisionBits);
weight = 0;
weightVert = 0;
sum = 0;
// Clamp
if (result > 255) {
result = 255;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (result & 0xff);
}
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
if (useROIAccessor) {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride + bandOffsets[k2] ] & 0xff;
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
if (byteLookupTable[k2][(int) pixelKernel[h][z]] != destinationNoDataByte[k2]) {
weight |= (1 << (4 * h + z));
// weightArray[h][z] = 1;
} else {
// weightArray[h][z] = 0;
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
long[] tempData = bicubicInpainting(pixelKernel[h], temp,
emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHi[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
// weightArrayVertical[h] = 1;
} else {
weightVert &= (0x0F - (1 << h));
// weightArrayVertical[h] = 0;
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
long[] tempData = bicubicInpainting(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > 255) {
result = 255;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (result & 0xff);
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int x0 = src.getX() + posx / srcPixelStride;
final int y0 = src.getY() + posy / srcScanlineStride;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride + bandOffsets[k2] ] & 0xff;
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
if (byteLookupTable[k2][(int) pixelKernel[h][z]] != destinationNoDataByte[k2]) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
long[] tempData = bicubicInpainting(pixelKernel[h], temp,
emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHi[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
long[] tempData = bicubicInpainting(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > 255) {
result = 255;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (result & 0xff);
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
}
}
private void ushortLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX,
int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
final float src_rect_x1 = src.getX();
final float src_rect_y1 = src.getY();
final float src_rect_x2 = src_rect_x1 + src.getWidth();
final float src_rect_y2 = src_rect_y1 + src.getHeight();
final float src_rect_x11 = src_rect_x1 + 1;
final float src_rect_y11 = src_rect_y1 + 1;
final float src_rect_x22 = src_rect_x2 - 2;
final float src_rect_y22 = src_rect_y2 - 2;
double fracx = 0, fracy = 0;
int dstPixelOffset;
int dstOffset = 0;
final Point2D dst_pt = new Point2D.Float();
final Point2D src_pt = new Point2D.Float();
final short dstDataArrays[][] = dst.getShortDataArrays();
final int dstBandOffsets[] = dst.getBandOffsets();
final int dstPixelStride = dst.getPixelStride();
final int dstScanlineStride = dst.getScanlineStride();
final short srcDataArrays[][] = src.getShortDataArrays();
final int bandOffsets[] = src.getBandOffsets();
final int srcPixelStride = src.getPixelStride();
final int srcScanlineStride = src.getScanlineStride();
final int dst_num_bands = dst.getNumBands();
final int dst_min_x = destRect.x;
final int dst_min_y = destRect.y;
final int dst_max_x = destRect.x + destRect.width;
final int dst_max_y = destRect.y + destRect.height;
// ROI scanline stride
final byte[] roiDataArray;
final int roiDataLength;
final int roiScanlineStride;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiDataLength = roiDataArray.length;
roiScanlineStride = roi.getScanlineStride();
} else {
roiDataArray = null;
roiDataLength = 0;
roiScanlineStride = 0;
}
if (caseA) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
int posx = (s_ix - srcRectX) * srcPixelStride;
int posy = (s_iy - srcRectY) * srcScanlineStride;
int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long temp = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
int pixelValue = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]] & 0xffff;
// Update of the temporary sum
temp += (pixelValue * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((temp + round) >> precisionBits) * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
if (result > USHORT_MAX_VALUE) {
result = USHORT_MAX_VALUE;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (result & 0xffff);
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else if (caseB) {
if (useROIAccessor) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
final int[][] pixelKernel = new int[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]] & 0xffff;
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((tempSum + round) >> precisionBits)
* dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > USHORT_MAX_VALUE) {
result = USHORT_MAX_VALUE;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (result & 0xffff);
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// PixelPositions
int x0 = src.getX() + posx / srcPixelStride;
int y0 = src.getY() + posy / srcScanlineStride;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
final int[][] pixelKernel = new int[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride + bandOffsets[k2] ] & 0xffff;
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((tempSum + round) >> precisionBits)
* dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > USHORT_MAX_VALUE) {
result = USHORT_MAX_VALUE;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (result & 0xffff);
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
} else if (caseC) {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
// Row temporary sum initialization
long tempSum = 0;
long sum = 0;
// final result initialization
long result = 0;
// initial x value definition
final double dst_min_x_d = dst_min_x + HALF_PIXEL;
// Band data array creation
short[] bandDataArray;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x_d, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
bandDataArray = srcDataArrays[k2];
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and check if every kernel pixel is a No Data
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = bandDataArray[pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride + bandOffsets[k2] ] & 0xffff;
if (!noData.contains((short) pixelKernel[h][z])) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
temp = (byte) ((weight >> 4 * h) & 0x0F);
long[] tempData = bicubicInpainting(pixelKernel[h], temp,
emptyArray);
tempSum = tempData[0] * dataHi[offsetX] + tempData[1]
* dataHi[offsetX + 1] + tempData[2] * dataHi[offsetX + 2]
+ tempData[3] * dataHi[offsetX + 3];
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
// Control if the 16 pixel are all No Data
if (weight == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
} else {
long[] tempData = bicubicInpainting(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
sum = tempData[0] * dataVi[offsetY] + tempData[1]
* dataVi[offsetY + 1] + tempData[2] * dataVi[offsetY + 2]
+ tempData[3] * dataVi[offsetY + 3];
// Interpolation
result = (int) ((sum + round) >> precisionBits);
sum = 0;
// Clamp
if (result > USHORT_MAX_VALUE) {
result = USHORT_MAX_VALUE;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (result & 0xffff);
}
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
if (useROIAccessor) {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride + bandOffsets[k2] ] & 0xffff;
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
if (!noData.contains((short) pixelKernel[h][z])) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
long[] tempData = bicubicInpainting(pixelKernel[h], temp,
emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHi[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
long[] tempData = bicubicInpainting(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > USHORT_MAX_VALUE) {
result = USHORT_MAX_VALUE;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (result & 0xffff);
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
int x0 = src.getX() + posx / srcPixelStride;
int y0 = src.getY() + posy / srcScanlineStride;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride + bandOffsets[k2] ] & 0xffff;
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
if (!noData.contains((short) pixelKernel[h][z])) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
long[] tempData = bicubicInpainting(pixelKernel[h], temp,
emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHi[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
long[] tempData = bicubicInpainting(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > USHORT_MAX_VALUE) {
result = USHORT_MAX_VALUE;
} else if (result < 0) {
result = 0;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (result & 0xffff);
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
}
}
private void shortLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX,
int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
final float src_rect_x1 = src.getX();
final float src_rect_y1 = src.getY();
final float src_rect_x2 = src_rect_x1 + src.getWidth();
final float src_rect_y2 = src_rect_y1 + src.getHeight();
final float src_rect_x11 = src_rect_x1 + 1;
final float src_rect_y11 = src_rect_y1 + 1;
final float src_rect_x22 = src_rect_x2 - 2;
final float src_rect_y22 = src_rect_y2 - 2;
double fracx = 0, fracy = 0;
int dstPixelOffset;
int dstOffset = 0;
final Point2D dst_pt = new Point2D.Float();
final Point2D src_pt = new Point2D.Float();
final short dstDataArrays[][] = dst.getShortDataArrays();
final int dstBandOffsets[] = dst.getBandOffsets();
final int dstPixelStride = dst.getPixelStride();
final int dstScanlineStride = dst.getScanlineStride();
final short srcDataArrays[][] = src.getShortDataArrays();
final int bandOffsets[] = src.getBandOffsets();
final int srcPixelStride = src.getPixelStride();
final int srcScanlineStride = src.getScanlineStride();
final int dst_num_bands = dst.getNumBands();
final int dst_min_x = destRect.x;
final int dst_min_y = destRect.y;
final int dst_max_x = destRect.x + destRect.width;
final int dst_max_y = destRect.y + destRect.height;
// ROI scanline stride
final byte[] roiDataArray;
final int roiDataLength;
final int roiScanlineStride;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiDataLength = roiDataArray.length;
roiScanlineStride = roi.getScanlineStride();
} else {
roiDataArray = null;
roiDataLength = 0;
roiScanlineStride = 0;
}
if (caseA) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
int posx = (s_ix - srcRectX) * srcPixelStride;
int posy = (s_iy - srcRectY) * srcScanlineStride;
int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long temp = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
int pixelValue = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]];
// Update of the temporary sum
temp += (pixelValue * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((temp + round) >> precisionBits) * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
if (result > Short.MAX_VALUE) {
result = Short.MAX_VALUE;
} else if (result < Short.MIN_VALUE) {
result = Short.MIN_VALUE;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) result;
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else if (caseB) {
if (useROIAccessor) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
final int[][] pixelKernel = new int[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]];
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((tempSum + round) >> precisionBits)
* dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > Short.MAX_VALUE) {
result = Short.MAX_VALUE;
} else if (result < Short.MIN_VALUE) {
result = Short.MIN_VALUE;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) result;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// PixelPositions
int x0 = src.getX() + posx / srcPixelStride;
int y0 = src.getY() + posy / srcScanlineStride;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
final int[][] pixelKernel = new int[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((tempSum + round) >> precisionBits)
* dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > Short.MAX_VALUE) {
result = Short.MAX_VALUE;
} else if (result < Short.MIN_VALUE) {
result = Short.MIN_VALUE;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) result;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
} else if (caseC) {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
// Row temporary sum initialization
long tempSum = 0;
long sum = 0;
// final result initialization
long result = 0;
// initial x value definition
final double dst_min_x_d = dst_min_x + HALF_PIXEL;
// Band data array creation
short[] bandDataArray;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x_d, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
bandDataArray = srcDataArrays[k2];
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and check if every kernel pixel is a No Data
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = bandDataArray[pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
if (!noData.contains((short) pixelKernel[h][z])) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
temp = (byte) ((weight >> 4 * h) & 0x0F);
long[] tempData = bicubicInpainting(pixelKernel[h], temp,
emptyArray);
tempSum = tempData[0] * dataHi[offsetX] + tempData[1]
* dataHi[offsetX + 1] + tempData[2] * dataHi[offsetX + 2]
+ tempData[3] * dataHi[offsetX + 3];
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
// Control if the 16 pixel are all No Data
if (weight == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
} else {
long[] tempData = bicubicInpainting(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
sum = tempData[0] * dataVi[offsetY] + tempData[1]
* dataVi[offsetY + 1] + tempData[2] * dataVi[offsetY + 2]
+ tempData[3] * dataVi[offsetY + 3];
// Interpolation
result = (int) ((sum + round) >> precisionBits);
sum = 0;
// Clamp
if (result > Short.MAX_VALUE) {
result = Short.MAX_VALUE;
} else if (result < Short.MIN_VALUE) {
result = Short.MIN_VALUE;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) result;
}
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
if (useROIAccessor) {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
if (!noData.contains((short) pixelKernel[h][z])) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
long[] tempData = bicubicInpainting(pixelKernel[h], temp,
emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHi[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
long[] tempData = bicubicInpainting(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > Short.MAX_VALUE) {
result = Short.MAX_VALUE;
} else if (result < Short.MIN_VALUE) {
result = Short.MIN_VALUE;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) result;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
int x0 = src.getX() + posx / srcPixelStride;
int y0 = src.getY() + posy / srcScanlineStride;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
if (!noData.contains((short) pixelKernel[h][z])) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
long[] tempData = bicubicInpainting(pixelKernel[h], temp,
emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHi[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
long[] tempData = bicubicInpainting(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
// Clamp
if (result > Short.MAX_VALUE) {
result = Short.MAX_VALUE;
} else if (result < Short.MIN_VALUE) {
result = Short.MIN_VALUE;
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) result;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
}
}
private void intLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX,
int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
final float src_rect_x1 = src.getX();
final float src_rect_y1 = src.getY();
final float src_rect_x2 = src_rect_x1 + src.getWidth();
final float src_rect_y2 = src_rect_y1 + src.getHeight();
final float src_rect_x11 = src_rect_x1 + 1;
final float src_rect_y11 = src_rect_y1 + 1;
final float src_rect_x22 = src_rect_x2 - 2;
final float src_rect_y22 = src_rect_y2 - 2;
double fracx = 0, fracy = 0;
int dstPixelOffset;
int dstOffset = 0;
final Point2D dst_pt = new Point2D.Float();
final Point2D src_pt = new Point2D.Float();
final int dstDataArrays[][] = dst.getIntDataArrays();
final int dstBandOffsets[] = dst.getBandOffsets();
final int dstPixelStride = dst.getPixelStride();
final int dstScanlineStride = dst.getScanlineStride();
final int srcDataArrays[][] = src.getIntDataArrays();
final int bandOffsets[] = src.getBandOffsets();
final int srcPixelStride = src.getPixelStride();
final int srcScanlineStride = src.getScanlineStride();
final int dst_num_bands = dst.getNumBands();
final int dst_min_x = destRect.x;
final int dst_min_y = destRect.y;
final int dst_max_x = destRect.x + destRect.width;
final int dst_max_y = destRect.y + destRect.height;
// ROI scanline stride
final byte[] roiDataArray;
final int roiDataLength;
final int roiScanlineStride;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiDataLength = roiDataArray.length;
roiScanlineStride = roi.getScanlineStride();
} else {
roiDataArray = null;
roiDataLength = 0;
roiScanlineStride = 0;
}
if (caseA) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
int posx = (s_ix - srcRectX) * srcPixelStride;
int posy = (s_iy - srcRectY) * srcScanlineStride;
int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long temp = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
int pixelValue = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]];
// Update of the temporary sum
temp += (pixelValue * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((temp + round) >> precisionBits) * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result;
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else if (caseB) {
if (useROIAccessor) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
final int[][] pixelKernel = new int[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]];
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((tempSum + round) >> precisionBits)
* dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// PixelPositions
int x0 = src.getX() + posx / srcPixelStride;
int y0 = src.getY() + posy / srcScanlineStride;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
final int[][] pixelKernel = new int[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]);
}
// Vertical sum update
sum += ((tempSum + round) >> precisionBits)
* dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
} else if (caseC) {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
// Row temporary sum initialization
long tempSum = 0;
long sum = 0;
// final result initialization
int result = 0;
// initial x value definition
final double dst_min_x_d = dst_min_x + HALF_PIXEL;
// Band data array creation
int[] bandDataArray;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x_d, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
bandDataArray = srcDataArrays[k2];
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and check if every kernel pixel is a No Data
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = bandDataArray[pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
if (!noData.contains((int) pixelKernel[h][z])) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
temp = (byte) ((weight >> 4 * h) & 0x0F);
long[] tempData = bicubicInpainting(pixelKernel[h], temp,
emptyArray);
tempSum = tempData[0] * dataHi[offsetX] + tempData[1]
* dataHi[offsetX + 1] + tempData[2] * dataHi[offsetX + 2]
+ tempData[3] * dataHi[offsetX + 3];
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
// Control if the 16 pixel are all No Data
if (weight == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
} else {
long[] tempData = bicubicInpainting(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
sum = tempData[0] * dataVi[offsetY] + tempData[1]
* dataVi[offsetY + 1] + tempData[2] * dataVi[offsetY + 2]
+ tempData[3] * dataVi[offsetY + 3];
// Interpolation
result = (int) ((sum + round) >> precisionBits);
sum = 0;
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result;
}
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
if (useROIAccessor) {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
if (!noData.contains((int) pixelKernel[h][z])) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
long[] tempData = bicubicInpainting(pixelKernel[h], temp,
emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHi[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
long[] tempData = bicubicInpainting(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
final long[][] pixelKernel = new long[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
long[] sumArray = new long[KERNEL_LINE_DIM];
long[] emptyArray = new long[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
int x0 = src.getX() + posx / srcPixelStride;
int y0 = src.getY() + posy / srcScanlineStride;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
long sum = 0;
int result = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
if (!noData.contains((int) pixelKernel[h][z])) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
long tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
long[] tempData = bicubicInpainting(pixelKernel[h], temp,
emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHi[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = ((tempSum + round) >> precisionBits);
}
long[] tempData = bicubicInpainting(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVi[offsetY + h];
}
// Interpolation
result = (int) ((sum + round) >> precisionBits);
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
}
}
private void floatLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX,
int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
final float src_rect_x1 = src.getX();
final float src_rect_y1 = src.getY();
final float src_rect_x2 = src_rect_x1 + src.getWidth();
final float src_rect_y2 = src_rect_y1 + src.getHeight();
final float src_rect_x11 = src_rect_x1 + 1;
final float src_rect_y11 = src_rect_y1 + 1;
final float src_rect_x22 = src_rect_x2 - 2;
final float src_rect_y22 = src_rect_y2 - 2;
double fracx = 0, fracy = 0;
int dstPixelOffset;
int dstOffset = 0;
final Point2D dst_pt = new Point2D.Float();
final Point2D src_pt = new Point2D.Float();
final float dstDataArrays[][] = dst.getFloatDataArrays();
final int dstBandOffsets[] = dst.getBandOffsets();
final int dstPixelStride = dst.getPixelStride();
final int dstScanlineStride = dst.getScanlineStride();
final float srcDataArrays[][] = src.getFloatDataArrays();
final int bandOffsets[] = src.getBandOffsets();
final int srcPixelStride = src.getPixelStride();
final int srcScanlineStride = src.getScanlineStride();
final int dst_num_bands = dst.getNumBands();
final int dst_min_x = destRect.x;
final int dst_min_y = destRect.y;
final int dst_max_x = destRect.x + destRect.width;
final int dst_max_y = destRect.y + destRect.height;
// ROI scanline stride
final byte[] roiDataArray;
final int roiDataLength;
final int roiScanlineStride;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiDataLength = roiDataArray.length;
roiScanlineStride = roi.getScanlineStride();
} else {
roiDataArray = null;
roiDataLength = 0;
roiScanlineStride = 0;
}
if (caseA) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
int posx = (s_ix - srcRectX) * srcPixelStride;
int posy = (s_iy - srcRectY) * srcScanlineStride;
int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
float sum = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
float temp = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
float pixelValue = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]];
// Update of the temporary sum
temp += (pixelValue * dataHf[offsetX + z]);
}
// Vertical sum update
sum += temp * dataVf[offsetY + h];
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = sum;
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else if (caseB) {
if (useROIAccessor) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
float sum = 0;
final float[][] pixelKernel = new float[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]];
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
float tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHf[offsetX + z]);
}
// Vertical sum update
sum += tempSum * dataVf[offsetY + h];
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = sum;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// PixelPositions
int x0 = src.getX() + posx / srcPixelStride;
int y0 = src.getY() + posy / srcScanlineStride;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
float sum = 0;
final float[][] pixelKernel = new float[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
float tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHf[offsetX + z]);
}
// Vertical sum update
sum += tempSum * dataVf[offsetY + h];
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = sum;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
} else if (caseC) {
final double[][] pixelKernel = new double[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
double[] sumArray = new double[KERNEL_LINE_DIM];
double[] emptyArray = new double[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
// Row temporary sum initialization
double tempSum = 0;
double sum = 0;
// initial x value definition
final double dst_min_x_d = dst_min_x + HALF_PIXEL;
// Band data array creation
float[] bandDataArray;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x_d, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
bandDataArray = srcDataArrays[k2];
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and check if every kernel pixel is a No Data
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
float value = bandDataArray[pos + (z - 1) * srcPixelStride
+ (h - 1) * srcScanlineStride];
pixelKernel[h][z] = value;
if (!noData.contains(value)) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
temp = (byte) ((weight >> 4 * h) & 0x0F);
double[] tempData = bicubicInpaintingDouble(pixelKernel[h], temp,
emptyArray);
tempSum = tempData[0] * dataHf[offsetX] + tempData[1]
* dataHf[offsetX + 1] + tempData[2] * dataHf[offsetX + 2]
+ tempData[3] * dataHf[offsetX + 3];
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = tempSum;
}
// Control if the 16 pixel are all No Data
if (weight == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
} else {
double[] tempData = bicubicInpaintingDouble(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
sum = tempData[0] * dataVf[offsetY] + tempData[1]
* dataVf[offsetY + 1] + tempData[2] * dataVf[offsetY + 2]
+ tempData[3] * dataVf[offsetY + 3];
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (float) sum;
// reset of the sum value
sum = 0;
}
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
if (useROIAccessor) {
final double[][] pixelKernel = new double[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
double[] sumArray = new double[KERNEL_LINE_DIM];
double[] emptyArray = new double[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
double sum = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
float value = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
pixelKernel[h][z] = value;
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
if (!noData.contains(value)) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
double tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
double[] tempData = bicubicInpaintingDouble(pixelKernel[h],
temp, emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHf[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = tempSum;
}
double[] tempData = bicubicInpaintingDouble(sumArray,
weightVert, emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVf[offsetY + h];
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (float) sum;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
final double[][] pixelKernel = new double[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
double[] sumArray = new double[KERNEL_LINE_DIM];
double[] emptyArray = new double[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
int x0 = src.getX() + posx / srcPixelStride;
int y0 = src.getY() + posy / srcScanlineStride;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
double sum = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
float value = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
pixelKernel[h][z] = value;
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
if (!noData.contains(value)) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
double tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
double[] tempData = bicubicInpaintingDouble(pixelKernel[h],
temp, emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHf[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = tempSum;
}
double[] tempData = bicubicInpaintingDouble(sumArray,
weightVert, emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVf[offsetY + h];
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (float) sum;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
}
}
private void doubleLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX,
int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) {
final float src_rect_x1 = src.getX();
final float src_rect_y1 = src.getY();
final float src_rect_x2 = src_rect_x1 + src.getWidth();
final float src_rect_y2 = src_rect_y1 + src.getHeight();
final float src_rect_x11 = src_rect_x1 + 1;
final float src_rect_y11 = src_rect_y1 + 1;
final float src_rect_x22 = src_rect_x2 - 2;
final float src_rect_y22 = src_rect_y2 - 2;
double fracx = 0, fracy = 0;
int dstPixelOffset;
int dstOffset = 0;
final Point2D dst_pt = new Point2D.Float();
final Point2D src_pt = new Point2D.Float();
final double dstDataArrays[][] = dst.getDoubleDataArrays();
final int dstBandOffsets[] = dst.getBandOffsets();
final int dstPixelStride = dst.getPixelStride();
final int dstScanlineStride = dst.getScanlineStride();
final double srcDataArrays[][] = src.getDoubleDataArrays();
final int bandOffsets[] = src.getBandOffsets();
final int srcPixelStride = src.getPixelStride();
final int srcScanlineStride = src.getScanlineStride();
final int dst_num_bands = dst.getNumBands();
final int dst_min_x = destRect.x;
final int dst_min_y = destRect.y;
final int dst_max_x = destRect.x + destRect.width;
final int dst_max_y = destRect.y + destRect.height;
// ROI scanline stride
final byte[] roiDataArray;
final int roiDataLength;
final int roiScanlineStride;
if (useROIAccessor) {
roiDataArray = roi.getByteDataArray(0);
roiDataLength = roiDataArray.length;
roiScanlineStride = roi.getScanlineStride();
} else {
roiDataArray = null;
roiDataLength = 0;
roiScanlineStride = 0;
}
if (caseA) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
double s_x = src_pt.getX();
double s_y = src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
int posx = (s_ix - srcRectX) * srcPixelStride;
int posy = (s_iy - srcRectY) * srcScanlineStride;
int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
double sum = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
double temp = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
double pixelValue = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]];
// Update of the temporary sum
temp += (pixelValue * dataHd[offsetX + z]);
}
// Vertical sum update
sum += temp * dataVd[offsetY + h];
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = sum;
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else if (caseB) {
if (useROIAccessor) {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
double s_x = src_pt.getX();
double s_y = src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
double sum = 0;
final double[][] pixelKernel = new double[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride
+ bandOffsets[k2]];
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
double tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHd[offsetX + z]);
}
// Vertical sum update
sum += tempSum * dataVd[offsetY + h];
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = sum;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
double s_x = src_pt.getX();
double s_y = src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
// PixelPositions
int x0 = src.getX() + posx / srcPixelStride;
int y0 = src.getY() + posy / srcScanlineStride;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
double sum = 0;
final double[][] pixelKernel = new double[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
pixelKernel[h][z] = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
}
}
// Control if the 16 pixel are outside the ROI
if (tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
double tempSum = 0;
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (pixelKernel[h][z] * dataHd[offsetX + z]);
}
// Vertical sum update
sum += tempSum * dataVd[offsetY + h];
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = sum;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
} else if (caseC) {
final double[][] pixelKernel = new double[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
double[] sumArray = new double[KERNEL_LINE_DIM];
double[] emptyArray = new double[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
// Row temporary sum initialization
double tempSum = 0;
double sum = 0;
// initial x value definition
final double dst_min_x_d = dst_min_x + HALF_PIXEL;
// Band data array creation
double[] bandDataArray;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x_d, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
double s_x = src_pt.getX();
double s_y = src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
for (int x = dst_min_x; x < dst_max_x; x++) {
if ((s_ix >= src_rect_x11) && (s_ix < (src_rect_x22))
&& (s_iy >= (src_rect_y11)) && (s_iy < (src_rect_y22))) {
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
final int pos = posx + posy;
for (int k2 = 0; k2 < dst_num_bands; k2++) {
bandDataArray = srcDataArrays[k2];
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and check if every kernel pixel is a No Data
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
double value = bandDataArray[pos + (z - 1) * srcPixelStride
+ (h - 1) * srcScanlineStride];
pixelKernel[h][z] = value;
if (!noData.contains(value)) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
temp = (byte) ((weight >> 4 * h) & 0x0F);
double[] tempData = bicubicInpaintingDouble(pixelKernel[h], temp,
emptyArray);
tempSum = tempData[0] * dataHd[offsetX] + tempData[1]
* dataHd[offsetX + 1] + tempData[2] * dataHd[offsetX + 2]
+ tempData[3] * dataHd[offsetX + 3];
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = tempSum;
}
// Control if the 16 pixel are all No Data
if (weight == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
} else {
double[] tempData = bicubicInpaintingDouble(sumArray, weightVert,
emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
sum = tempData[0] * dataVd[offsetY] + tempData[1]
* dataVd[offsetY + 1] + tempData[2] * dataVd[offsetY + 2]
+ tempData[3] * dataVd[offsetY + 3];
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = sum;
// result reset
sum = 0;
}
}
} else if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
if (useROIAccessor) {
final double[][] pixelKernel = new double[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
double[] sumArray = new double[KERNEL_LINE_DIM];
double[] emptyArray = new double[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
double s_x = src_pt.getX();
double s_y = src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
// If roiAccessor is present, the y position on the roi image is calculated
final int posyROI = (s_iy - srcRectY) * roiScanlineStride;
final int baseIndex = (posx / dst_num_bands) + posyROI;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
double sum = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
double value = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
pixelKernel[h][z] = value;
int index = baseIndex - 1 + z + (h - 1)
* (roiScanlineStride);
if (index < roiDataLength) {
// Update of the weight sum
tmpROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1
: 0);
}
if (!noData.contains(value)) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
double tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
double[] tempData = bicubicInpaintingDouble(pixelKernel[h],
temp, emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHd[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = tempSum;
}
double[] tempData = bicubicInpaintingDouble(sumArray,
weightVert, emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVd[offsetY + h];
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = sum;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
} else {
final double[][] pixelKernel = new double[KERNEL_LINE_DIM][KERNEL_LINE_DIM];
double[] sumArray = new double[KERNEL_LINE_DIM];
double[] emptyArray = new double[KERNEL_LINE_DIM];
short weight = 0;
byte weightVert = 0;
byte temp = 0;
for (int y = dst_min_y; y < dst_max_y; y++) {
dstPixelOffset = dstOffset;
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
double s_x = src_pt.getX();
double s_y = src_pt.getY();
s_x -= 0.5;
s_y -= 0.5;
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
fracx = s_x - s_ix * 1.0d;
fracy = s_y - s_iy * 1.0d;
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// Compute clipMinX, clipMinY
javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1,
src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy,
dst_min_x, dst_max_x, 1, 2, 1, 2);
int clipMinX = ((Integer) clipRange.getMinValue()).intValue();
int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue();
// Advance s_ix, s_iy, ifracx, ifracy
Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy,
ifracx, ifracy);
s_ix = startPts[0].x;
s_iy = startPts[0].y;
if (setDestinationNoData) {
for (int x = dst_min_x; x < clipMinX; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
dstPixelOffset += dstPixelStride;
}
} else
// Advance to first pixel
dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride;
for (int x = clipMinX; x < clipMaxX; x++) {
final int posx = (s_ix - srcRectX) * srcPixelStride;
final int posy = (s_iy - srcRectY) * srcScanlineStride;
int x0 = src.getX() + posx / srcPixelStride;
int y0 = src.getY() + posy / srcScanlineStride;
// X and Y offset initialization
final int offsetX = KERNEL_LINE_DIM * (int) (shift * fracx);
final int offsetY = KERNEL_LINE_DIM * (int) (shift * fracy);
final int pos = posx + posy;
if (!roiBounds.contains(x0, y0)) {
if (setDestinationNoData) {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
}
}
} else {
for (int k2 = 0; k2 < dst_num_bands; k2++) {
double sum = 0;
int tmpROI = 0;
// Cycle through all the 16 kernel pixel and calculation of the interpolated value
// and cycle for filling all the ROI index by shifting of 1 on the x axis
// and by 1 on the y axis.
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Selection of one pixel
double value = srcDataArrays[k2][pos + (z - 1)
* srcPixelStride + (h - 1) * srcScanlineStride];
pixelKernel[h][z] = value;
tmpROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff;
if (!noData.contains(value)) {
weight |= (1 << (4 * h + z));
} else {
weight &= (0xffff - (1 << 4 * h + z));
}
}
}
// Control if the 16 pixel are outside the ROI
// Control if the 16 pixel are outside the ROI
if (weight == 0 || tmpROI == 0) {
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
} else {
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Row temporary sum initialization
double tempSum = 0;
temp = (byte) ((weight >> 4 * h) & 0x0F);
double[] tempData = bicubicInpaintingDouble(pixelKernel[h],
temp, emptyArray);
for (int z = 0; z < KERNEL_LINE_DIM; z++) {
// Update of the temporary sum
tempSum += (tempData[z] * dataHd[offsetX + z]);
}
if (temp > 0) {
weightVert |= (1 << h);
} else {
weightVert &= (0x0F - (1 << h));
}
sumArray[h] = tempSum;
}
double[] tempData = bicubicInpaintingDouble(sumArray,
weightVert, emptyArray);
weight = 0;
weightVert = 0;
// Vertical sum update
for (int h = 0; h < KERNEL_LINE_DIM; h++) {
// Update of the temporary sum
sum += tempData[h] * dataVd[offsetY + h];
}
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = sum;
}
}
}
// walk
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
if (fracx == OVERFLOW) {
// Avoid overflow in the interpolation table
fracx = AVOID_OVERFLOW;
}
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
if (fracy == OVERFLOW) {
// Avoid overflow in the interpolation table
fracy = AVOID_OVERFLOW;
}
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
if (setDestinationNoData && clipMinX <= clipMaxX) {
for (int x = clipMaxX; x < dst_max_x; x++) {
for (int k2 = 0; k2 < dst_num_bands; k2++)
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2];
dstPixelOffset += dstPixelStride;
}
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
}
}
private long[] bicubicInpainting(long[] array, short weightSum, long[] emptyArray) {
// Absence of No Data, the pixels are returned.
if (weightSum == 15) {
return array;
}
long s_ = array[0];
long s0 = array[1];
long s1 = array[2];
long s2 = array[3];
emptyArray[0] = 0;
emptyArray[1] = 0;
emptyArray[2] = 0;
emptyArray[3] = 0;
// s2 s1 s0 s_
// 0/x 0/x 0/x 0/x
switch (weightSum) {
case 0:
// 0 0 0 0
break;
case 1:
// 0 0 0 x
emptyArray[0] = s_;
emptyArray[1] = s_;
emptyArray[2] = s_;
emptyArray[3] = s_;
break;
case 2:
// 0 0 x 0
emptyArray[0] = s0;
emptyArray[1] = s0;
emptyArray[2] = s0;
emptyArray[3] = s0;
break;
case 3:
// 0 0 x x
emptyArray[0] = s_;
emptyArray[1] = s0;
emptyArray[2] = s0;
emptyArray[3] = s0;
break;
case 4:
// 0 x 0 0
emptyArray[0] = s1;
emptyArray[1] = s1;
emptyArray[2] = s1;
emptyArray[3] = s1;
break;
case 5:
// 0 x 0 x
emptyArray[0] = s_;
emptyArray[1] = (s_ + s1) / 2;
emptyArray[2] = s1;
emptyArray[3] = s1;
break;
case 6:
// 0 x x 0
emptyArray[0] = s0;
emptyArray[1] = s0;
emptyArray[2] = s1;
emptyArray[3] = s1;
break;
case 7:
// 0 x x x
emptyArray[0] = s_;
emptyArray[1] = s0;
emptyArray[2] = s1;
emptyArray[3] = s1;
break;
case 8:
// x 0 0 0
emptyArray[0] = s2;
emptyArray[1] = s2;
emptyArray[2] = s2;
emptyArray[3] = s2;
break;
case 9:
// x 0 0 x
emptyArray[0] = s_;
emptyArray[1] = (s_ + s2) / 2;
emptyArray[2] = (s_ + s2) / 2;
emptyArray[3] = s2;
break;
case 10:
// x 0 x 0
emptyArray[0] = s0;
emptyArray[1] = s0;
emptyArray[2] = (s0 + s2) / 2;
emptyArray[3] = s2;
break;
case 11:
// x 0 x x
emptyArray[0] = s_;
emptyArray[1] = s0;
emptyArray[2] = (s0 + s2) / 2;
emptyArray[3] = s2;
break;
case 12:
// x x 0 0
emptyArray[0] = s1;
emptyArray[1] = s1;
emptyArray[2] = s1;
emptyArray[3] = s2;
break;
case 13:
// x x 0 x
emptyArray[0] = s_;
emptyArray[1] = (s_ + s1) / 2;
emptyArray[2] = s1;
emptyArray[3] = s2;
break;
case 14:
// x x x 0
emptyArray[0] = s0;
emptyArray[1] = s0;
emptyArray[2] = s1;
emptyArray[3] = s2;
break;
default:
throw new IllegalArgumentException("Array cannot be composed from more than 4 elements");
}
return emptyArray;
}
// This method is used for filling the no data values inside the interpolation kernel with the values of the adjacent pixels
private double[] bicubicInpaintingDouble(double[] array, short weightSum, double[] emptyArray) {
// Absence of No Data, the pixels are returned.
if (weightSum == 15) {
return array;
}
double s_ = array[0];
double s0 = array[1];
double s1 = array[2];
double s2 = array[3];
emptyArray[0] = 0;
emptyArray[1] = 0;
emptyArray[2] = 0;
emptyArray[3] = 0;
switch (weightSum) {
case 0:
// 0 0 0 0
break;
case 1:
// 0 0 0 x
emptyArray[0] = s_;
emptyArray[1] = s_;
emptyArray[2] = s_;
emptyArray[3] = s_;
break;
case 2:
// 0 0 x 0
emptyArray[0] = s0;
emptyArray[1] = s0;
emptyArray[2] = s0;
emptyArray[3] = s0;
break;
case 3:
// 0 0 x x
emptyArray[0] = s_;
emptyArray[1] = s0;
emptyArray[2] = s0;
emptyArray[3] = s0;
break;
case 4:
// 0 x 0 0
emptyArray[0] = s1;
emptyArray[1] = s1;
emptyArray[2] = s1;
emptyArray[3] = s1;
break;
case 5:
// 0 x 0 x
emptyArray[0] = s_;
emptyArray[1] = (s_ + s1) / 2;
emptyArray[2] = s1;
emptyArray[3] = s1;
break;
case 6:
// 0 x x 0
emptyArray[0] = s0;
emptyArray[1] = s0;
emptyArray[2] = s1;
emptyArray[3] = s1;
break;
case 7:
// 0 x x x
emptyArray[0] = s_;
emptyArray[1] = s0;
emptyArray[2] = s1;
emptyArray[3] = s1;
break;
case 8:
// x 0 0 0
emptyArray[0] = s2;
emptyArray[1] = s2;
emptyArray[2] = s2;
emptyArray[3] = s2;
break;
case 9:
// x 0 0 x
emptyArray[0] = s_;
emptyArray[1] = (s_ + s2) / 2;
emptyArray[2] = (s_ + s2) / 2;
emptyArray[3] = s2;
break;
case 10:
// x 0 x 0
emptyArray[0] = s0;
emptyArray[1] = s0;
emptyArray[2] = (s0 + s2) / 2;
emptyArray[3] = s2;
break;
case 11:
// x 0 x x
emptyArray[0] = s_;
emptyArray[1] = s0;
emptyArray[2] = (s0 + s2) / 2;
emptyArray[3] = s2;
break;
case 12:
// x x 0 0
emptyArray[0] = s1;
emptyArray[1] = s1;
emptyArray[2] = s1;
emptyArray[3] = s2;
break;
case 13:
// x x 0 x
emptyArray[0] = s_;
emptyArray[1] = (s_ + s1) / 2;
emptyArray[2] = s1;
emptyArray[3] = s2;
break;
case 14:
// x x x 0
emptyArray[0] = s0;
emptyArray[1] = s0;
emptyArray[2] = s1;
emptyArray[3] = s2;
break;
default:
throw new IllegalArgumentException("Array cannot be composed from more than 4 elements");
}
return emptyArray;
}
}