/* 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 java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferUShort;
import java.awt.image.IndexColorModel;
import java.awt.image.MultiPixelPackedSampleModel;
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.JAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.RasterAccessor;
import javax.media.jai.RasterFormatTag;
import javax.media.jai.iterator.RandomIter;
import com.sun.media.jai.util.ImageUtil;
import it.geosolutions.jaiext.interpolators.InterpolationBicubic;
import it.geosolutions.jaiext.interpolators.InterpolationBilinear;
import it.geosolutions.jaiext.interpolators.InterpolationNearest;
import it.geosolutions.jaiext.interpolators.InterpolationNoData;
import it.geosolutions.jaiext.iterators.RandomIterFactory;
import it.geosolutions.jaiext.range.Range;
public class AffineGeneralOpImage extends AffineOpImage {
/** ROI extender */
final static BorderExtender roiExtender = BorderExtender
.createInstance(BorderExtender.BORDER_ZERO);
/** This field is not null only if it belongs to the InterpolationNearest class */
private InterpolationNearest interpN;
/** This field is not null only if it belongs to the InterpolationBilinear class */
private InterpolationBilinear interpB;
/** This field is not null only if it belongs to the InterpolationBicubicNew class */
private InterpolationBicubic interpBN;
/** Value describing if the image is a binary one */
private boolean isBinary;
/** Subsample bits used for calculating the fractional value between two points */
private int subsampleBits;
/** Interpolation object used for storing the interpolator defined by the user */
private Interpolation interpolator;
/** Shift value to multiply to the fractional value */
private int shiftvalue;
/** Value indicating if roi RasterAccessor should be used on computations */
private boolean useROIAccessor;
/** Destination No Data value */
private double[] destinationNoData;
/** Width of the interpolation kernel */
private int interp_width;
/** Height of the interpolation kernel */
private int interp_height;
/** Left padding of the interpolation kernel */
private int interp_left;
/** Top padding of the interpolation kernel */
private int interp_top;
/** Bottom padding of the interpolation kernel */
private int interp_bottom;
/** Right padding of the interpolation kernel */
private int interp_right;
/** Value indicating if destination No Data must be set if the pixel is outside the source rectangle */
private boolean setDestinationNoData;
/** Destination No Data value for binary image */
private int black;
/**
* Constructor used for interpolator of the class InterpolationNearest
*
* @param nodata
*/
public AffineGeneralOpImage(RenderedImage source, BorderExtender extender, Map config,
ImageLayout layout, AffineTransform transform, Interpolation interp,
boolean useROIAccessor, double[] destinationNoData, boolean setDestinationNoData,
Range nodata) {
super(source, extender, configHelper(config, source), layout, transform, interp, destinationNoData);
affineOpInitialization(source, interp, layout, useROIAccessor, setDestinationNoData, nodata, destinationNoData);
}
// Static method used only for binary images
private static Map configHelper(Map configuration, RenderedImage source) {
SampleModel sm = source.getSampleModel();
boolean binaryImage = (sm instanceof MultiPixelPackedSampleModel)
&& (sm.getSampleSize(0) == 1)
&& (sm.getDataType() == DataBuffer.TYPE_BYTE
|| sm.getDataType() == DataBuffer.TYPE_USHORT || sm.getDataType() == DataBuffer.TYPE_INT);
if (binaryImage) {
// Since this operation deals with packed binary data, we do not need
// to expand the IndexColorModel
Map config;
if (configuration == null) {
config = new RenderingHints(JAI.KEY_REPLACE_INDEX_COLOR_MODEL, Boolean.FALSE);
} else {
config = configuration;
if (!(config.containsKey(JAI.KEY_REPLACE_INDEX_COLOR_MODEL))) {
RenderingHints hints = (RenderingHints) configuration;
config = (RenderingHints) hints.clone();
config.put(JAI.KEY_REPLACE_INDEX_COLOR_MODEL, Boolean.FALSE);
}
}
return config;
} else {
return configuration;
}
}
private void affineOpInitialization(RenderedImage source, Interpolation interp,
ImageLayout layout, boolean useROIAccessor, boolean setDestinationNoData, Range nodata, double[] destNoData) {
SampleModel sm = source.getSampleModel();
// Special case -- if the image is represented using
// a MultiPixelPackedSampleModel and a byte, ushort,
// or int DataBuffer we can access the pixel data directly.
// Note that there is a potential loophole that has not been
// resolved by Java2D as to whether the underlying DataBuffer
// must be of one of the standard types. Here we make the
// assumption that it will be -- we can't check without
// forcing an actual tile to be computed.
//
isBinary = (sm instanceof MultiPixelPackedSampleModel)
&& (sm.getSampleSize(0) == 1)
&& (sm.getDataType() == DataBuffer.TYPE_BYTE
|| sm.getDataType() == DataBuffer.TYPE_USHORT || sm.getDataType() == DataBuffer.TYPE_INT);
// Propagate source's ColorModel and SampleModel but change tile size.
if (isBinary) {
if (layout != null) {
colorModel = layout.getColorModel(source);
} else {
colorModel = source.getColorModel();
}
sampleModel = source.getSampleModel()
.createCompatibleSampleModel(tileWidth, tileHeight);
} else {
// 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) {
sampleModel = source.getSampleModel().createCompatibleSampleModel(tileWidth,
tileHeight);
colorModel = srcColorModel;
}
}
// Interpolator settings
interpolator = interp;
// If both roiBounds and roiIter are not null, they are used in calculation
double[] destNod = null;
if (destNoData != null && destNoData.length > 0) {
destNod = destNoData;
}
if (interpolator instanceof InterpolationNearest) {
interpN = (InterpolationNearest) interpolator;
interpN.setROIBounds(roiBounds);
if(destNod == null){
destNod = new double[]{interpN.getDestinationNoData()};
}
} else if (interpolator instanceof InterpolationBilinear) {
interpB = (InterpolationBilinear) interpolator;
interpB.setROIBounds(roiBounds);
if(destNod == null){
destNod = new double[]{interpB.getDestinationNoData()};
}
} else if (interpolator instanceof InterpolationBicubic) {
interpBN = (InterpolationBicubic) interpolator;
interpBN.setROIBounds(roiBounds);
if (destNod == null) {
destNod = new double[]{interpN.getDestinationNoData()};
}
} else if (backgroundValues != null) {
destNod = backgroundValues;
}
// Define number of bands
int numBands = getSampleModel().getNumBands();
if (destNod == null) {
destNod = new double[numBands];
}
if(destNod.length < numBands){
double[] tmp = new double[numBands];
Arrays.fill(tmp, destNod[0]);
destNod = tmp;
}
this.destinationNoData = destNod;
if (interpolator instanceof InterpolationNoData) {
InterpolationNoData interpolationNoData = (InterpolationNoData) interpolator;
interpolationNoData.setDestinationNoData(destNod[0]);
if (nodata != null) {
hasNoData = true;
interpolationNoData.setNoDataRange(nodata);
}
interpolationNoData.setUseROIAccessor(this.useROIAccessor);
}
// this value is used for binary images
black = ((int) this.destinationNoData[0]) & 1;
// subsample bits used for the bilinear and bicubic interpolation
subsampleBits = interp.getSubsampleBitsH();
// Internal precision required for position calculations
shiftvalue = 1 << subsampleBits;
// Interpolation Kernel dimensions
interp_width = interp.getWidth();
interp_height = interp.getHeight();
interp_left = interp.getLeftPadding();
interp_top = interp.getTopPadding();
interp_right = interp_width - interp_left - 1;
interp_bottom = interp_height - interp_top - 1;
// ROIAccessor can be used only if the interpolator is one of the types:
// InterpolationNearest, InterpolationBilinear, InterpolationBicubicNew.
if (hasROI && (interpN != null || interpB != null || interpBN != null)) {
this.useROIAccessor = useROIAccessor;
} else {
this.useROIAccessor = false;
}
// destination No Data set
this.setDestinationNoData = setDestinationNoData;
}
public Raster computeTile(int tileX, int tileY) {
//
// Create a new WritableRaster to represent this tile.
//
Point org = new Point(tileXToX(tileX), tileYToY(tileY));
WritableRaster dest = createWritableRaster(sampleModel, org);
//
// Clip output rectangle to image bounds.
//
Rectangle rect = new Rectangle(org.x, org.y, tileWidth, tileHeight);
// Destination writable raster band number
int dstBandNum = dest.getNumBands();
// Destination No Data Array definition for filling the entire destination raster
// if it is outside the source bounds
double[] destinationNoDataArray = new double[dstBandNum];
for (int i = 0; i < dstBandNum; i++) {
destinationNoDataArray[i] = destinationNoData[i];
}
//
// Clip destination tile against the writable destination
// area. This is either the layout or a smaller area if
// no extension is specified.
//
Rectangle destRect = rect.intersection(theDest);
Rectangle destRect1 = rect.intersection(getBounds());
if ((destRect.width <= 0) || (destRect.height <= 0)) {
// No area to write
if (setDestinationNoData) {
ImageUtil.fillBackground(dest, destRect1, destinationNoDataArray);
}
return dest;
}
//
// determine the source rectangle needed to compute the destRect
//
Rectangle srcRect = mapDestRect(destRect, 0);
if (extender == null) {
srcRect = srcRect.intersection(srcimg);
} else {
srcRect = srcRect.intersection(padimg);
}
if (!(srcRect.width > 0 && srcRect.height > 0)) {
if (setDestinationNoData) {
ImageUtil.fillBackground(dest, destRect1, destinationNoDataArray);
}
return dest;
}
if (!destRect1.equals(destRect)) {
// beware that destRect1 contains destRect
ImageUtil.fillBordersWithBackgroundValues(destRect1, destRect, dest,
destinationNoDataArray);
}
Raster[] sources = new Raster[1];
Raster[] rois = new Raster[1];
// SourceImage
PlanarImage srcIMG = getSourceImage(0);
// Get the source and ROI data
if (extender == null) {
sources[0] = srcIMG.getData(srcRect);
} else {
if (srcIMG.getBounds().contains(srcRect)) {
sources[0] = srcIMG.getData(srcRect);
} else {
sources[0] = extendedIMG.getData(srcRect);
}
}
// Compute the destination tile.
computeRect(sources, dest, destRect);
// Recycle the source tile
if (getSourceImage(0).overlapsMultipleTiles(srcRect) && !isBinary) {
recycleTile(sources[0]);
}
return dest;
}
/** Method for evaluating the destination image tile with ROI */
protected void computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect) {
// Retrieve format tags.
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.
if (!isBinary) {
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;
}
} else {
dataType = source.getSampleModel().getDataType();
switch (dataType) {
case DataBuffer.TYPE_BYTE:
byteLoopBinary(dataType, srcAccessor, source, dest, destRect, roi, srcRectX,
srcRectY, roiIter);
break;
case DataBuffer.TYPE_INT:
intLoopBinary(dataType, srcAccessor, source, dest, destRect, roi, srcRectX,
srcRectY, roiIter);
break;
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
ushortLoopBinary(dataType, srcAccessor, source, dest, destRect, roi, srcRectX,
srcRectY, 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() && !isBinary) {
dstAccessor.clampDataArrays();
dstAccessor.copyDataToRaster();
}
}
private void byteLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX,
int srcRectY, RasterAccessor dst, RasterAccessor roiAccessor, RandomIter roiIter) {
// Creation of the interpolation kernel for interpolators different from the Interpolation type:
// InterpolationNearest, InterpolationBilinear, InterpolationBicubicNew.
int[][] samples = new int[interp_height][interp_width];
// Integral fractional values for a general interpolator
int xfrac;
int yfrac;
// Source region
float src_rect_x1 = src.getX();
float src_rect_y1 = src.getY();
float src_rect_x2 = src_rect_x1 + src.getWidth();
float src_rect_y2 = src_rect_y1 + src.getHeight();
// destination image pixel offset
int dstPixelOffset;
int dstOffset = 0;
// Destination and source point stored as point2D object
Point2D dst_pt = new Point2D.Float();
Point2D src_pt = new Point2D.Float();
// destination data arrays
byte[][] dstDataArrays = dst.getByteDataArrays();
// Destination band offsets array
int[] dstBandOffsets = dst.getBandOffsets();
// destination pixel stride
int dstPixelStride = dst.getPixelStride();
// destination scanline stride
int dstScanlineStride = dst.getScanlineStride();
// source image data array
byte[][] srcDataArrays = src.getByteDataArrays();
// source image band offsets array
int[] bandOffsets = src.getBandOffsets();
// source pixel stride
int srcPixelStride = src.getPixelStride();
// source scanline stride
int srcScanlineStride = src.getScanlineStride();
// destination band number
int dst_num_bands = dst.getNumBands();
// ROI scanline stride
int roiScanlineStride = 0;
if (roiAccessor != null) {
roiScanlineStride = roiAccessor.getScanlineStride();
}
// Destination bounds
int dst_min_x = destRect.x;
int dst_min_y = destRect.y;
int dst_max_x = destRect.x + destRect.width;
int dst_max_y = destRect.y + destRect.height;
// ROI position initialization
Integer posyROI = null;
// Fractional array initialization
Number[] fracValues = new Number[2];
// Cycle on the destination image y bounds
for (int y = dst_min_y; y < dst_max_y; y++) {
// update of the destination pixel offset
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((double) dst_min_x + 0.5, (double) y + 0.5);
// Backward mapping of the destination point position
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
// As per definition of bilinear or bicubic interpolation
if (interpN == null || !(interp instanceof InterpolationNearest)) {
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);
// Calculation of the fractional values
float fracx = s_x - (float) s_ix;
float fracy = s_y - (float) s_iy;
// Get the new frac values
xfrac = (int) (fracx * shiftvalue);
yfrac = (int) (fracy * shiftvalue);
// Store of the fractional value inside an array
if (dataType < DataBuffer.TYPE_FLOAT) {
fracValues[0] = xfrac;
fracValues[1] = yfrac;
} else {
fracValues[0] = fracx;
fracValues[1] = fracy;
}
// Translate to/from SampleModel space & Raster space
int posy = (s_iy - srcRectY) * srcScanlineStride;
int posx = (s_ix - srcRectX) * srcPixelStride;
// Conversion if the fractional values to integer ones for Nearest-Neighbor interpolation
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// If roiAccessor is present, the y position on the roi image is calculated
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Cycle on the destination image x bounds
for (int x = dst_min_x; x < dst_max_x; x++) {
//
// Check against the source rectangle
//
if ((s_ix >= src_rect_x1 + interp_left) && (s_ix < (src_rect_x2 - interp_right))
&& (s_iy >= src_rect_y1 + interp_top)
&& (s_iy < (src_rect_y2 - interp_bottom))) {
// Cycle on all the image bands
for (int k2 = 0; k2 < dst_num_bands; k2++) {
// initial value for the output sample
float result = 0;
int s = 0;
int posyy = posy + bandOffsets[k2];
// Control for using the defined interpolator
if (interpN != null) {
result = interpN.interpolate(src, k2, dst_num_bands, posx, posyy,
posyROI, roiAccessor, roiIter, false).intValue();
} else if (interpB != null) {
result = interpB.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).intValue();
} else if (interpBN != null) {
result = interpBN.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).intValue();
// Case of general interpolator (ROI and No Data not supported)
} else {
// Source data array of the selected band
byte[] srcData = srcDataArrays[k2];
// Offset of the selected band
int tmp = bandOffsets[k2];
// Get the pixels required for this interpolation
int start = interp_left * srcPixelStride + interp_top
* srcScanlineStride;
// Initial array index of the selected pixel
start = posx + posy - start;
// Initial value for the counter for filling the interpolation kernel
int countH = 0, countV = 0;
// cycle on the x and y directions
for (int i = 0; i < interp_height; i++) {
int startY = start;
for (int j = 0; j < interp_width; j++) {
// interpolation kernel value addition
samples[countV][countH++] = srcData[start + tmp] & 0xff;
// update of the array index on the x direction
start += srcPixelStride;
}
// Update of the counter on the y axis and reset of the one on the X axis
countV++;
countH = 0;
// update of the array index on the y direction
start = startY + srcScanlineStride;
}
// Get the new frac values
xfrac = (int) (fracx * shiftvalue);
yfrac = (int) (fracy * shiftvalue);
// Do the interpolation
result = interp.interpolate(samples, xfrac, yfrac);
}
if (interpN == null || !(interp instanceof InterpolationNearest)) {
// Clamp
if (result < 0.5f) {
s = 0;
} else if (result > 254.5f) {
s = 255;
} else {
s = (int) result;
}
} else {
s = (int) result;
}
// Write the result
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (s & 0xff);
}
// If the pixel is outside bounds and is possible to set
} else if (setDestinationNoData) {
for (int k = 0; k < dst_num_bands; k++) {
dstDataArrays[k][dstPixelOffset + dstBandOffsets[k]] = (byte) destinationNoData[k];
}
}
// walk
if (interpN == null || !(interp instanceof InterpolationNearest)) {
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// If interpolation Nearest is used, then the
} else {
if (ifracx < ifracdx1) {
s_ix += incx;
ifracx += ifracdx;
} else {
s_ix += incx1;
ifracx -= ifracdx1;
}
if (ifracy < ifracdy1) {
s_iy += incy;
ifracy += ifracdy;
} else {
s_iy += incy1;
ifracy -= ifracdy1;
}
}
// Translate to/from SampleModel space & Raster space
posy = (s_iy - srcRectY) * srcScanlineStride;
posx = (s_ix - srcRectX) * srcPixelStride;
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
private void byteLoopBinary(int dataType, RasterAccessor src, Raster source,
WritableRaster dest, Rectangle destRect, Raster roi, int srcRectX, int srcRectY, RandomIter roiIter) {
float src_rect_x1 = source.getMinX();
float src_rect_y1 = source.getMinY();
float src_rect_x2 = src_rect_x1 + source.getWidth();
float src_rect_y2 = src_rect_y1 + source.getHeight();
MultiPixelPackedSampleModel sourceSM = (MultiPixelPackedSampleModel) source
.getSampleModel();
DataBufferByte sourceDB = (DataBufferByte) source.getDataBuffer();
int sourceTransX = source.getSampleModelTranslateX();
int sourceTransY = source.getSampleModelTranslateY();
int sourceDataBitOffset = sourceSM.getDataBitOffset();
int sourceScanlineStride = sourceSM.getScanlineStride();
int sourcePixelStride = sourceSM.getPixelBitStride();
MultiPixelPackedSampleModel destSM = (MultiPixelPackedSampleModel) dest.getSampleModel();
DataBufferByte destDB = (DataBufferByte) dest.getDataBuffer();
int destTransX = dest.getSampleModelTranslateX();
int destTransY = dest.getSampleModelTranslateY();
int destDataBitOffset = destSM.getDataBitOffset();
int destScanlineStride = destSM.getScanlineStride();
byte[] sourceData = sourceDB.getData();
Number[] sourceDataNum = new Number[sourceData.length];
for (int i = 0; i < sourceData.length; i++) {
sourceDataNum[i] = sourceData[i];
}
int sourceDBOffset = sourceDB.getOffset();
byte[] destData = destDB.getData();
int destDBOffset = destDB.getOffset();
Point2D dst_pt = new Point2D.Float();
Point2D src_pt = new Point2D.Float();
int dst_min_x = destRect.x;
int dst_min_y = destRect.y;
int dst_max_x = destRect.x + destRect.width;
int dst_max_y = destRect.y + destRect.height;
// Output value initialization
int s = 0;
// pixel value coordinates initialization
int[] coordinates = new int[2];
int[] roiData = null;
int roiDBOffset = 0;
MultiPixelPackedSampleModel roiSM = null;
// int roiTransX =0;
int roiTransY = 0;
// int roiDataBitOffset =0;
int roiScanlineStride = 0;
if (roi != null) {
roiSM = (MultiPixelPackedSampleModel) roi.getSampleModel();
// roiTransX = roi.getSampleModelTranslateX();
roiTransY = roi.getSampleModelTranslateY();
// roiDataBitOffset = roiSM.getDataBitOffset();
roiScanlineStride = roiSM.getScanlineStride();
DataBuffer roiDB = roi.getDataBuffer();
roiDBOffset = roiDB.getOffset();
DataBufferByte roiDBByte = (DataBufferByte) roiDB;
byte[] roiDataB = roiDBByte.getData();
roiData = new int[roiDataB.length];
for (int ii = 0; ii < roiDataB.length; ii++) {
roiData[ii] = roiDataB[ii];
}
}
for (int y = dst_min_y; y < dst_max_y; y++) {
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation((double) dst_min_x + 0.5, (double) y + 0.5);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
double fracx = s_x - (double) s_ix;
double fracy = s_y - (double) s_iy;
// Get the new frac values
int xfrac = (int) (fracx * shiftvalue);
int yfrac = (int) (fracy * shiftvalue);
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
int destYOffset = (y - destTransY) * destScanlineStride + destDBOffset;
int destXOffset = destDataBitOffset + (dst_min_x - destTransX);
int sourceYOffset = (s_iy - sourceTransY) * sourceScanlineStride + sourceDBOffset;
// int sourceXOffset = s_ix - sourceTransX + sourceDataBitOffset;
int roiYOffset = (s_iy - roiTransY) * roiScanlineStride + roiDBOffset;
// Cycle on the destination image x bounds
for (int x = dst_min_x; x < dst_max_x; x++) {
sourceYOffset = (s_iy - sourceTransY) * sourceScanlineStride + sourceDBOffset;
roiYOffset = (s_iy - roiTransY) * roiScanlineStride + roiDBOffset;
int dindex = 0;
// int delement = 0;
//
// Check against the source rectangle
//
if ((s_ix >= src_rect_x1 + interp_left) && (s_ix < (src_rect_x2 - interp_right))
&& (s_iy >= src_rect_y1 + interp_top)
&& (s_iy < (src_rect_y2 - interp_bottom))) {
coordinates[0] = src.getX() + (s_ix - srcRectX) * sourcePixelStride;
;
coordinates[1] = src.getY() + ((s_iy - srcRectY) * sourceScanlineStride)
/ sourceScanlineStride;
int xNextBitNo = sourceDataBitOffset + (s_ix + 1 - sourceTransX);
if (interpN != null) {
s = interpN.interpolateBinary(xNextBitNo, sourceDataNum, sourceYOffset,
sourceScanlineStride, coordinates, roiData, roiYOffset,
roiScanlineStride, roiIter);
} else if (interpB != null) {
s = interpB.interpolateBinary(xNextBitNo, sourceDataNum, xfrac, yfrac,
sourceYOffset, sourceScanlineStride, coordinates, roiData,
roiYOffset, roiScanlineStride, roiIter);
} else if (interpBN != null) {
s = interpBN.interpolateBinary(xNextBitNo, sourceDataNum, xfrac, yfrac,
sourceYOffset, sourceScanlineStride, coordinates, roiData,
roiYOffset, roiScanlineStride, roiIter);
} else {
throw new UnsupportedOperationException(
"Binary interpolation not supported for interpolators different from"
+ "InterpolatorNearestNew,InterpolatorBinaryNew,InterpolatorBicubicNew");
}
} else if (setDestinationNoData) {
s = black;
}
dindex = destYOffset + (destXOffset >> 3);
int dshift = 7 - (destXOffset & 7);
// delement = destData[dindex];
// delement |= s << dshift;
//
// destData[dindex] = (byte) delement;
if (s == 1) {
destData[dindex] |= (0x01 << dshift);
} else {
destData[dindex] &= (0xff - (0x01 << dshift));
}
// walk
if (interpN == null || !(interp instanceof InterpolationNearest)) {
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// If interpolation Nearest is used, then the
} else {
if (ifracx < ifracdx1) {
s_ix += incx;
ifracx += ifracdx;
} else {
s_ix += incx1;
ifracx -= ifracdx1;
}
if (ifracy < ifracdy1) {
s_iy += incy;
ifracy += ifracdy;
} else {
s_iy += incy1;
ifracy -= ifracdy1;
}
}
++destXOffset;
}
}
}
private void ushortLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX,
int srcRectY, RasterAccessor dst, RasterAccessor roiAccessor, RandomIter roiIter) {
// Creation of the interpolation kernel for interpolators different from the Interpolation type:
// InterpolationNearest, InterpolationBilinear, InterpolationBicubicNew.
int[][] samples = new int[interp_height][interp_width];
// Integral fractional values for a general interpolator
int xfrac;
int yfrac;
// Source region
float src_rect_x1 = src.getX();
float src_rect_y1 = src.getY();
float src_rect_x2 = src_rect_x1 + src.getWidth();
float src_rect_y2 = src_rect_y1 + src.getHeight();
// destination image pixel offset
int dstPixelOffset;
int dstOffset = 0;
// Destination and source point stored as point2D object
Point2D dst_pt = new Point2D.Float();
Point2D src_pt = new Point2D.Float();
// destination data arrays
short[][] dstDataArrays = dst.getShortDataArrays();
// Destination band offsets array
int[] dstBandOffsets = dst.getBandOffsets();
// destination pixel stride
int dstPixelStride = dst.getPixelStride();
// destination scanline stride
int dstScanlineStride = dst.getScanlineStride();
// source image data array
short[][] srcDataArrays = src.getShortDataArrays();
// source image band offsets array
int[] bandOffsets = src.getBandOffsets();
// source pixel stride
int srcPixelStride = src.getPixelStride();
// source scanline stride
int srcScanlineStride = src.getScanlineStride();
// destination band number
int dst_num_bands = dst.getNumBands();
// ROI scanline stride
int roiScanlineStride = 0;
if (roiAccessor != null) {
roiScanlineStride = roiAccessor.getScanlineStride();
}
// Destination bounds
int dst_min_x = destRect.x;
int dst_min_y = destRect.y;
int dst_max_x = destRect.x + destRect.width;
int dst_max_y = destRect.y + destRect.height;
// ROI position initialization
Integer posyROI = null;
// Fractional array initialization
Number[] fracValues = new Number[2];
// Cycle on the destination image y bounds
for (int y = dst_min_y; y < dst_max_y; y++) {
// update of the destination pixel offset
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((double) dst_min_x + 0.5, (double) y + 0.5);
// Backward mapping of the destination point position
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
// As per definition of bilinear or bicubic interpolation
if (interpN == null || !(interp instanceof InterpolationNearest)) {
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);
// Calculation of the fractional values
float fracx = s_x - (float) s_ix;
float fracy = s_y - (float) s_iy;
// Get the new frac values
xfrac = (int) (fracx * shiftvalue);
yfrac = (int) (fracy * shiftvalue);
// Store of the fractional value inside an array
if (dataType < DataBuffer.TYPE_FLOAT) {
fracValues[0] = xfrac;
fracValues[1] = yfrac;
} else {
fracValues[0] = fracx;
fracValues[1] = fracy;
}
// Translate to/from SampleModel space & Raster space
int posy = (s_iy - srcRectY) * srcScanlineStride;
int posx = (s_ix - srcRectX) * srcPixelStride;
// Conversion if the fractional values to integer ones for Nearest-Neighbor interpolation
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// If roiAccessor is present, the y position on the roi image is calculated
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Cycle on the destination image x bounds
for (int x = dst_min_x; x < dst_max_x; x++) {
//
// Check against the source rectangle
//
if ((s_ix >= src_rect_x1 + interp_left) && (s_ix < (src_rect_x2 - interp_right))
&& (s_iy >= src_rect_y1 + interp_top)
&& (s_iy < (src_rect_y2 - interp_bottom))) {
// Cycle on all the image bands
for (int k2 = 0; k2 < dst_num_bands; k2++) {
// initial value for the output sample
float result = 0;
int s = 0;
int posyy = posy + bandOffsets[k2];
// Control for using the defined interpolator
if (interpN != null) {
result = interpN.interpolate(src, k2, dst_num_bands, posx, posyy,
posyROI, roiAccessor, roiIter, false).intValue();
} else if (interpB != null) {
result = interpB.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).intValue();
} else if (interpBN != null) {
result = interpBN.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).intValue();
// Case of general interpolator (ROI and No Data not supported)
} else {
// Source data array of the selected band
short[] srcData = srcDataArrays[k2];
// Offset of the selected band
int tmp = bandOffsets[k2];
// Get the pixels required for this interpolation
int start = interp_left * srcPixelStride + interp_top
* srcScanlineStride;
// Initial array index of the selected pixel
start = posx + posy - start;
// Initial value for the counter for filling the interpolation kernel
int countH = 0, countV = 0;
// cycle on the x and y directions
for (int i = 0; i < interp_height; i++) {
int startY = start;
for (int j = 0; j < interp_width; j++) {
// interpolation kernel value addition
samples[countV][countH++] = srcData[start + tmp] & 0xffff;
// update of the array index on the x direction
start += srcPixelStride;
}
// Update of the counter on the y axis and reset of the one on the X axis
countV++;
countH = 0;
// update of the array index on the y direction
start = startY + srcScanlineStride;
}
// Get the new frac values
xfrac = (int) (fracx * shiftvalue);
yfrac = (int) (fracy * shiftvalue);
// Do the interpolation
result = interp.interpolate(samples, xfrac, yfrac);
}
if (interpN == null || !(interp instanceof InterpolationNearest)) {
// Clamp
if (result < 0.0f) {
s = 0;
} else if (result > USHORT_MAX_VALUE) {
s = USHORT_MAX_VALUE;
} else {
s = (int) result;
}
} else {
s = (int) result;
}
// Write the result
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (s & 0xffff);
}
// If the pixel is outside bounds and is possible to set
} else if (setDestinationNoData) {
for (int k = 0; k < dst_num_bands; k++) {
dstDataArrays[k][dstPixelOffset + dstBandOffsets[k]] = (short) destinationNoData[k];
}
}
// walk
if (interpN == null || !(interp instanceof InterpolationNearest)) {
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// If interpolation Nearest is used, then the
} else {
if (ifracx < ifracdx1) {
s_ix += incx;
ifracx += ifracdx;
} else {
s_ix += incx1;
ifracx -= ifracdx1;
}
if (ifracy < ifracdy1) {
s_iy += incy;
ifracy += ifracdy;
} else {
s_iy += incy1;
ifracy -= ifracdy1;
}
}
// Translate to/from SampleModel space & Raster space
posy = (s_iy - srcRectY) * srcScanlineStride;
posx = (s_ix - srcRectX) * srcPixelStride;
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
private void ushortLoopBinary(int dataType, RasterAccessor src, Raster source,
WritableRaster dest, Rectangle destRect, Raster roi, int srcRectX, int srcRectY, RandomIter roiIter) {
float src_rect_x1 = source.getMinX();
float src_rect_y1 = source.getMinY();
float src_rect_x2 = src_rect_x1 + source.getWidth();
float src_rect_y2 = src_rect_y1 + source.getHeight();
MultiPixelPackedSampleModel sourceSM = (MultiPixelPackedSampleModel) source
.getSampleModel();
DataBuffer sourceDBUS = source.getDataBuffer();
DataBufferUShort sourceDB = (DataBufferUShort) sourceDBUS;
int sourceTransX = source.getSampleModelTranslateX();
int sourceTransY = source.getSampleModelTranslateY();
int sourceDataBitOffset = sourceSM.getDataBitOffset();
int sourceScanlineStride = sourceSM.getScanlineStride();
int sourcePixelStride = sourceSM.getPixelBitStride();
MultiPixelPackedSampleModel destSM = (MultiPixelPackedSampleModel) dest.getSampleModel();
DataBufferUShort destDB = (DataBufferUShort) dest.getDataBuffer();
int destTransX = dest.getSampleModelTranslateX();
int destTransY = dest.getSampleModelTranslateY();
int destDataBitOffset = destSM.getDataBitOffset();
int destScanlineStride = destSM.getScanlineStride();
short[] sourceData = sourceDB.getData();
Number[] sourceDataNum = new Number[sourceData.length];
for (int i = 0; i < sourceData.length; i++) {
sourceDataNum[i] = sourceData[i];
}
int sourceDBOffset = sourceDB.getOffset();
short[] destData = destDB.getData();
int destDBOffset = destDB.getOffset();
Point2D dst_pt = new Point2D.Float();
Point2D src_pt = new Point2D.Float();
int dst_min_x = destRect.x;
int dst_min_y = destRect.y;
int dst_max_x = destRect.x + destRect.width;
int dst_max_y = destRect.y + destRect.height;
// Output value initialization
int s = 0;
// pixel value coordinates initialization
int[] coordinates = new int[2];
int[] roiData = null;
int roiDBOffset = 0;
MultiPixelPackedSampleModel roiSM = null;
// int roiTransX =0;
int roiTransY = 0;
// int roiDataBitOffset =0;
int roiScanlineStride = 0;
if (roi != null) {
roiSM = (MultiPixelPackedSampleModel) roi.getSampleModel();
// roiTransX = roi.getSampleModelTranslateX();
roiTransY = roi.getSampleModelTranslateY();
// roiDataBitOffset = roiSM.getDataBitOffset();
roiScanlineStride = roiSM.getScanlineStride();
DataBuffer roiDB = roi.getDataBuffer();
roiDBOffset = roiDB.getOffset();
DataBufferByte roiDBByte = (DataBufferByte) roiDB;
byte[] roiDataB = roiDBByte.getData();
roiData = new int[roiDataB.length];
for (int ii = 0; ii < roiDataB.length; ii++) {
roiData[ii] = roiDataB[ii];
}
}
for (int y = dst_min_y; y < dst_max_y; y++) {
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation((double) dst_min_x + 0.5, (double) y + 0.5);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
double fracx = s_x - (double) s_ix;
double fracy = s_y - (double) s_iy;
// Get the new frac values
int xfrac = (int) (fracx * shiftvalue);
int yfrac = (int) (fracy * shiftvalue);
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
int destYOffset = (y - destTransY) * destScanlineStride + destDBOffset;
int destXOffset = destDataBitOffset + (dst_min_x - destTransX);
int sourceYOffset = (s_iy - sourceTransY) * sourceScanlineStride + sourceDBOffset;
// int sourceXOffset = s_ix - sourceTransX + sourceDataBitOffset;
int roiYOffset = (s_iy - roiTransY) * roiScanlineStride + roiDBOffset;
// Cycle on the destination image x bounds
for (int x = dst_min_x; x < dst_max_x; x++) {
sourceYOffset = (s_iy - sourceTransY) * sourceScanlineStride + sourceDBOffset;
roiYOffset = (s_iy - roiTransY) * roiScanlineStride + roiDBOffset;
int dindex = 0;
int dshift;
// int delement = 0;
//
// Check against the source rectangle
//
if ((s_ix >= src_rect_x1 + interp_left) && (s_ix < (src_rect_x2 - interp_right))
&& (s_iy >= src_rect_y1 + interp_top)
&& (s_iy < (src_rect_y2 - interp_bottom))) {
coordinates[0] = src.getX() + (s_ix - srcRectX) * sourcePixelStride;
;
coordinates[1] = src.getY() + ((s_iy - srcRectY) * sourceScanlineStride)
/ sourceScanlineStride;
int xNextBitNo = sourceDataBitOffset + (s_ix + 1 - sourceTransX);
if (interpN != null) {
s = interpN.interpolateBinary(xNextBitNo, sourceDataNum, sourceYOffset,
sourceScanlineStride, coordinates, roiData, roiYOffset,
roiScanlineStride, roiIter);
} else if (interpB != null) {
s = interpB.interpolateBinary(xNextBitNo, sourceDataNum, xfrac, yfrac,
sourceYOffset, sourceScanlineStride, coordinates, roiData,
roiYOffset, roiScanlineStride, roiIter);
} else if (interpBN != null) {
s = interpBN.interpolateBinary(xNextBitNo, sourceDataNum, xfrac, yfrac,
sourceYOffset, sourceScanlineStride, coordinates, roiData,
roiYOffset, roiScanlineStride, roiIter);
} else {
throw new UnsupportedOperationException(
"Binary interpolation not supported for interpolators different from"
+ "InterpolatorNearestNew,InterpolatorBinaryNew,InterpolatorBicubicNew");
}
} else if (setDestinationNoData) {
s = black;
}
dindex = destYOffset + (destXOffset >> 4);
dshift = 15 - (destXOffset & 15);
// delement = destData[dindex];
// delement |= s << dshift;
//
// destData[dindex] = (short) delement;
if (s == 1) {
destData[dindex] |= (0x01 << dshift);
} else {
destData[dindex] &= (0xffff - (0x01 << dshift));
}
// walk
if (interpN == null || !(interp instanceof InterpolationNearest)) {
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// If interpolation Nearest is used, then the
} else {
if (ifracx < ifracdx1) {
s_ix += incx;
ifracx += ifracdx;
} else {
s_ix += incx1;
ifracx -= ifracdx1;
}
if (ifracy < ifracdy1) {
s_iy += incy;
ifracy += ifracdy;
} else {
s_iy += incy1;
ifracy -= ifracdy1;
}
}
++destXOffset;
}
}
}
private void shortLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX,
int srcRectY, RasterAccessor dst, RasterAccessor roiAccessor, RandomIter roiIter) {
// Creation of the interpolation kernel for interpolators different from the Interpolation type:
// InterpolationNearest, InterpolationBilinear, InterpolationBicubicNew.
int[][] samples = new int[interp_height][interp_width];
// Integral fractional values for a general interpolator
int xfrac;
int yfrac;
// Source region
float src_rect_x1 = src.getX();
float src_rect_y1 = src.getY();
float src_rect_x2 = src_rect_x1 + src.getWidth();
float src_rect_y2 = src_rect_y1 + src.getHeight();
// destination image pixel offset
int dstPixelOffset;
int dstOffset = 0;
// Destination and source point stored as point2D object
Point2D dst_pt = new Point2D.Float();
Point2D src_pt = new Point2D.Float();
// destination data arrays
short[][] dstDataArrays = dst.getShortDataArrays();
// Destination band offsets array
int[] dstBandOffsets = dst.getBandOffsets();
// destination pixel stride
int dstPixelStride = dst.getPixelStride();
// destination scanline stride
int dstScanlineStride = dst.getScanlineStride();
// source image data array
short[][] srcDataArrays = src.getShortDataArrays();
// source image band offsets array
int[] bandOffsets = src.getBandOffsets();
// source pixel stride
int srcPixelStride = src.getPixelStride();
// source scanline stride
int srcScanlineStride = src.getScanlineStride();
// destination band number
int dst_num_bands = dst.getNumBands();
// ROI scanline stride
int roiScanlineStride = 0;
if (roiAccessor != null) {
roiScanlineStride = roiAccessor.getScanlineStride();
}
// Destination bounds
int dst_min_x = destRect.x;
int dst_min_y = destRect.y;
int dst_max_x = destRect.x + destRect.width;
int dst_max_y = destRect.y + destRect.height;
// ROI position initialization
Integer posyROI = null;
// Fractional array initialization
Number[] fracValues = new Number[2];
// Cycle on the destination image y bounds
for (int y = dst_min_y; y < dst_max_y; y++) {
// update of the destination pixel offset
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((double) dst_min_x + 0.5, (double) y + 0.5);
// Backward mapping of the destination point position
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
// As per definition of bilinear or bicubic interpolation
if (interpN == null || !(interp instanceof InterpolationNearest)) {
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);
// Calculation of the fractional values
float fracx = s_x - (float) s_ix;
float fracy = s_y - (float) s_iy;
// Get the new frac values
xfrac = (int) (fracx * shiftvalue);
yfrac = (int) (fracy * shiftvalue);
// Store of the fractional value inside an array
if (dataType < DataBuffer.TYPE_FLOAT) {
fracValues[0] = xfrac;
fracValues[1] = yfrac;
} else {
fracValues[0] = fracx;
fracValues[1] = fracy;
}
// Translate to/from SampleModel space & Raster space
int posy = (s_iy - srcRectY) * srcScanlineStride;
int posx = (s_ix - srcRectX) * srcPixelStride;
// Conversion if the fractional values to integer ones for Nearest-Neighbor interpolation
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// If roiAccessor is present, the y position on the roi image is calculated
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Cycle on the destination image x bounds
for (int x = dst_min_x; x < dst_max_x; x++) {
//
// Check against the source rectangle
//
if ((s_ix >= src_rect_x1 + interp_left) && (s_ix < (src_rect_x2 - interp_right))
&& (s_iy >= src_rect_y1 + interp_top)
&& (s_iy < (src_rect_y2 - interp_bottom))) {
// Cycle on all the image bands
for (int k2 = 0; k2 < dst_num_bands; k2++) {
// initial value for the output sample
float result = 0;
int s = 0;
int posyy = posy + bandOffsets[k2];
// Control for using the defined interpolator
if (interpN != null) {
result = interpN.interpolate(src, k2, dst_num_bands, posx, posyy,
posyROI, roiAccessor, roiIter, false).intValue();
} else if (interpB != null) {
result = interpB.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).intValue();
} else if (interpBN != null) {
result = interpBN.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).intValue();
// Case of general interpolator (ROI and No Data not supported)
} else {
// Source data array of the selected band
short[] srcData = srcDataArrays[k2];
// Offset of the selected band
int tmp = bandOffsets[k2];
// Get the pixels required for this interpolation
int start = interp_left * srcPixelStride + interp_top
* srcScanlineStride;
// Initial array index of the selected pixel
start = posx + posy - start;
// Initial value for the counter for filling the interpolation kernel
int countH = 0, countV = 0;
// cycle on the x and y directions
for (int i = 0; i < interp_height; i++) {
int startY = start;
for (int j = 0; j < interp_width; j++) {
// interpolation kernel value addition
samples[countV][countH++] = srcData[start + tmp];
// update of the array index on the x direction
start += srcPixelStride;
}
// Update of the counter on the y axis and reset of the one on the X axis
countV++;
countH = 0;
// update of the array index on the y direction
start = startY + srcScanlineStride;
}
// Get the new frac values
xfrac = (int) (fracx * shiftvalue);
yfrac = (int) (fracy * shiftvalue);
// Do the interpolation
result = interp.interpolate(samples, xfrac, yfrac);
}
// Clamp
if (result < ((float) Short.MIN_VALUE)) {
s = Short.MIN_VALUE;
} else if (result > ((float) Short.MAX_VALUE)) {
s = Short.MAX_VALUE;
} else {
s = (int) result;
}
// Write the result
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) s;
}
// If the pixel is outside bounds and is possible to set
} else if (setDestinationNoData) {
for (int k = 0; k < dst_num_bands; k++) {
dstDataArrays[k][dstPixelOffset + dstBandOffsets[k]] = (short) destinationNoData[k];
}
}
// walk
if (interpN == null || !(interp instanceof InterpolationNearest)) {
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// If interpolation Nearest is used, then the
} else {
if (ifracx < ifracdx1) {
s_ix += incx;
ifracx += ifracdx;
} else {
s_ix += incx1;
ifracx -= ifracdx1;
}
if (ifracy < ifracdy1) {
s_iy += incy;
ifracy += ifracdy;
} else {
s_iy += incy1;
ifracy -= ifracdy1;
}
}
// Translate to/from SampleModel space & Raster space
posy = (s_iy - srcRectY) * srcScanlineStride;
posx = (s_ix - srcRectX) * srcPixelStride;
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Go to next pixel
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 roiAccessor, RandomIter roiIter) {
// Creation of the interpolation kernel for interpolators different from the Interpolation type:
// InterpolationNearest, InterpolationBilinear, InterpolationBicubicNew.
int[][] samples = new int[interp_height][interp_width];
// Integral fractional values for a general interpolator
int xfrac;
int yfrac;
// Source region
float src_rect_x1 = src.getX();
float src_rect_y1 = src.getY();
float src_rect_x2 = src_rect_x1 + src.getWidth();
float src_rect_y2 = src_rect_y1 + src.getHeight();
// destination image pixel offset
int dstPixelOffset;
int dstOffset = 0;
// Destination and source point stored as point2D object
Point2D dst_pt = new Point2D.Float();
Point2D src_pt = new Point2D.Float();
// destination data arrays
int[][] dstDataArrays = dst.getIntDataArrays();
// Destination band offsets array
int[] dstBandOffsets = dst.getBandOffsets();
// destination pixel stride
int dstPixelStride = dst.getPixelStride();
// destination scanline stride
int dstScanlineStride = dst.getScanlineStride();
// source image data array
int[][] srcDataArrays = src.getIntDataArrays();
// source image band offsets array
int[] bandOffsets = src.getBandOffsets();
// source pixel stride
int srcPixelStride = src.getPixelStride();
// source scanline stride
int srcScanlineStride = src.getScanlineStride();
// destination band number
int dst_num_bands = dst.getNumBands();
// ROI scanline stride
int roiScanlineStride = 0;
if (roiAccessor != null) {
roiScanlineStride = roiAccessor.getScanlineStride();
}
// Destination bounds
int dst_min_x = destRect.x;
int dst_min_y = destRect.y;
int dst_max_x = destRect.x + destRect.width;
int dst_max_y = destRect.y + destRect.height;
// ROI position initialization
Integer posyROI = null;
// Fractional array initialization
Number[] fracValues = new Number[2];
// Cycle on the destination image y bounds
for (int y = dst_min_y; y < dst_max_y; y++) {
// update of the destination pixel offset
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((double) dst_min_x + 0.5, (double) y + 0.5);
// Backward mapping of the destination point position
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
// As per definition of bilinear or bicubic interpolation
if (interpN == null || !(interp instanceof InterpolationNearest)) {
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);
// Calculation of the fractional values
float fracx = s_x - (float) s_ix;
float fracy = s_y - (float) s_iy;
// Get the new frac values
xfrac = (int) (fracx * shiftvalue);
yfrac = (int) (fracy * shiftvalue);
// Store of the fractional value inside an array
if (dataType < DataBuffer.TYPE_FLOAT) {
fracValues[0] = xfrac;
fracValues[1] = yfrac;
} else {
fracValues[0] = fracx;
fracValues[1] = fracy;
}
// Translate to/from SampleModel space & Raster space
int posy = (s_iy - srcRectY) * srcScanlineStride;
int posx = (s_ix - srcRectX) * srcPixelStride;
// Conversion if the fractional values to integer ones for Nearest-Neighbor interpolation
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// If roiAccessor is present, the y position on the roi image is calculated
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Cycle on the destination image x bounds
for (int x = dst_min_x; x < dst_max_x; x++) {
//
// Check against the source rectangle
//
if ((s_ix >= src_rect_x1 + interp_left) && (s_ix < (src_rect_x2 - interp_right))
&& (s_iy >= src_rect_y1 + interp_top)
&& (s_iy < (src_rect_y2 - interp_bottom))) {
// Cycle on all the image bands
for (int k2 = 0; k2 < dst_num_bands; k2++) {
// initial value for the output sample
float result = 0;
int s = 0;
int posyy = posy + bandOffsets[k2];
// Control for using the defined interpolator
if (interpN != null) {
result = interpN.interpolate(src, k2, dst_num_bands, posx, posyy,
posyROI, roiAccessor, roiIter, false).intValue();
} else if (interpB != null) {
result = interpB.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).intValue();
} else if (interpBN != null) {
result = interpBN.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).intValue();
// Case of general interpolator (ROI and No Data not supported)
} else {
// Source data array of the selected band
int[] srcData = srcDataArrays[k2];
// Offset of the selected band
int tmp = bandOffsets[k2];
// Get the pixels required for this interpolation
int start = interp_left * srcPixelStride + interp_top
* srcScanlineStride;
// Initial array index of the selected pixel
start = posx + posy - start;
// Initial value for the counter for filling the interpolation kernel
int countH = 0, countV = 0;
// cycle on the x and y directions
for (int i = 0; i < interp_height; i++) {
int startY = start;
for (int j = 0; j < interp_width; j++) {
// interpolation kernel value addition
samples[countV][countH++] = srcData[start + tmp];
// update of the array index on the x direction
start += srcPixelStride;
}
// Update of the counter on the y axis and reset of the one on the X axis
countV++;
countH = 0;
// update of the array index on the y direction
start = startY + srcScanlineStride;
}
// Get the new frac values
xfrac = (int) (fracx * shiftvalue);
yfrac = (int) (fracy * shiftvalue);
// Do the interpolation
result = interp.interpolate(samples, xfrac, yfrac);
}
// Clamp
if (result < ((float) Integer.MIN_VALUE)) {
s = Integer.MIN_VALUE;
} else if (result > ((float) Integer.MAX_VALUE)) {
s = Integer.MAX_VALUE;
} else {
s = (int) result;
}
// Write the result
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = s;
}
// If the pixel is outside bounds and is possible to set
} else if (setDestinationNoData) {
for (int k = 0; k < dst_num_bands; k++) {
dstDataArrays[k][dstPixelOffset + dstBandOffsets[k]] = (int) destinationNoData[k];
}
}
// walk
if (interpN == null || !(interp instanceof InterpolationNearest)) {
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// If interpolation Nearest is used, then the
} else {
if (ifracx < ifracdx1) {
s_ix += incx;
ifracx += ifracdx;
} else {
s_ix += incx1;
ifracx -= ifracdx1;
}
if (ifracy < ifracdy1) {
s_iy += incy;
ifracy += ifracdy;
} else {
s_iy += incy1;
ifracy -= ifracdy1;
}
}
// Translate to/from SampleModel space & Raster space
posy = (s_iy - srcRectY) * srcScanlineStride;
posx = (s_ix - srcRectX) * srcPixelStride;
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
private void intLoopBinary(int dataType, RasterAccessor src, Raster source,
WritableRaster dest, Rectangle destRect, Raster roi, int srcRectX, int srcRectY, RandomIter roiIter) {
float src_rect_x1 = source.getMinX();
float src_rect_y1 = source.getMinY();
float src_rect_x2 = src_rect_x1 + source.getWidth();
float src_rect_y2 = src_rect_y1 + source.getHeight();
MultiPixelPackedSampleModel sourceSM = (MultiPixelPackedSampleModel) source
.getSampleModel();
DataBufferInt sourceDB = (DataBufferInt) source.getDataBuffer();
int sourceTransX = source.getSampleModelTranslateX();
int sourceTransY = source.getSampleModelTranslateY();
int sourceDataBitOffset = sourceSM.getDataBitOffset();
int sourceScanlineStride = sourceSM.getScanlineStride();
int sourcePixelStride = sourceSM.getPixelBitStride();
MultiPixelPackedSampleModel destSM = (MultiPixelPackedSampleModel) dest.getSampleModel();
DataBufferInt destDB = (DataBufferInt) dest.getDataBuffer();
int destTransX = dest.getSampleModelTranslateX();
int destTransY = dest.getSampleModelTranslateY();
int destDataBitOffset = destSM.getDataBitOffset();
int destScanlineStride = destSM.getScanlineStride();
int[] sourceData = sourceDB.getData();
Number[] sourceDataNum = new Number[sourceData.length];
for (int i = 0; i < sourceData.length; i++) {
sourceDataNum[i] = sourceData[i];
}
int sourceDBOffset = sourceDB.getOffset();
int[] destData = destDB.getData();
int destDBOffset = destDB.getOffset();
Point2D dst_pt = new Point2D.Float();
Point2D src_pt = new Point2D.Float();
int dst_min_x = destRect.x;
int dst_min_y = destRect.y;
int dst_max_x = destRect.x + destRect.width;
int dst_max_y = destRect.y + destRect.height;
// Output value initialization
int s = 0;
// pixel value coordinates initialization
int[] coordinates = new int[2];
int[] roiData = null;
int roiDBOffset = 0;
MultiPixelPackedSampleModel roiSM = null;
int roiTransY = 0;
int roiScanlineStride = 0;
if (roi != null) {
roiSM = (MultiPixelPackedSampleModel) roi.getSampleModel();
// roiTransX = roi.getSampleModelTranslateX();
roiTransY = roi.getSampleModelTranslateY();
// roiDataBitOffset = roiSM.getDataBitOffset();
roiScanlineStride = roiSM.getScanlineStride();
DataBuffer roiDB = roi.getDataBuffer();
roiDBOffset = roiDB.getOffset();
DataBufferByte roiDBByte = (DataBufferByte) roiDB;
byte[] roiDataB = roiDBByte.getData();
roiData = new int[roiDataB.length];
for (int ii = 0; ii < roiDataB.length; ii++) {
roiData[ii] = roiDataB[ii];
}
}
for (int y = dst_min_y; y < dst_max_y; y++) {
// Backward map the first point in the line
// The energy is at the (pt_x + 0.5, pt_y + 0.5)
dst_pt.setLocation((double) dst_min_x + 0.5, (double) y + 0.5);
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
// Floor to get the integral coordinate
int s_ix = (int) Math.floor(s_x);
int s_iy = (int) Math.floor(s_y);
double fracx = s_x - (double) s_ix;
double fracy = s_y - (double) s_iy;
// Get the new frac values
int xfrac = (int) (fracx * shiftvalue);
int yfrac = (int) (fracy * shiftvalue);
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
int destYOffset = (y - destTransY) * destScanlineStride + destDBOffset;
int destXOffset = destDataBitOffset + (dst_min_x - destTransX);
int sourceYOffset = (s_iy - sourceTransY) * sourceScanlineStride + sourceDBOffset;
// int sourceXOffset = s_ix - sourceTransX + sourceDataBitOffset;
int roiYOffset = (s_iy - roiTransY) * roiScanlineStride + roiDBOffset;
// Cycle on the destination image x bounds
for (int x = dst_min_x; x < dst_max_x; x++) {
sourceYOffset = (s_iy - sourceTransY) * sourceScanlineStride + sourceDBOffset;
roiYOffset = (s_iy - roiTransY) * roiScanlineStride + roiDBOffset;
int dindex = 0;
int dshift;
// int delement = 0;
//
// Check against the source rectangle
//
if ((s_ix >= src_rect_x1 + interp_left) && (s_ix < (src_rect_x2 - interp_right))
&& (s_iy >= src_rect_y1 + interp_top)
&& (s_iy < (src_rect_y2 - interp_bottom))) {
coordinates[0] = src.getX() + (s_ix - srcRectX) * sourcePixelStride;
;
coordinates[1] = src.getY() + ((s_iy - srcRectY) * sourceScanlineStride)
/ sourceScanlineStride;
int xNextBitNo = sourceDataBitOffset + (s_ix + 1 - sourceTransX);
if (interpN != null) {
s = interpN.interpolateBinary(xNextBitNo, sourceDataNum, sourceYOffset,
sourceScanlineStride, coordinates, roiData, roiYOffset,
roiScanlineStride, roiIter);
} else if (interpB != null) {
s = interpB.interpolateBinary(xNextBitNo, sourceDataNum, xfrac, yfrac,
sourceYOffset, sourceScanlineStride, coordinates, roiData,
roiYOffset, roiScanlineStride, roiIter);
} else if (interpBN != null) {
s = interpBN.interpolateBinary(xNextBitNo, sourceDataNum, xfrac, yfrac,
sourceYOffset, sourceScanlineStride, coordinates, roiData,
roiYOffset, roiScanlineStride, roiIter);
} else {
throw new UnsupportedOperationException(
"Binary interpolation not supported for interpolators different from"
+ "InterpolatorNearestNew,InterpolatorBinaryNew,InterpolatorBicubicNew");
}
} else if (setDestinationNoData) {
s = black;
}
dindex = destYOffset + (destXOffset >> 5);
dshift = 31 - (destXOffset & 31);
// delement = destData[dindex];
// delement |= s << dshift;
//
// destData[dindex] = delement;
if (s == 1) {
destData[dindex] |= (0x01 << dshift);
} else {
destData[dindex] &= (0xffffffff - (0x01 << dshift));
}
// walk
if (interpN == null || !(interp instanceof InterpolationNearest)) {
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// If interpolation Nearest is used, then the
} else {
if (ifracx < ifracdx1) {
s_ix += incx;
ifracx += ifracdx;
} else {
s_ix += incx1;
ifracx -= ifracdx1;
}
if (ifracy < ifracdy1) {
s_iy += incy;
ifracy += ifracdy;
} else {
s_iy += incy1;
ifracy -= ifracdy1;
}
}
++destXOffset;
}
}
}
private void floatLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX,
int srcRectY, RasterAccessor dst, RasterAccessor roiAccessor, RandomIter roiIter) {
// Creation of the interpolation kernel for interpolators different from the Interpolation type:
// InterpolationNearest, InterpolationBilinear, InterpolationBicubicNew.
float[][] samples = new float[interp_height][interp_width];
// Integral fractional values for a general interpolator
int xfrac;
int yfrac;
// Source region
float src_rect_x1 = src.getX();
float src_rect_y1 = src.getY();
float src_rect_x2 = src_rect_x1 + src.getWidth();
float src_rect_y2 = src_rect_y1 + src.getHeight();
// destination image pixel offset
int dstPixelOffset;
int dstOffset = 0;
// Destination and source point stored as point2D object
Point2D dst_pt = new Point2D.Float();
Point2D src_pt = new Point2D.Float();
// destination data arrays
float[][] dstDataArrays = dst.getFloatDataArrays();
// Destination band offsets array
int[] dstBandOffsets = dst.getBandOffsets();
// destination pixel stride
int dstPixelStride = dst.getPixelStride();
// destination scanline stride
int dstScanlineStride = dst.getScanlineStride();
// source image data array
float[][] srcDataArrays = src.getFloatDataArrays();
// source image band offsets array
int[] bandOffsets = src.getBandOffsets();
// source pixel stride
int srcPixelStride = src.getPixelStride();
// source scanline stride
int srcScanlineStride = src.getScanlineStride();
// destination band number
int dst_num_bands = dst.getNumBands();
// ROI scanline stride
int roiScanlineStride = 0;
if (roiAccessor != null) {
roiScanlineStride = roiAccessor.getScanlineStride();
}
// Destination bounds
int dst_min_x = destRect.x;
int dst_min_y = destRect.y;
int dst_max_x = destRect.x + destRect.width;
int dst_max_y = destRect.y + destRect.height;
// ROI position initialization
Integer posyROI = null;
// Fractional array initialization
Number[] fracValues = new Number[2];
// Cycle on the destination image y bounds
for (int y = dst_min_y; y < dst_max_y; y++) {
// update of the destination pixel offset
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((double) dst_min_x + 0.5, (double) y + 0.5);
// Backward mapping of the destination point position
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
// As per definition of bilinear or bicubic interpolation
if (interpN == null || !(interp instanceof InterpolationNearest)) {
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);
// Calculation of the fractional values
float fracx = s_x - (float) s_ix;
float fracy = s_y - (float) s_iy;
// Get the new frac values
xfrac = (int) (fracx * shiftvalue);
yfrac = (int) (fracy * shiftvalue);
// Store of the fractional value inside an array
if (dataType < DataBuffer.TYPE_FLOAT) {
fracValues[0] = xfrac;
fracValues[1] = yfrac;
} else {
fracValues[0] = fracx;
fracValues[1] = fracy;
}
// Translate to/from SampleModel space & Raster space
int posy = (s_iy - srcRectY) * srcScanlineStride;
int posx = (s_ix - srcRectX) * srcPixelStride;
// Conversion if the fractional values to integer ones for Nearest-Neighbor interpolation
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// If roiAccessor is present, the y position on the roi image is calculated
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Cycle on the destination image x bounds
for (int x = dst_min_x; x < dst_max_x; x++) {
//
// Check against the source rectangle
//
if ((s_ix >= src_rect_x1 + interp_left) && (s_ix < (src_rect_x2 - interp_right))
&& (s_iy >= src_rect_y1 + interp_top)
&& (s_iy < (src_rect_y2 - interp_bottom))) {
// Cycle on all the image bands
for (int k2 = 0; k2 < dst_num_bands; k2++) {
// initial value for the output sample
float s = 0;
int posyy = posy + bandOffsets[k2];
// Control for using the defined interpolator
if (interpN != null) {
s = interpN.interpolate(src, k2, dst_num_bands, posx, posyy, posyROI,
roiAccessor, roiIter, false).floatValue();
} else if (interpB != null) {
s = interpB.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).floatValue();
} else if (interpBN != null) {
s = interpBN.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).floatValue();
// Case of general interpolator (ROI and No Data not supported)
} else {
// Source data array of the selected band
float[] srcData = srcDataArrays[k2];
// Offset of the selected band
int tmp = bandOffsets[k2];
// Get the pixels required for this interpolation
int start = interp_left * srcPixelStride + interp_top
* srcScanlineStride;
// Initial array index of the selected pixel
start = posx + posy - start;
// Initial value for the counter for filling the interpolation kernel
int countH = 0, countV = 0;
// cycle on the x and y directions
for (int i = 0; i < interp_height; i++) {
int startY = start;
for (int j = 0; j < interp_width; j++) {
// interpolation kernel value addition
samples[countV][countH++] = srcData[start + tmp];
// update of the array index on the x direction
start += srcPixelStride;
}
// Update of the counter on the y axis and reset of the one on the X axis
countV++;
countH = 0;
// update of the array index on the y direction
start = startY + srcScanlineStride;
}
// Do the interpolation
s = interp.interpolate(samples, fracx, fracy);
}
// Write the result
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (float) s;
}
// If the pixel is outside bounds and is possible to set
} else if (setDestinationNoData) {
for (int k = 0; k < dst_num_bands; k++) {
dstDataArrays[k][dstPixelOffset + dstBandOffsets[k]] = (float) destinationNoData[k];
}
}
// walk
if (interpN == null || !(interp instanceof InterpolationNearest)) {
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// If interpolation Nearest is used, then the
} else {
if (ifracx < ifracdx1) {
s_ix += incx;
ifracx += ifracdx;
} else {
s_ix += incx1;
ifracx -= ifracdx1;
}
if (ifracy < ifracdy1) {
s_iy += incy;
ifracy += ifracdy;
} else {
s_iy += incy1;
ifracy -= ifracdy1;
}
}
// Translate to/from SampleModel space & Raster space
posy = (s_iy - srcRectY) * srcScanlineStride;
posx = (s_ix - srcRectX) * srcPixelStride;
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Go to next pixel
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 roiAccessor, RandomIter roiIter) {
// Creation of the interpolation kernel for interpolators different from the Interpolation type:
// InterpolationNearest, InterpolationBilinear, InterpolationBicubicNew.
double[][] samples = new double[interp_height][interp_width];
// Integral fractional values for a general interpolator
int xfrac;
int yfrac;
// Source region
float src_rect_x1 = src.getX();
float src_rect_y1 = src.getY();
float src_rect_x2 = src_rect_x1 + src.getWidth();
float src_rect_y2 = src_rect_y1 + src.getHeight();
// destination image pixel offset
int dstPixelOffset;
int dstOffset = 0;
// Destination and source point stored as point2D object
Point2D dst_pt = new Point2D.Float();
Point2D src_pt = new Point2D.Float();
// destination data arrays
double[][] dstDataArrays = dst.getDoubleDataArrays();
// Destination band offsets array
int[] dstBandOffsets = dst.getBandOffsets();
// destination pixel stride
int dstPixelStride = dst.getPixelStride();
// destination scanline stride
int dstScanlineStride = dst.getScanlineStride();
// source image data array
double[][] srcDataArrays = src.getDoubleDataArrays();
// source image band offsets array
int[] bandOffsets = src.getBandOffsets();
// source pixel stride
int srcPixelStride = src.getPixelStride();
// source scanline stride
int srcScanlineStride = src.getScanlineStride();
// destination band number
int dst_num_bands = dst.getNumBands();
// ROI scanline stride
int roiScanlineStride = 0;
if (roiAccessor != null) {
roiScanlineStride = roiAccessor.getScanlineStride();
}
// Destination bounds
int dst_min_x = destRect.x;
int dst_min_y = destRect.y;
int dst_max_x = destRect.x + destRect.width;
int dst_max_y = destRect.y + destRect.height;
// ROI position initialization
Integer posyROI = null;
// Fractional array initialization
Number[] fracValues = new Number[2];
// Cycle on the destination image y bounds
for (int y = dst_min_y; y < dst_max_y; y++) {
// update of the destination pixel offset
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((double) dst_min_x + 0.5, (double) y + 0.5);
// Backward mapping of the destination point position
mapDestPoint(dst_pt, src_pt);
// Get the mapped source coordinates
float s_x = (float) src_pt.getX();
float s_y = (float) src_pt.getY();
// As per definition of bilinear or bicubic interpolation
if (interpN == null || !(interp instanceof InterpolationNearest)) {
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);
// Calculation of the fractional values
float fracx = s_x - (float) s_ix;
float fracy = s_y - (float) s_iy;
// Get the new frac values
xfrac = (int) (fracx * shiftvalue);
yfrac = (int) (fracy * shiftvalue);
// Store of the fractional value inside an array
if (dataType < DataBuffer.TYPE_FLOAT) {
fracValues[0] = xfrac;
fracValues[1] = yfrac;
} else {
fracValues[0] = fracx;
fracValues[1] = fracy;
}
// Translate to/from SampleModel space & Raster space
int posy = (s_iy - srcRectY) * srcScanlineStride;
int posx = (s_ix - srcRectX) * srcPixelStride;
// Conversion if the fractional values to integer ones for Nearest-Neighbor interpolation
int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX);
int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX);
// If roiAccessor is present, the y position on the roi image is calculated
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Cycle on the destination image x bounds
for (int x = dst_min_x; x < dst_max_x; x++) {
//
// Check against the source rectangle
//
if ((s_ix >= src_rect_x1 + interp_left) && (s_ix < (src_rect_x2 - interp_right))
&& (s_iy >= src_rect_y1 + interp_top)
&& (s_iy < (src_rect_y2 - interp_bottom))) {
// Cycle on all the image bands
for (int k2 = 0; k2 < dst_num_bands; k2++) {
// initial value for the output sample
double s = 0;
int posyy = posy + bandOffsets[k2];
// Control for using the defined interpolator
if (interpN != null) {
s = interpN.interpolate(src, k2, dst_num_bands, posx, posyy, posyROI,
roiAccessor, roiIter, false).doubleValue();
} else if (interpB != null) {
s = interpB.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).doubleValue();
} else if (interpBN != null) {
s = interpBN.interpolate(src, k2, dst_num_bands, posx, posyy,
fracValues, posyROI, roiAccessor, roiIter, false).doubleValue();
// Case of general interpolator (ROI and No Data not supported)
} else {
// Source data array of the selected band
double[] srcData = srcDataArrays[k2];
// Offset of the selected band
int tmp = bandOffsets[k2];
// Get the pixels required for this interpolation
int start = interp_left * srcPixelStride + interp_top
* srcScanlineStride;
// Initial array index of the selected pixel
start = posx + posy - start;
// Initial value for the counter for filling the interpolation kernel
int countH = 0, countV = 0;
// cycle on the x and y directions
for (int i = 0; i < interp_height; i++) {
int startY = start;
for (int j = 0; j < interp_width; j++) {
// interpolation kernel value addition
samples[countV][countH++] = srcData[start + tmp];
// update of the array index on the x direction
start += srcPixelStride;
}
// Update of the counter on the y axis and reset of the one on the X axis
countV++;
countH = 0;
// update of the array index on the y direction
start = startY + srcScanlineStride;
}
// Do the interpolation
s = interp.interpolate(samples, fracx, fracy);
}
// Write the result
dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = s;
}
// If the pixel is outside bounds and is possible to set
} else if (setDestinationNoData) {
for (int k = 0; k < dst_num_bands; k++) {
dstDataArrays[k][dstPixelOffset + dstBandOffsets[k]] = destinationNoData[k];
}
}
// walk
if (interpN == null || !(interp instanceof InterpolationNearest)) {
if (fracx < fracdx1) {
s_ix += incx;
fracx += fracdx;
} else {
s_ix += incx1;
fracx -= fracdx1;
}
if (fracy < fracdy1) {
s_iy += incy;
fracy += fracdy;
} else {
s_iy += incy1;
fracy -= fracdy1;
}
// If interpolation Nearest is used, then the
} else {
if (ifracx < ifracdx1) {
s_ix += incx;
ifracx += ifracdx;
} else {
s_ix += incx1;
ifracx -= ifracdx1;
}
if (ifracy < ifracdy1) {
s_iy += incy;
ifracy += ifracdy;
} else {
s_iy += incy1;
ifracy -= ifracdy1;
}
}
// Translate to/from SampleModel space & Raster space
posy = (s_iy - srcRectY) * srcScanlineStride;
posx = (s_ix - srcRectX) * srcPixelStride;
if (roiAccessor != null) {
posyROI = (s_iy - srcRectY) * roiScanlineStride;
}
// Go to next pixel
dstPixelOffset += dstPixelStride;
}
// Go to the next line in the destination rectangle
dstOffset += dstScanlineStride;
}
}
}