/* 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.scale; import java.awt.Rectangle; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.IndexColorModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.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; import it.geosolutions.jaiext.interpolators.InterpolationBilinear; import it.geosolutions.jaiext.iterators.RandomIterFactory; import it.geosolutions.jaiext.range.Range; public class ScaleBilinearOpImage extends ScaleOpImage { /** boolean indicating if the data type is DataBuffer.TYPE_INT*/ protected boolean dataINT = false; /** Byte lookuptable used if no data are present */ protected byte[][] byteLookupTable; /** Bilinear interpolator */ protected InterpolationBilinear interpB = null; public ScaleBilinearOpImage(RenderedImage source, ImageLayout layout, Map configuration, BorderExtender extender, Interpolation interp, float scaleX, float scaleY, float transX, float transY, boolean useRoiAccessor, Range nodata, double[] backgroundValues) { super(source, layout, configuration, true, extender, interp, scaleX, scaleY, transX, transY, useRoiAccessor, backgroundValues); scaleOpInitialization(source, interp, nodata, backgroundValues, useRoiAccessor); } private void scaleOpInitialization(RenderedImage source, Interpolation interp, Range nodata, double[] backgroundValues, boolean useRoiAccessor) { // 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(source.getSampleModel())) { sampleModel = source.getSampleModel() .createCompatibleSampleModel(tileWidth, tileHeight); colorModel = srcColorModel; } SampleModel sm = source.getSampleModel(); // Source image data Type int srcDataType = sm.getDataType(); // NumBands int numBands = getSampleModel().getNumBands(); // selection of the inverse scale parameters both for the x and y axis if (invScaleXRational.num > invScaleXRational.denom) { invScaleXInt = invScaleXRational.num / invScaleXRational.denom; invScaleXFrac = invScaleXRational.num % invScaleXRational.denom; } else { invScaleXInt = 0; invScaleXFrac = invScaleXRational.num; } if (invScaleYRational.num > invScaleYRational.denom) { invScaleYInt = invScaleYRational.num / invScaleYRational.denom; invScaleYFrac = invScaleYRational.num % invScaleYRational.denom; } else { invScaleYInt = 0; invScaleYFrac = invScaleYRational.num; } // Interpolator settings interpolator = interp; // 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 InterpolationBilinear) { isBilinearNew = true; interpB = (InterpolationBilinear) interp; this.interp = interpB; interpB.setROIBounds(roiBounds); if(nod == null){ nod = interpB.getNoDataRange(); } if(destNod == null){ destNod = new double[]{interpB.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; } // subsample bits used for the bilinear and bicubic interpolation subsampleBits = interp.getSubsampleBitsH(); // Internal precision required for position calculations one = 1 << subsampleBits; // Subsampling related variables shift = 29 - subsampleBits; shift2 = 2 * subsampleBits; round2 = 1 << (shift2 - 1); // Number of subsample positions one = 1 << subsampleBits; // Get the width and height and padding of the Interpolation kernel. interp_width = interp.getWidth(); interp_height = interp.getHeight(); interp_left = interp.getLeftPadding(); interp_top = interp.getTopPadding(); // 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]; } // Creation of a lookuptable containing the values to use for no data if (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)) { byteLookupTable[b][i] = destinationNoDataByte[b]; } 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; } @Override protected void computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect) { // Retrieve format tags. RasterFormatTag[] formatTags = getFormatTags(); // Only one source raster is used Raster source = sources[0]; // Get the source rectangle Rectangle srcRect = source.getBounds(); // SRC and destination accessors are used for simplifying calculations RasterAccessor srcAccessor = new RasterAccessor(source, srcRect, formatTags[0], getSourceImage(0).getColorModel()); RasterAccessor dstAccessor = new RasterAccessor(dest, destRect, formatTags[1], getColorModel()); // Destination rectangle dimensions int dwidth = destRect.width; int dheight = destRect.height; // From the rasterAccessor are calculated the pixelStride and the scanLineStride int srcPixelStride = srcAccessor.getPixelStride(); int srcScanlineStride = srcAccessor.getScanlineStride(); // Initialization of the x and y position array int[] xpos = new int[dwidth]; int[] ypos = new int[dheight]; // ROI support int[] yposRoi = null; // Scanline stride. It is used as integer because it can return null values int roiScanlineStride = 0; // 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); } // creation of the rasterAccessor roiAccessor = new RasterAccessor(roi, srcRect, RasterAccessor.findCompatibleTags( new RenderedImage[] { srcROIImage }, srcROIImage)[0], srcROIImage.getColorModel()); // ROI scanlinestride roiScanlineStride = roiAccessor.getScanlineStride(); // Initialization of the roi y position array yposRoi = new int[dheight]; } else { roiIter = RandomIterFactory.create(srcROIImgExt, roiRect, true, true); } } // Initialization of the x and y fractional array int[] xfracValues = new int[dwidth]; int[] yfracValues = new int[dheight]; // Initialization of the x and y fractional array float[] xfracValuesFloat = new float[dwidth]; float[] yfracValuesFloat = new float[dheight]; // destination data type dataType = dest.getSampleModel().getDataType(); if (dataType < DataBuffer.TYPE_FLOAT) { preComputePositionsInt(destRect, srcRect.x, srcRect.y, srcPixelStride, srcScanlineStride, xpos, ypos, xfracValues, yfracValues, roiScanlineStride, yposRoi); } else { preComputePositionsFloat(destRect, srcRect.x, srcRect.y, srcPixelStride, srcScanlineStride, xpos, ypos, xfracValuesFloat, yfracValuesFloat, roiScanlineStride, yposRoi); } // This methods differs only for the presence of the roi or if the image is a binary one switch (dstAccessor.getDataType()) { case DataBuffer.TYPE_BYTE: byteLoop(srcAccessor, destRect, dstAccessor, xpos, ypos, xfracValues, yfracValues, roiAccessor, yposRoi, roiScanlineStride, roiIter); break; case DataBuffer.TYPE_USHORT: ushortLoop(srcAccessor, destRect, dstAccessor, xpos, ypos, xfracValues, yfracValues, roiAccessor, yposRoi, roiScanlineStride, roiIter); break; case DataBuffer.TYPE_SHORT: shortLoop(srcAccessor, destRect, dstAccessor, xpos, ypos, xfracValues, yfracValues, roiAccessor, yposRoi, roiScanlineStride, roiIter); break; case DataBuffer.TYPE_INT: intLoop(srcAccessor, destRect, dstAccessor, xpos, ypos, xfracValues, yfracValues, roiAccessor, yposRoi, roiScanlineStride, roiIter); break; case DataBuffer.TYPE_FLOAT: floatLoop(srcAccessor, destRect, dstAccessor, xpos, ypos, xfracValuesFloat, yfracValuesFloat, roiAccessor, yposRoi, roiScanlineStride, roiIter); break; case DataBuffer.TYPE_DOUBLE: doubleLoop(srcAccessor, destRect, dstAccessor, xpos, ypos, xfracValuesFloat, yfracValuesFloat, roiAccessor, yposRoi, roiScanlineStride, roiIter); break; } } private void byteLoop(RasterAccessor src, Rectangle dstRect, RasterAccessor dst, int[] xpos, int[] ypos, int[] xfrac, int[] yfrac, RasterAccessor roi, int[] yposRoi, int roiScanlineStride, RandomIter roiIter) { // BandOffsets final int srcScanlineStride = src.getScanlineStride(); final int srcPixelStride = src.getPixelStride(); final int bandOffsets[] = src.getBandOffsets(); // Destination rectangle dimensions final int dwidth = dstRect.width; final int dheight = dstRect.height; // Destination image band numbers final int dnumBands = dst.getNumBands(); // Destination bandOffsets, PixelStride and ScanLineStride final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); // Destination and source data arrays (for all bands) final byte[][] srcDataArrays = src.getByteDataArrays(); final byte[][] dstDataArrays = dst.getByteDataArrays(); final byte[] roiDataArray; final int roiDataLength; if (useRoiAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; } else { roiDataArray = null; roiDataLength = 0; } if (caseA) { // for all bands for (int k = 0; k < dnumBands; k++) { final byte[] srcData = srcDataArrays[k]; final byte[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final int s00 = srcData[pos] & 0xff; final int s01 = srcData[pos + srcPixelStride] & 0xff; final int s10 = srcData[pos + srcScanlineStride] & 0xff; final int s11 = srcData[pos + srcPixelStride + srcScanlineStride] & 0xff; // Perform the bilinear interpolation final int s0 = (s01 - s00) * xfrac[i] + (s00 << subsampleBits); final int s1 = (s11 - s10) * xfrac[i] + (s10 << subsampleBits); final int s = ((s1 - s0) * yfrac[j] + (s0 << subsampleBits) + round2) >> shift2; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (byte) (s & 0xff); // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (caseB) { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final byte[] srcData = srcDataArrays[k]; final byte[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final int s00 = srcData[pos] & 0xff; final int s01 = srcData[pos + srcPixelStride] & 0xff; final int s10 = srcData[pos + srcScanlineStride] & 0xff; final int s11 = srcData[pos + srcPixelStride + srcScanlineStride] & 0xff; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataByte[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataByte[k]; } else { // Perform the bilinear interpolation final int s0 = (s01 - s00) * xfrac[i] + (s00 << subsampleBits); final int s1 = (s11 - s10) * xfrac[i] + (s10 << subsampleBits); final int s = ((s1 - s0) * yfrac[j] + (s0 << subsampleBits) + round2) >> shift2; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (byte) (s & 0xff); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final byte[] srcData = srcDataArrays[k]; final byte[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0); final int w01 = roiIter.getSample(x0 + 1, y0, 0); final int w10 = roiIter.getSample(x0, y0 + 1, 0); final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final int s00 = srcData[posx + posy] & 0xff; final int s01 = srcData[posx + srcPixelStride + posy] & 0xff; final int s10 = srcData[posx + posy + srcScanlineStride] & 0xff; final int s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride] & 0xff; // Perform the bilinear interpolation final int s0 = (s01 - s00) * xfrac[i] + (s00 << subsampleBits); final int s1 = (s11 - s10) * xfrac[i] + (s10 << subsampleBits); final int s = ((s1 - s0) * yfrac[j] + (s0 << subsampleBits) + round2) >> shift2; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (byte) (s & 0xff); } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataByte[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataByte[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } else { if (caseC) { int w00 = 0; int w01 = 0; int w10 = 0; int w11 = 0; int s00; int s01; int s10; int s11; // for all bands for (int k = 0; k < dnumBands; k++) { final byte[] srcData = srcDataArrays[k]; final byte[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values s00 = srcData[posx + posy] & 0xff; s01 = srcData[posx + srcPixelStride + posy] & 0xff; s10 = srcData[posx + posy + srcScanlineStride] & 0xff; s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride] & 0xff; if (byteLookupTable[k][s00] == destinationNoDataByte[k]) { w00 = 0; } else { w00 = 1; } if (byteLookupTable[k][s01] == destinationNoDataByte[k]) { w01 = 0; } else { w01 = 1; } if (byteLookupTable[k][s10] == destinationNoDataByte[k]) { w10 = 0; } else { w10 = 1; } if (byteLookupTable[k][s11] == destinationNoDataByte[k]) { w11 = 0; } else { w11 = 1; } if ((w00+w01+w10+w11)==0) { dstData[dstPixelOffset] = destinationNoDataByte[k]; } else { // compute value dstData[dstPixelOffset] = (byte) (computeValue(s00, s01, s10, s11, w00,w01,w10,w11, xfrac[i], yfrac[j], k) & 0xff); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final byte[] srcData = srcDataArrays[k]; final byte[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values final int s00 = srcData[posx + posy] & 0xff; final int s01 = srcData[posx + srcPixelStride + posy] & 0xff; final int s10 = srcData[posx + posy + srcScanlineStride] & 0xff; final int s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride] & 0xff; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataByte[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataByte[k]; } else { if (byteLookupTable[k][s00] == destinationNoDataByte[k]) { w00 = 0; } else { w00 = 1; } if (byteLookupTable[k][s01] == destinationNoDataByte[k]) { w01 = 0; } else { w01 = 1; } if (byteLookupTable[k][s10] == destinationNoDataByte[k]) { w10 = 0; } else { w10 = 1; } if (byteLookupTable[k][s11] == destinationNoDataByte[k]) { w11 = 0; } else { w11 = 1; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (byte) (computeValue(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], k) & 0xff); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final byte[] srcData = srcDataArrays[k]; final byte[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0); int w01 = roiIter.getSample(x0 + 1, y0, 0); int w10 = roiIter.getSample(x0, y0 + 1, 0); int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final int s00 = srcData[posx + posy] & 0xff; final int s01 = srcData[posx + srcPixelStride + posy] & 0xff; final int s10 = srcData[posx + posy + srcScanlineStride] & 0xff; final int s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride] & 0xff; if (byteLookupTable[k][s00] == destinationNoDataByte[k]) { w00 = 0; } else { w00 = 1; } if (byteLookupTable[k][s01] == destinationNoDataByte[k]) { w01 = 0; } else { w01 = 1; } if (byteLookupTable[k][s10] == destinationNoDataByte[k]) { w10 = 0; } else { w10 = 1; } if (byteLookupTable[k][s11] == destinationNoDataByte[k]) { w11 = 0; } else { w11 = 1; } // compute value dstData[dstPixelOffset] = (byte) (computeValue(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], k) & 0xff); } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataByte[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataByte[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } } } } private void ushortLoop(RasterAccessor src, Rectangle dstRect, RasterAccessor dst, int[] xpos, int[] ypos, int[] xfrac, int[] yfrac, RasterAccessor roi, int[] yposRoi, int roiScanlineStride, RandomIter roiIter) { // BandOffsets final int srcScanlineStride = src.getScanlineStride(); final int srcPixelStride = src.getPixelStride(); final int bandOffsets[] = src.getBandOffsets(); // Destination rectangle dimensions final int dwidth = dstRect.width; final int dheight = dstRect.height; // Destination image band numbers final int dnumBands = dst.getNumBands(); // Destination bandOffsets, PixelStride and ScanLineStride final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); // Destination and source data arrays (for all bands) final short[][] srcDataArrays = src.getShortDataArrays(); final short[][] dstDataArrays = dst.getShortDataArrays(); final byte[] roiDataArray; final int roiDataLength; if (useRoiAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; } else { roiDataArray = null; roiDataLength = 0; } if (caseA) { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final int s00 = srcData[pos] & 0xffff; final int s01 = srcData[pos + srcPixelStride] & 0xffff; final int s10 = srcData[pos + srcScanlineStride] & 0xffff; final int s11 = srcData[pos + srcPixelStride + srcScanlineStride] & 0xffff; // Perform the bilinear interpolation final int s0 = (s01 - s00) * xfrac[i] + (s00 << subsampleBits); final int s1 = (s11 - s10) * xfrac[i] + (s10 << subsampleBits); final int s = ((s1 - s0) * yfrac[j] + (s0 << subsampleBits) + round2) >> shift2; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (short) (s & 0xffff); // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (caseB) { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final int s00 = srcData[pos] & 0xffff; final int s01 = srcData[pos + srcPixelStride] & 0xffff; final int s10 = srcData[pos + srcScanlineStride] & 0xffff; final int s11 = srcData[pos + srcPixelStride + srcScanlineStride] & 0xffff; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xffff : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xffff : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xffff : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xffff : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else { // Perform the bilinear interpolation final int s0 = (s01 - s00) * xfrac[i] + (s00 << subsampleBits); final int s1 = (s11 - s10) * xfrac[i] + (s10 << subsampleBits); final int s = ((s1 - s0) * yfrac[j] + (s0 << subsampleBits) + round2) >> shift2; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (short) (s & 0xffff); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0); final int w01 = roiIter.getSample(x0 + 1, y0, 0); final int w10 = roiIter.getSample(x0, y0 + 1, 0); final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final int s00 = srcData[posx + posy] & 0xffff; final int s01 = srcData[posx + srcPixelStride + posy] & 0xffff; final int s10 = srcData[posx + posy + srcScanlineStride] & 0xffff; final int s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride] & 0xffff; // Perform the bilinear interpolation final int s0 = (s01 - s00) * xfrac[i] + (s00 << subsampleBits); final int s1 = (s11 - s10) * xfrac[i] + (s10 << subsampleBits); final int s = ((s1 - s0) * yfrac[j] + (s0 << subsampleBits) + round2) >> shift2; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (short) (s & 0xffff); } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataUShort[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataUShort[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } else { if (caseC) { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values final short s00 = (short) (srcData[posx + posy] & 0xffff); final short s01 = (short) (srcData[posx + srcPixelStride + posy] & 0xffff); final short s10 = (short) (srcData[posx + posy + srcScanlineStride] & 0xffff); final short s11 = (short) (srcData[posx + srcPixelStride + posy + srcScanlineStride] & 0xffff); int w00 = 1; int w01 = 1; int w10 = 1; int w11 = 1; if (noData.contains(s00)) { w00 = 0; } if (noData.contains(s01)) { w01 = 0; } if (noData.contains(s10)) { w10 = 0; } if (noData.contains(s11)) { w11 = 0; } if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else { // compute value dstData[dstPixelOffset] = (short) (computeValue(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], k) & 0xffff); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values final short s00 = (short) (srcData[posx + posy] & 0xffff); final short s01 = (short) (srcData[posx + srcPixelStride + posy] & 0xffff); final short s10 = (short) (srcData[posx + posy + srcScanlineStride] & 0xffff); final short s11 = (short) (srcData[posx + srcPixelStride + posy + srcScanlineStride] & 0xffff); final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xffff : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xffff : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xffff : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xffff : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else { if (noData.contains(s00)) { w00 = 0; } else { w00 = 1; } if (noData.contains(s01)) { w01 = 0; } else { w01 = 1; } if (noData.contains(s10)) { w10 = 0; } else { w10 = 1; } if (noData.contains(s11)) { w11 = 0; } else { w11 = 1; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (short) (computeValue(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], k) & 0xffff); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0); int w01 = roiIter.getSample(x0 + 1, y0, 0); int w10 = roiIter.getSample(x0, y0 + 1, 0); int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final short s00 = (short) (srcData[posx + posy] & 0xffff); final short s01 = (short) (srcData[posx + srcPixelStride + posy] & 0xffff); final short s10 = (short) (srcData[posx + posy + srcScanlineStride] & 0xffff); final short s11 = (short) (srcData[posx + srcPixelStride + posy + srcScanlineStride] & 0xffff); if (noData.contains(s00)) { w00 = 0; } else { w00 = 1; } if (noData.contains(s01)) { w01 = 0; } else { w01 = 1; } if (noData.contains(s10)) { w10 = 0; } else { w10 = 1; } if (noData.contains(s11)) { w11 = 0; } else { w11 = 1; } // compute value dstData[dstPixelOffset] = (short) (computeValue(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], k) & 0xffff); } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataUShort[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataUShort[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } } } } private void shortLoop(RasterAccessor src, Rectangle dstRect, RasterAccessor dst, int[] xpos, int[] ypos, int[] xfrac, int[] yfrac, RasterAccessor roi, int[] yposRoi, int roiScanlineStride, RandomIter roiIter) { // BandOffsets final int srcScanlineStride = src.getScanlineStride(); final int srcPixelStride = src.getPixelStride(); final int bandOffsets[] = src.getBandOffsets(); // Destination rectangle dimensions final int dwidth = dstRect.width; final int dheight = dstRect.height; // Destination image band numbers final int dnumBands = dst.getNumBands(); // Destination bandOffsets, PixelStride and ScanLineStride final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); // Destination and source data arrays (for all bands) final short[][] srcDataArrays = src.getShortDataArrays(); final short[][] dstDataArrays = dst.getShortDataArrays(); final byte[] roiDataArray; final int roiDataLength; if (useRoiAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; } else { roiDataArray = null; roiDataLength = 0; } if (caseA) { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final int s00 = srcData[pos]; final int s01 = srcData[pos + srcPixelStride]; final int s10 = srcData[pos + srcScanlineStride]; final int s11 = srcData[pos + srcPixelStride + srcScanlineStride]; // Perform the bilinear interpolation final int s0 = (s01 - s00) * xfrac[i] + (s00 << subsampleBits); final int s1 = (s11 - s10) * xfrac[i] + (s10 << subsampleBits); final int s = ((s1 - s0) * yfrac[j] + (s0 << subsampleBits) + round2) >> shift2; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (short) s; // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (caseB) { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final int s00 = srcData[pos]; final int s01 = srcData[pos + srcPixelStride]; final int s10 = srcData[pos + srcScanlineStride]; final int s11 = srcData[pos + srcPixelStride + srcScanlineStride]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataShort[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataShort[k]; } else { // Perform the bilinear interpolation final int s0 = (s01 - s00) * xfrac[i] + (s00 << subsampleBits); final int s1 = (s11 - s10) * xfrac[i] + (s10 << subsampleBits); final int s = ((s1 - s0) * yfrac[j] + (s0 << subsampleBits) + round2) >> shift2; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (short) s; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0); final int w01 = roiIter.getSample(x0 + 1, y0, 0); final int w10 = roiIter.getSample(x0, y0 + 1, 0); final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final int s00 = srcData[posx + posy]; final int s01 = srcData[posx + srcPixelStride + posy]; final int s10 = srcData[posx + posy + srcScanlineStride]; final int s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; // Perform the bilinear interpolation final int s0 = (s01 - s00) * xfrac[i] + (s00 << subsampleBits); final int s1 = (s11 - s10) * xfrac[i] + (s10 << subsampleBits); final int s = ((s1 - s0) * yfrac[j] + (s0 << subsampleBits) + round2) >> shift2; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (short) s; } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataShort[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataShort[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } else { if (caseC) { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values final short s00 = srcData[posx + posy]; final short s01 = srcData[posx + srcPixelStride + posy]; final short s10 = srcData[posx + posy + srcScanlineStride]; final short s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; int w00 = 1; int w01 = 1; int w10 = 1; int w11 = 1; if (noData.contains(s00)) { w00 = 0; } if (noData.contains(s01)) { w01 = 0; } if (noData.contains(s10)) { w10 = 0; } if (noData.contains(s11)) { w11 = 0; } if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { dstData[dstPixelOffset] = destinationNoDataShort[k]; } else { // compute value dstData[dstPixelOffset] = (short) (computeValue(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], k)); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values final short s00 = srcData[posx + posy]; final short s01 = srcData[posx + srcPixelStride + posy]; final short s10 = srcData[posx + posy + srcScanlineStride]; final short s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; int w00 = w00index < roiDataLength ? roiDataArray[w00index] : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataShort[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataShort[k]; } else { if (noData.contains(s00)) { w00 = 0; } else { w00 = 1; } if (noData.contains(s01)) { w01 = 0; } else { w01 = 1; } if (noData.contains(s10)) { w10 = 0; } else { w10 = 1; } if (noData.contains(s11)) { w11 = 0; } else { w11 = 1; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (short) (computeValue(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], k)); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final short[] srcData = srcDataArrays[k]; final short[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0); int w01 = roiIter.getSample(x0 + 1, y0, 0); int w10 = roiIter.getSample(x0, y0 + 1, 0); int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final short s00 = srcData[posx + posy]; final short s01 = srcData[posx + srcPixelStride + posy]; final short s10 = srcData[posx + posy + srcScanlineStride]; final short s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; if (noData.contains(s00)) { w00 = 0; } else { w00 = 1; } if (noData.contains(s01)) { w01 = 0; } else { w01 = 1; } if (noData.contains(s10)) { w10 = 0; } else { w10 = 1; } if (noData.contains(s11)) { w11 = 0; } else { w11 = 1; } // compute value dstData[dstPixelOffset] = (short) (computeValue(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], k)); } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataShort[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataShort[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } } } } private void intLoop(RasterAccessor src, Rectangle dstRect, RasterAccessor dst, int[] xpos, int[] ypos, int[] xfrac, int[] yfrac, RasterAccessor roi, int[] yposRoi, int roiScanlineStride, RandomIter roiIter) { // BandOffsets final int srcScanlineStride = src.getScanlineStride(); final int srcPixelStride = src.getPixelStride(); final int bandOffsets[] = src.getBandOffsets(); // Destination rectangle dimensions final int dwidth = dstRect.width; final int dheight = dstRect.height; // Destination image band numbers final int dnumBands = dst.getNumBands(); // Destination bandOffsets, PixelStride and ScanLineStride final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); // Destination and source data arrays (for all bands) final int[][] srcDataArrays = src.getIntDataArrays(); final int[][] dstDataArrays = dst.getIntDataArrays(); final byte[] roiDataArray; final int roiDataLength; if (useRoiAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; } else { roiDataArray = null; roiDataLength = 0; } if (caseA) { // for all bands for (int k = 0; k < dnumBands; k++) { final int[] srcData = srcDataArrays[k]; final int[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final int s00 = srcData[pos]; final int s01 = srcData[pos + srcPixelStride]; final int s10 = srcData[pos + srcScanlineStride]; final int s11 = srcData[pos + srcPixelStride + srcScanlineStride]; // Perform the bilinear interpolation final int s0 = (s01 - s00) * xfrac[i] + (s00 << subsampleBits); final int s1 = (s11 - s10) * xfrac[i] + (s10 << subsampleBits); final int s = ((s1 - s0) * yfrac[j] + (s0 << subsampleBits) + round2) >> shift2; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = s; // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (caseB) { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final int[] srcData = srcDataArrays[k]; final int[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final int s00 = srcData[pos]; final int s01 = srcData[pos + srcPixelStride]; final int s10 = srcData[pos + srcScanlineStride]; final int s11 = srcData[pos + srcPixelStride + srcScanlineStride]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataInt[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataInt[k]; } else { // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (computeValue(s00, s01, s10, s11, 1, 1, 1, 1, xfrac[i], yfrac[j], k)); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final int[] srcData = srcDataArrays[k]; final int[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0); final int w01 = roiIter.getSample(x0 + 1, y0, 0); final int w10 = roiIter.getSample(x0, y0 + 1, 0); final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final int s00 = srcData[posx + posy]; final int s01 = srcData[posx + srcPixelStride + posy]; final int s10 = srcData[posx + posy + srcScanlineStride]; final int s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; // compute value dstData[dstPixelOffset] = (computeValue(s00, s01, s10, s11, 1, 1, 1, 1, xfrac[i], yfrac[j], k)); } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataInt[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataInt[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } else { if (caseC) { // for all bands for (int k = 0; k < dnumBands; k++) { final int[] srcData = srcDataArrays[k]; final int[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values final int s00 = srcData[posx + posy]; final int s01 = srcData[posx + srcPixelStride + posy]; final int s10 = srcData[posx + posy + srcScanlineStride]; final int s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; int w00 = 1; int w01 = 1; int w10 = 1; int w11 = 1; if (noData.contains(s00)) { w00 = 0; } if (noData.contains(s01)) { w01 = 0; } if (noData.contains(s10)) { w10 = 0; } if (noData.contains(s11)) { w11 = 0; } if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { dstData[dstPixelOffset] = destinationNoDataInt[k]; } else { // compute value dstData[dstPixelOffset] = (computeValue(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], k)); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final int[] srcData = srcDataArrays[k]; final int[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values final int s00 = srcData[posx + posy]; final int s01 = srcData[posx + srcPixelStride + posy]; final int s10 = srcData[posx + posy + srcScanlineStride]; final int s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; int w00 = w00index < roiDataLength ? roiDataArray[w00index] : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataInt[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataInt[k]; } else { if (noData.contains(s00)) { w00 = 0; } else { w00 = 1; } if (noData.contains(s01)) { w01 = 0; } else { w01 = 1; } if (noData.contains(s10)) { w10 = 0; } else { w10 = 1; } if (noData.contains(s11)) { w11 = 0; } else { w11 = 1; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (computeValue(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], k)); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final int[] srcData = srcDataArrays[k]; final int[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0); int w01 = roiIter.getSample(x0 + 1, y0, 0); int w10 = roiIter.getSample(x0, y0 + 1, 0); int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final int s00 = srcData[posx + posy]; final int s01 = srcData[posx + srcPixelStride + posy]; final int s10 = srcData[posx + posy + srcScanlineStride]; final int s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; if (noData.contains(s00)) { w00 = 0; } else { w00 = 1; } if (noData.contains(s01)) { w01 = 0; } else { w01 = 1; } if (noData.contains(s10)) { w10 = 0; } else { w10 = 1; } if (noData.contains(s11)) { w11 = 0; } else { w11 = 1; } // compute value dstData[dstPixelOffset] = (computeValue(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], k)); } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataInt[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataInt[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } } } } private void floatLoop(RasterAccessor src, Rectangle dstRect, RasterAccessor dst, int[] xpos, int[] ypos, float[] xfrac, float[] yfrac, RasterAccessor roi, int[] yposRoi, int roiScanlineStride, RandomIter roiIter) { // BandOffsets final int srcScanlineStride = src.getScanlineStride(); final int srcPixelStride = src.getPixelStride(); final int bandOffsets[] = src.getBandOffsets(); // Destination rectangle dimensions final int dwidth = dstRect.width; final int dheight = dstRect.height; // Destination image band numbers final int dnumBands = dst.getNumBands(); // Destination bandOffsets, PixelStride and ScanLineStride final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); // Destination and source data arrays (for all bands) final float[][] srcDataArrays = src.getFloatDataArrays(); final float[][] dstDataArrays = dst.getFloatDataArrays(); final byte[] roiDataArray; final int roiDataLength; if (useRoiAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; } else { roiDataArray = null; roiDataLength = 0; } if (caseA) { // for all bands for (int k = 0; k < dnumBands; k++) { final float[] srcData = srcDataArrays[k]; final float[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final float s00 = srcData[pos]; final float s01 = srcData[pos + srcPixelStride]; final float s10 = srcData[pos + srcScanlineStride]; final float s11 = srcData[pos + srcPixelStride + srcScanlineStride]; // Perform the bilinear interpolation final float s0 = (s01 - s00) * xfrac[i] + s00; final float s1 = (s11 - s10) * xfrac[i] + s10; final float s = (s1 - s0) * yfrac[j] + s0; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = s; // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (caseB) { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final float[] srcData = srcDataArrays[k]; final float[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final float s00 = srcData[pos]; final float s01 = srcData[pos + srcPixelStride]; final float s10 = srcData[pos + srcScanlineStride]; final float s11 = srcData[pos + srcPixelStride + srcScanlineStride]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else { // Perform the bilinear interpolation final float s0 = (s01 - s00) * xfrac[i] + s00; final float s1 = (s11 - s10) * xfrac[i] + s10; final float s = (s1 - s0) * yfrac[j] + s0; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = s; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final float[] srcData = srcDataArrays[k]; final float[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0); final int w01 = roiIter.getSample(x0 + 1, y0, 0); final int w10 = roiIter.getSample(x0, y0 + 1, 0); final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final float s00 = srcData[posx + posy]; final float s01 = srcData[posx + srcPixelStride + posy]; final float s10 = srcData[posx + posy + srcScanlineStride]; final float s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; // Perform the bilinear interpolation final float s0 = (s01 - s00) * xfrac[i] + s00; final float s1 = (s11 - s10) * xfrac[i] + s10; final float s = (s1 - s0) * yfrac[j] + s0; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = s; } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataFloat[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataFloat[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } else { if (caseC) { // for all bands for (int k = 0; k < dnumBands; k++) { final float[] srcData = srcDataArrays[k]; final float[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values final float s00 = srcData[posx + posy]; final float s01 = srcData[posx + srcPixelStride + posy]; final float s10 = srcData[posx + posy + srcScanlineStride]; final float s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; int w00 = 1; int w01 = 1; int w10 = 1; int w11 = 1; if (noData.contains(s00)) { w00 = 0; } if (noData.contains(s01)) { w01 = 0; } if (noData.contains(s10)) { w10 = 0; } if (noData.contains(s11)) { w11 = 0; } if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else { // compute value dstData[dstPixelOffset] = (float) computeValueDouble(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], dataType, k); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final float[] srcData = srcDataArrays[k]; final float[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values final float s00 = srcData[posx + posy]; final float s01 = srcData[posx + srcPixelStride + posy]; final float s10 = srcData[posx + posy + srcScanlineStride]; final float s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; int w00 = w00index < roiDataLength ? roiDataArray[w00index] : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else { if (noData.contains(s00)) { w00 = 0; } else { w00 = 1; } if (noData.contains(s01)) { w01 = 0; } else { w01 = 1; } if (noData.contains(s10)) { w10 = 0; } else { w10 = 1; } if (noData.contains(s11)) { w11 = 0; } else { w11 = 1; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (float) computeValueDouble(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], dataType, k); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final float[] srcData = srcDataArrays[k]; final float[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0); int w01 = roiIter.getSample(x0 + 1, y0, 0); int w10 = roiIter.getSample(x0, y0 + 1, 0); int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final float s00 = srcData[posx + posy]; final float s01 = srcData[posx + srcPixelStride + posy]; final float s10 = srcData[posx + posy + srcScanlineStride]; final float s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; if (noData.contains(s00)) { w00 = 0; } else { w00 = 1; } if (noData.contains(s01)) { w01 = 0; } else { w01 = 1; } if (noData.contains(s10)) { w10 = 0; } else { w10 = 1; } if (noData.contains(s11)) { w11 = 0; } else { w11 = 1; } // compute value dstData[dstPixelOffset] = (float) computeValueDouble( s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], dataType, k); } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataFloat[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataFloat[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } } } } private void doubleLoop(RasterAccessor src, Rectangle dstRect, RasterAccessor dst, int[] xpos, int[] ypos, float[] xfrac, float[] yfrac, RasterAccessor roi, int[] yposRoi, int roiScanlineStride, RandomIter roiIter) { // BandOffsets final int srcScanlineStride = src.getScanlineStride(); final int srcPixelStride = src.getPixelStride(); final int bandOffsets[] = src.getBandOffsets(); // Destination rectangle dimensions final int dwidth = dstRect.width; final int dheight = dstRect.height; // Destination image band numbers final int dnumBands = dst.getNumBands(); // Destination bandOffsets, PixelStride and ScanLineStride final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); // Destination and source data arrays (for all bands) final double[][] srcDataArrays = src.getDoubleDataArrays(); final double[][] dstDataArrays = dst.getDoubleDataArrays(); final byte[] roiDataArray; final int roiDataLength; if (useRoiAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; } else { roiDataArray = null; roiDataLength = 0; } if (caseA) { // for all bands for (int k = 0; k < dnumBands; k++) { final double[] srcData = srcDataArrays[k]; final double[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final double s00 = srcData[pos]; final double s01 = srcData[pos + srcPixelStride]; final double s10 = srcData[pos + srcScanlineStride]; final double s11 = srcData[pos + srcPixelStride + srcScanlineStride]; // Perform the bilinear interpolation final double s0 = (s01 - s00) * xfrac[i] + s00; final double s1 = (s11 - s10) * xfrac[i] + s10; final double s = (s1 - s0) * yfrac[j] + s0; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = s; // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (caseB) { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final double[] srcData = srcDataArrays[k]; final double[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; final int pos = posx + posy; final double s00 = srcData[pos]; final double s01 = srcData[pos + srcPixelStride]; final double s10 = srcData[pos + srcScanlineStride]; final double s11 = srcData[pos + srcPixelStride + srcScanlineStride]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else { // Perform the bilinear interpolation final double s0 = (s01 - s00) * xfrac[i] + s00; final double s1 = (s11 - s10) * xfrac[i] + s10; final double s = (s1 - s0) * yfrac[j] + s0; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = s; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final double[] srcData = srcDataArrays[k]; final double[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0); final int w01 = roiIter.getSample(x0 + 1, y0, 0); final int w10 = roiIter.getSample(x0, y0 + 1, 0); final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final double s00 = srcData[posx + posy]; final double s01 = srcData[posx + srcPixelStride + posy]; final double s10 = srcData[posx + posy + srcScanlineStride]; final double s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; // Perform the bilinear interpolation final double s0 = (s01 - s00) * xfrac[i]; final double s1 = (s11 - s10) * xfrac[i]; final double s = (s1 - s0) * yfrac[j] + s0; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = s; } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataDouble[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataDouble[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } else { if (caseC) { // for all bands for (int k = 0; k < dnumBands; k++) { final double[] srcData = srcDataArrays[k]; final double[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values final double s00 = srcData[posx + posy]; final double s01 = srcData[posx + srcPixelStride + posy]; final double s10 = srcData[posx + posy + srcScanlineStride]; final double s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; int w00 = 1; int w01 = 1; int w10 = 1; int w11 = 1; if (noData.contains(s00)) { w00 = 0; } if (noData.contains(s01)) { w01 = 0; } if (noData.contains(s10)) { w10 = 0; } if (noData.contains(s11)) { w11 = 0; } if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else { // compute value dstData[dstPixelOffset] = computeValueDouble(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], dataType, k); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { // for all bands for (int k = 0; k < dnumBands; k++) { final double[] srcData = srcDataArrays[k]; final double[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // Get the four surrounding pixel values final double s00 = srcData[posx + posy]; final double s01 = srcData[posx + srcPixelStride + posy]; final double s10 = srcData[posx + posy + srcScanlineStride]; final double s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + 1 + roiScanlineStride; int w00 = w00index < roiDataLength ? roiDataArray[w00index] : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] : 0; if (baseIndex > roiDataLength || w00 == 0) { dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else { if (noData.contains(s00)) { w00 = 0; } else { w00 = 1; } if (noData.contains(s01)) { w01 = 0; } else { w01 = 1; } if (noData.contains(s10)) { w10 = 0; } else { w10 = 1; } if (noData.contains(s11)) { w11 = 0; } else { w11 = 1; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = computeValueDouble(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], dataType, k); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { // for all bands for (int k = 0; k < dnumBands; k++) { final double[] srcData = srcDataArrays[k]; final double[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; final int bandOffset = bandOffsets[k]; // cycle on the y values for (int j = 0; j < dheight; j++) { // pixel offset initialization int dstPixelOffset = dstlineOffset; // y position selection final int posy = ypos[j] + bandOffset; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection final int posx = xpos[i]; // PixelPositions final int x0 = src.getX() + posx / srcPixelStride; final int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0); int w01 = roiIter.getSample(x0 + 1, y0, 0); int w10 = roiIter.getSample(x0, y0 + 1, 0); int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0); if (!(w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { // Get the four surrounding pixel values final double s00 = srcData[posx + posy]; final double s01 = srcData[posx + srcPixelStride + posy]; final double s10 = srcData[posx + posy + srcScanlineStride]; final double s11 = srcData[posx + srcPixelStride + posy + srcScanlineStride]; if (noData.contains(s00)) { w00 = 0; } else { w00 = 1; } if (noData.contains(s01)) { w01 = 0; } else { w01 = 1; } if (noData.contains(s10)) { w10 = 0; } else { w10 = 1; } if (noData.contains(s11)) { w11 = 0; } else { w11 = 1; } // compute value dstData[dstPixelOffset] = computeValueDouble(s00, s01, s10, s11, w00, w01, w10, w11, xfrac[i], yfrac[j], dataType, k); } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataDouble[k]; } } else { // The destination no data value is saved in the destination array dstData[dstPixelOffset] = destinationNoDataDouble[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } } } } /* Private method for calculate bilinear interpolation for byte, short/ushort, integer dataType */ private int computeValue(int s00, int s01, int s10, int s11, byte weight, int xfrac, int yfrac) { int s0; int s1; //int s = 0; long s0L; long s1L; // Complementary values of the fractional part int xfracCompl = one - xfrac; int yfracCompl = one - yfrac; // For Integer value is possible that a bitshift of "subsampleBits" could shift over the integer bit number // so the samples, in this case, are expanded to Long. // All the possible weight combination are checked switch (weight) { case 1: s0 = s00 * xfracCompl; //s = (s0 * yfracCompl + round2) >> shift2; return (s0 * yfracCompl + round2) >> shift2; //break; case 2: s0 = s01 * xfrac; //s = (s0 * yfracCompl + round2) >> shift2; return (s0 * yfracCompl + round2) >> shift2; //break; case 3: if (dataINT) { if (((s00 | s10) >>> shift == 0)) { if (((s01 | s11) >>> shift == 0)) { s0L = (s01 - s00) * xfrac + (s00 << subsampleBits); } else { s0L = (1L * s01 - s00) * xfrac + (1L * s00 << subsampleBits); } } else { s0L = (1L * s01 - s00) * xfrac + (1L * s00 << subsampleBits); } //s = (int) ((s0L * yfracCompl + round2) >> shift2); return (int) ((s0L * yfracCompl + round2) >> shift2); } else { s0 = (s01 - s00) * xfrac + (s00 << subsampleBits); return (s0 * yfracCompl + round2) >> shift2; //s = (s0 * yfracCompl + round2) >> shift2; } //break; case 4: s1 = s10 * xfracCompl; return (s1 * yfrac + round2) >> shift2; //s = (s1 * yfrac + round2) >> shift2; //break; case 5: if (dataINT) { s0L = s00 * xfracCompl; s1L = s10 * xfracCompl; return (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); //s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } else { s0 = s00 * xfracCompl; s1 = s10 * xfracCompl; return ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; //s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } //break; case 6: if (dataINT) { s0L = s01 * xfrac; s1L = s10 * xfracCompl; return (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); //s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } else { s0 = s01 * xfrac; s1 = s10 * xfracCompl; return ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; //s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } //break; case 7: if (dataINT) { if (((s00 | s10) >>> shift == 0)) { if (((s01 | s11) >>> shift == 0)) { s0L = (s01 - s00) * xfrac + (s00 << subsampleBits); } else { s0L = (1L * s01 - s00) * xfrac + (1L * s00 << subsampleBits); } } else { s0L = (1L * s01 - s00) * xfrac + (1L * s00 << subsampleBits); } s1L = s10 * xfracCompl; return (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); //s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } else { s0 = (s01 - s00) * xfrac + (s00 << subsampleBits); s1 = s10 * xfracCompl; return ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; //s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } //break; case 8: s1 = s11 * xfrac; return (s1 * yfrac + round2) >> shift2; //s = (s1 * yfrac + round2) >> shift2; //break; case 9: if (dataINT) { s0L = s00 * xfracCompl; s1L = s11 * xfrac; return (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); //s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } else { s0 = s00 * xfracCompl; s1 = s11 * xfrac; return ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; //s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } //break; case 10: if (dataINT) { s0L = s01 * xfrac; s1L = s11 * xfrac; return (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); //s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } else { s0 = s01 * xfrac; s1 = s11 * xfrac; return ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; //s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } //break; case 11: if (dataINT) { if (((s00 | s10) >>> shift == 0)) { if (((s01 | s11) >>> shift == 0)) { s0L = (s01 - s00) * xfrac + (s00 << subsampleBits); } else { s0L = (1L * s01 - s00) * xfrac + (1L * s00 << subsampleBits); } } else { s0L = (1L * s01 - s00) * xfrac + (1L * s00 << subsampleBits); } s1L = s11 * xfrac; return (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); //s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } else { s0 = (s01 - s00) * xfrac + (s00 << subsampleBits); s1 = s11 * xfrac; return ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; //s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } //break; case 12: if (dataINT) { if (((s00 | s10) >>> shift == 0)) { if (((s01 | s11) >>> shift == 0)) { s1L = (s11 - s10) * xfrac + (s10 << subsampleBits); } else { s1L = (1L * s11 - s10) * xfrac + (1L * s10 << subsampleBits); } } else { s1L = (1L * s11 - s10) * xfrac + (1L * s10 << subsampleBits); } return (int) ((s1L * yfrac + round2) >> shift2); //s = (int) ((s1L * yfrac + round2) >> shift2); } else { s1 = (s11 - s10) * xfrac + (s10 << subsampleBits); return (s1 * yfrac + round2) >> shift2; //s = (s1 * yfrac + round2) >> shift2; } //break; case 13: if (dataINT) { if (((s00 | s10) >>> shift == 0)) { if (((s01 | s11) >>> shift == 0)) { s1L = (s11 - s10) * xfrac + (s10 << subsampleBits); } else { s1L = (1L * s11 - s10) * xfrac + (1L * s10 << subsampleBits); } } else { s1L = (1L * s11 - s10) * xfrac + (1L * s10 << subsampleBits); } s0L = s00 * xfracCompl; return (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); //s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } else { s0 = s00 * xfracCompl; s1 = (s11 - s10) * xfrac + (s10 << subsampleBits); return ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; //s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } //break; case 14: if (dataINT) { if (((s00 | s10) >>> shift == 0)) { if (((s01 | s11) >>> shift == 0)) { s1L = (s11 - s10) * xfrac + (s10 << subsampleBits); } else { s1L = (1L * s11 - s10) * xfrac + (1L * s10 << subsampleBits); } } else { s1L = (1L * s11 - s10) * xfrac + (1L * s10 << subsampleBits); } s0L = s01 * xfrac; return (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); //s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } else { s0 = s01 * xfrac; s1 = (s11 - s10) * xfrac + (s10 << subsampleBits); return ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; //s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } //break; case 15: if (dataINT) { if (((s00 | s10) >>> shift == 0)) { if (((s01 | s11) >>> shift == 0)) { s1L = (s11 - s10) * xfrac + (s10 << subsampleBits); } else { s1L = (1L * s11 - s10) * xfrac + (1L * s10 << subsampleBits); } } else { s1L = (1L * s11 - s10) * xfrac + (1L * s10 << subsampleBits); } if (((s00 | s10) >>> shift == 0)) { if (((s01 | s11) >>> shift == 0)) { s0L = (s01 - s00) * xfrac + (s00 << subsampleBits); } else { s0L = (1L * s01 - s00) * xfrac + (1L * s00 << subsampleBits); } } else { s0L = (1L * s01 - s00) * xfrac + (1L * s00 << subsampleBits); } return (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); //s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } else { s0 = (s01 - s00) * xfrac + (s00 << subsampleBits); s1 = (s11 - s10) * xfrac + (s10 << subsampleBits); return ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; //s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } //break; default: throw new IllegalArgumentException("Wrong Number of No Data"); } //return s; } /* Private method for calculate bilinear interpolation for byte, short/ushort, integer dataType */ private int computeValue(int s00, int s01, int s10, int s11, int w00, int w01, int w10, int w11, int xfrac, int yfrac, int k) { int s0 = 0; int s1 = 0; int s = 0; long s0L = 0; long s1L = 0; // Complementary values of the fractional part int xfracCompl = one - xfrac; int yfracCompl = one - yfrac; // Boolean indicating if a pixel weight is 0 boolean w00z = w00 == 0; boolean w01z = w01 == 0; boolean w10z = w10 == 0; boolean w11z = w11 == 0; // Boolean indicating if 2 same line-pixel weights are 0 boolean w0z = w00z && w01z; boolean w1z = w10z && w11z; if (w0z && w1z) { switch (dataType) { case DataBuffer.TYPE_BYTE: return destinationNoDataByte[k]; case DataBuffer.TYPE_USHORT: return destinationNoDataUShort[k]; case DataBuffer.TYPE_SHORT: return destinationNoDataShort[k]; case DataBuffer.TYPE_INT: return destinationNoDataInt[k]; } } int shift = 29 - subsampleBits; // For Integer value is possible that a bitshift of "subsampleBits" could shift over the integer bit number // so the samples, in this case, are expanded to Long. boolean s0Long = ((s00 | s10) >>> shift == 0); boolean s1Long = ((s01 | s11) >>> shift == 0); // boolean indicating if the data type is DataBuffer.TYPE_INT boolean dataINT = dataType == DataBuffer.TYPE_INT; // All the possible weight combination are checked if (w00z || w01z || w10z || w11z) { // For integers is even considered the case when the integers are expanded to longs if (dataINT) { if (w0z) { s0L = 0; } else if (w00z) { // w01 = 1 s0L = s01 * xfrac; } else if (w01z) {// w00 = 1 s0L = s00 * xfracCompl; } else {// w00 = 1 & W01 = 1 if (s0Long) { if (s1Long) { s0L = (s01 - s00) * xfrac + (s00 << subsampleBits); } else { s0L = (1L * s01 - s00) * xfrac + (1L * s00 << subsampleBits); } } else { s0L = (1L * s01 - s00) * xfrac + (1L * s00 << subsampleBits); } } // lower value if (w1z) { s1L = 0; } else if (w10z) { // w11 = 1 s1L = s11 * xfrac; } else if (w11z) { // w10 = 1 // - (s10 * xfrac); //s10; s1L = s10 * xfracCompl; } else { if (s0Long) { if (s1Long) { s1L = (s11 - s10) * xfrac + (s10 << subsampleBits); } else { s1L = (1L * s11 - s10) * xfrac + (1L * s10 << subsampleBits); } } else { s1L = (1L * s11 - s10) * xfrac + (1L * s10 << subsampleBits); } } if (w0z) { s = (int) ((s1L * yfrac + round2) >> shift2); } else { if (w1z) { s = (int) ((s0L * yfracCompl + round2) >> shift2); } else { s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } } } else { // Interpolation for type byte, ushort, short if (w0z) { s0 = 0; } else if (w00z) { // w01 = 1 s0 = s01 * xfrac; } else if (w01z) {// w00 = 1 s0 = s00 * xfracCompl;// s00; } else {// w00 = 1 & W01 = 1 s0 = (s01 - s00) * xfrac + (s00 << subsampleBits); } // lower value if (w1z) { s1 = 0; } else if (w10z) { // w11 = 1 s1 = s11 * xfrac; } else if (w11z) { // w10 = 1 s1 = s10 * xfracCompl;// - (s10 * xfrac); //s10; } else { s1 = (s11 - s10) * xfrac + (s10 << subsampleBits); } if (w0z) { s = (s1 * yfrac + round2) >> shift2; } else { if (w1z) { s = (s0 * yfracCompl + round2) >> shift2; } else { s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } } } } else { // Perform the bilinear interpolation if (dataINT) { if (s0Long) { if (s1Long) { s0 = (s01 - s00) * xfrac + (s00 << subsampleBits); s1 = (s11 - s10) * xfrac + (s10 << subsampleBits); s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } else { s0L = (1L * s01 - s00) * xfrac + (s00 << subsampleBits); s1L = (1L * s11 - s10) * xfrac + (s10 << subsampleBits); s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } } else { s0L = (1L * s01 - s00) * xfrac + (1L * s00 << subsampleBits); s1L = (1L * s11 - s10) * xfrac + (1L * s10 << subsampleBits); s = (int) (((s1L - s0L) * yfrac + (s0L << subsampleBits) + round2) >> shift2); } } else { s0 = (s01 - s00) * xfrac + (s00 << subsampleBits); s1 = (s11 - s10) * xfrac + (s10 << subsampleBits); s = ((s1 - s0) * yfrac + (s0 << subsampleBits) + round2) >> shift2; } } return s; } /* Private method for calculate bilinear interpolation for float/double dataType */ private double computeValueDouble(double s00, double s01, double s10, double s11, double w00, double w01, double w10, double w11, double xfrac, double yfrac, int dataType, int k) { double s0 = 0; double s1 = 0; double s = 0; // Complementary values of the fractional part double xfracCompl = 1 - xfrac; double yfracCompl = 1 - yfrac; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { switch (dataType) { case DataBuffer.TYPE_FLOAT: return destinationNoDataFloat[k]; case DataBuffer.TYPE_DOUBLE: return destinationNoDataDouble[k]; } } if (w00 == 0 || w01 == 0 || w10 == 0 || w11 == 0) { if (w00 == 0 && w01 == 0) { s0 = 0; } else if (w00 == 0) { // w01 = 1 s0 = s01 * xfrac; } else if (w01 == 0) {// w00 = 1 s0 = s00 * xfracCompl;// s00; } else {// w00 = 1 & W01 = 1 s0 = (s01 - s00) * xfrac + s00; } // lower value if (w10 == 0 && w11 == 0) { s1 = 0; } else if (w10 == 0) { // w11 = 1 s1 = s11 * xfrac; } else if (w11 == 0) { // w10 = 1 s1 = s10 * xfracCompl;// - (s10 * xfrac); //s10; } else { s1 = (s11 - s10) * xfrac + s10; } if (w00 == 0 && w01 == 0) { s = s1 * yfrac; } else { if (w10 == 0 && w11 == 0) { s = s0 * yfracCompl; } else { s = (s1 - s0) * yfrac + s0; } } } else { // Perform the bilinear interpolation because all the weight are not 0. s0 = (s01 - s00) * xfrac + s00; s1 = (s11 - s10) * xfrac + s10; s = (s1 - s0) * yfrac + s0; } // Simple conversion for float dataType. return s; } }