/* 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.InterpolationBicubic; import it.geosolutions.jaiext.iterators.RandomIterFactory; import it.geosolutions.jaiext.range.Range; public class ScaleBicubicOpImage extends ScaleOpImage { /** Bicubic interpolator */ protected InterpolationBicubic interpBN = null; /** Bicubic Horizontal coefficients for integer type */ private int[] dataHi; /** Bicubic Vertical coefficients for integer type */ private int[] dataVi; /** Bicubic Horizontal coefficients for float type */ private float[] dataHf; /** Bicubic Vertical coefficients for float type */ private float[] dataVf; /** Bicubic Horizontal coefficients for double type */ private double[] dataHd; /** Bicubic Vertical coefficients for double type */ private double[] dataVd; /** Byte lookuptable used if no data are present */ private byte[][] byteLookupTable; public ScaleBicubicOpImage(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 (interpolator instanceof InterpolationBicubic) { isBicubicNew = true; interpBN = (InterpolationBicubic) interpolator; this.interp = interpBN; switch (srcDataType) { case DataBuffer.TYPE_BYTE: case DataBuffer.TYPE_USHORT: case DataBuffer.TYPE_SHORT: case DataBuffer.TYPE_INT: dataHi = interpBN.getHorizontalTableData(); dataVi = interpBN.getVerticalTableData(); break; case DataBuffer.TYPE_FLOAT: dataHf = interpBN.getHorizontalTableDataFloat(); dataVf = interpBN.getVerticalTableDataFloat(); break; case DataBuffer.TYPE_DOUBLE: dataHd = interpBN.getHorizontalTableDataDouble(); dataVd = interpBN.getVerticalTableDataDouble(); break; default: throw new IllegalArgumentException("Wrong data Type"); } interpBN.setROIBounds(roiBounds); noData = interpBN.getNoDataRange(); precisionBits = interpBN.getPrecisionBits(); if(nod == null){ nod = interpBN.getNoDataRange(); } if(destNod == null){ destNod = new double[]{interpBN.getDestinationNoData()}; } } // Nodata definition if (nod != null) { hasNoData = true; noData = nod; } if (destNod != null) { destinationNoDataDouble = destNod; } else if (this.backgroundValues != null && this.backgroundValues.length > 0) { destinationNoDataDouble = this.backgroundValues; } // Expand the destination nodata values if not defined if(destinationNoDataDouble != null && destinationNoDataDouble.length < numBands){ double[] tmp = new double[numBands]; Arrays.fill(tmp, destinationNoDataDouble[0]); destinationNoDataDouble = tmp; } // ROIAccessor definition if (hasROI) { this.useRoiAccessor = useRoiAccessor; } // subsample bits used for the bilinear and bicubic interpolation subsampleBits = interp.getSubsampleBitsH(); if (precisionBits > 0) { round = 1 << (precisionBits - 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]; // destination data type dataType = dest.getSampleModel().getDataType(); preComputePositionsInt(destRect, srcRect.x, srcRect.y, srcPixelStride, srcScanlineStride, xpos, ypos, xfracValues, yfracValues, 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, xfracValues, yfracValues, roiAccessor, yposRoi, roiScanlineStride, roiIter); break; case DataBuffer.TYPE_DOUBLE: doubleLoop(srcAccessor, destRect, dstAccessor, xpos, ypos, xfracValues, yfracValues, 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; long sum = 0; int s = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value for (int h = 0; h < 4; h++) { // Row temporary sum initialization long temp = 0; for (int z = 0; z < 4; z++) { // Selection of one pixel int pixelValue = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xff; // Update of the temporary sum temp += (pixelValue * dataHi[offsetX + z]); } // Vertical sum update sum += ((temp + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp if (s > 255) { s = 255; } else if (s < 0) { s = 0; } // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; int[][] pixelKernel = new int[4][4]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataByte[k]; } else { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xff; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum temp += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1 : 0); } } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataByte[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]); } // Vertical sum update sum += ((tempSum + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp if (s > 255) { s = 255; } else if (s < 0) { s = 0; } 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; int[][] pixelKernel = new int[4][4]; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (roiBounds.contains(x0, y0)) { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by 1 on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xff; temp += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff; } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataByte[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]); } // Vertical sum update sum += ((tempSum + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp if (s > 255) { s = 255; } else if (s < 0) { s = 0; } dstData[dstPixelOffset] = (byte) (s & 0xff); } } 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) { final long[][] pixelKernel = new long[4][4]; final long[] sumArray = new long[4]; // final int[][] weightArray = new int[4][4] short weight = 0; // final int[] weightArrayVertical = new int[4]; byte weightVert = 0; final long[] emptyArray = new long[4]; // Row temporary sum initialization long tempSum = 0; long sum = 0; byte temp = 0; // final result initialization int s = 0; // 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; // Y offset initialization final int offsetY = 4 * yfrac[j]; // 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; // X offset initialization final int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and check if the value is a No Data. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xff; if (byteLookupTable[k][(int) pixelKernel[h][z]] != destinationNoDataByte[k]) { // temp++; weight |= (1 << (4 * h + z)); // weightArray[h][z] = 1; } else { // weightArray[h][z] = 0; weight &= (0xffff - (1 << 4 * h + z)); } } temp = (byte) ((weight >> 4 * h) & 0x0F); final long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); tempSum = tempData[0] * dataHi[offsetX] + tempData[1] * dataHi[offsetX + 1] + tempData[2] * dataHi[offsetX + 2] + tempData[3] * dataHi[offsetX + 3]; // if ((weightArray[h][0] + weightArray[h][1] + weightArray[h][2] + weightArray[h][3]) > 0) { if (temp > 0) { weightVert |= (1 << h); // weightArrayVertical[h] = 1; } else { weightVert &= (0x0F - (1 << h)); // weightArrayVertical[h] = 0; } sumArray[h] = ((tempSum + round) >> precisionBits); } // Control if the 16 pixel are all No Data if (weight == 0) { dstData[dstPixelOffset] = destinationNoDataByte[k]; } else { // temp = 0; weight = 0; final long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); weightVert = 0; // Vertical sum update sum = tempData[0] * dataVi[offsetY] + tempData[1] * dataVi[offsetY + 1] + tempData[2] * dataVi[offsetY + 2] + tempData[3] * dataVi[offsetY + 3]; // Interpolation s = (int) ((sum + round) >> precisionBits); sum = 0; // Clamp and overshooting fix s = clampAndFixOvershootingByte(s, k); dstData[dstPixelOffset] = (byte) (s & 0xff); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { final long[][] pixelKernel = new long[4][4]; final long[] sumArray = new long[4]; // final int[][] weightArray = new int[4][4]; // final int[] weightArrayVertical = new int[4]; short weight = 0; byte weightVert = 0; byte temp = 0; final long[] emptyArray = new long[4]; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataByte[k]; } else { // int tempND = 0; int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xff; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum tempROI += ((byte) (roiDataArray[index] & 0xff) != 0 ? 1 : 0); } if (byteLookupTable[k][(int) pixelKernel[h][z]] != destinationNoDataByte[k]) { // tempND++; weight |= (0x01 << (4 * h + z)); // weightArray[h][z] = 1; } else { // weightArray[h][z] = 0; weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataByte[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHi[offsetX + z]); } // if ((weightArray[h][0] + weightArray[h][1] // + weightArray[h][2] + weightArray[h][3]) > 0) { // weightArrayVertical[h] = 1; // } else { // weightArrayVertical[h] = 0; // } if (temp > 0) { weightVert |= (0x01 << h); // weightArrayVertical[h] = 1; } else { weightVert &= (0x0F - (0x01 << h)); // weightArrayVertical[h] = 0; } sumArray[h] = ((tempSum + round) >> precisionBits); } long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); // weight reset weightVert = 0; weight = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp and overshooting fix s = clampAndFixOvershootingByte(s, k); dstData[dstPixelOffset] = (byte) (s & 0xff); } } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { final long[][] pixelKernel = new long[4][4]; final long[] sumArray = new long[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // final int[][] weightArray = new int[4][4]; // final int[] weightArrayVertical = new int[4]; final long[] emptyArray = new long[4]; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. // int tempND = 0; int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xff; tempROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xff; if (byteLookupTable[k][(int) pixelKernel[h][z]] != destinationNoDataByte[k]) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataByte[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHi[offsetX + z]); } if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = ((tempSum + round) >> precisionBits); } long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); // weight reset weight = 0; weightVert = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp and overshooting fix s = clampAndFixOvershootingByte(s, k); dstData[dstPixelOffset] = (byte) (s & 0xff); } } else { 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; long sum = 0; int s = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value for (int h = 0; h < 4; h++) { // Row temporary sum initialization long temp = 0; for (int z = 0; z < 4; z++) { // Selection of one pixel int pixelValue = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xffff; // Update of the temporary sum temp += (pixelValue * dataHi[offsetX + z]); } // Vertical sum update sum += ((temp + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp if (s > 65536) { s = 65536; } else if (s < 0) { s = 0; } // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; int[][] pixelKernel = new int[4][4]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xffff; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum temp += ((short) (roiDataArray[index] & 0xffff) != 0 ? 1 : 0); } } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]); } // Vertical sum update sum += ((tempSum + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp and overshooting fix s = clampAndFixOvershootingUShort(s, k); 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; int[][] pixelKernel = new int[4][4]; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (roiBounds.contains(x0, y0)) { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xffff; temp += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xffff; } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]); } // Vertical sum update sum += ((tempSum + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp and overshooting fix s = clampAndFixOvershootingUShort(s, k); dstData[dstPixelOffset] = (short) (s & 0xffff); } } 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) { long[][] pixelKernel = new long[4][4]; long[] sumArray = new long[4]; long[] emptyArray = new long[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // Row temporary sum initialization long tempSum = 0; long sum = 0; // final result initialization int s = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and check if the value is a No Data. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xffff; if (!noData.contains((short) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } temp = (byte) ((weight >> 4 * h) & 0x0F); long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); tempSum = tempData[0] * dataHi[offsetX] + tempData[1] * dataHi[offsetX + 1] + tempData[2] * dataHi[offsetX + 2] + tempData[3] * dataHi[offsetX + 3]; if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = ((tempSum + round) >> precisionBits); } // Control if the 16 pixel are all No Data if (weight == 0) { dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else { temp = 0; long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update sum = tempData[0] * dataVi[offsetY] + tempData[1] * dataVi[offsetY + 1] + tempData[2] * dataVi[offsetY + 2] + tempData[3] * dataVi[offsetY + 3]; // Interpolation s = (int) ((sum + round) >> precisionBits); sum = 0; // Clamp and overshooting fix s = clampAndFixOvershootingUShort(s, k); dstData[dstPixelOffset] = (short) (s & 0xffff); } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { final long[][] pixelKernel = new long[4][4]; final long[] sumArray = new long[4]; final long[] emptyArray = new long[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else { int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xffff; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum tempROI += ((short) (roiDataArray[index] & 0xffff) != 0 ? 1 : 0); } if (!noData.contains((short) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHi[offsetX + z]); } if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = ((tempSum + round) >> precisionBits); } long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp and overshooting fix s = clampAndFixOvershootingUShort(s, k); dstData[dstPixelOffset] = (short) (s & 0xffff); } } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { final long[][] pixelKernel = new long[4][4]; final long[] sumArray = new long[4]; final long[] emptyArray = new long[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride] & 0xffff; tempROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0) & 0xffff; if (!noData.contains((short) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataUShort[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHi[offsetX + z]); } if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = ((tempSum + round) >> precisionBits); } long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp and overshooting fix s = clampAndFixOvershootingUShort(s, k); dstData[dstPixelOffset] = (short) (s & 0xffff); } } else { 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; long sum = 0; int s = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value for (int h = 0; h < 4; h++) { // Row temporary sum initialization long temp = 0; for (int z = 0; z < 4; z++) { // Selection of one pixel int pixelValue = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; // Update of the temporary sum temp += (pixelValue * dataHi[offsetX + z]); } // Vertical sum update sum += ((temp + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp if (s > Short.MAX_VALUE) { s = Short.MAX_VALUE; } else if (s < Short.MIN_VALUE) { s = Short.MIN_VALUE; } // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; int[][] pixelKernel = new int[4][4]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataShort[k]; } else { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum temp += ((short) (roiDataArray[index]) != 0 ? 1 : 0); } } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataShort[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]); } // Vertical sum update sum += ((tempSum + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp if (s > Short.MAX_VALUE) { s = Short.MAX_VALUE; } else if (s < Short.MIN_VALUE) { s = Short.MIN_VALUE; } 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; int[][] pixelKernel = new int[4][4]; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (roiBounds.contains(x0, y0)) { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; temp += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0); } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataShort[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]); } // Vertical sum update sum += ((tempSum + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp if (s > Short.MAX_VALUE) { s = Short.MAX_VALUE; } else if (s < Short.MIN_VALUE) { s = Short.MIN_VALUE; } dstData[dstPixelOffset] = (short) s; } } 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) { long[][] pixelKernel = new long[4][4]; long[] sumArray = new long[4]; long[] emptyArray = new long[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // Row temporary sum initialization long tempSum = 0; long sum = 0; // final result initialization int s = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and check if the value is a No Data. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; if (!noData.contains((short) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } temp = (byte) ((weight >> 4 * h) & 0x0F); long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); tempSum = tempData[0] * dataHi[offsetX] + tempData[1] * dataHi[offsetX + 1] + tempData[2] * dataHi[offsetX + 2] + tempData[3] * dataHi[offsetX + 3]; if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = ((tempSum + round) >> precisionBits); } // Control if the 16 pixel are all No Data if (weight == 0) { dstData[dstPixelOffset] = destinationNoDataShort[k]; } else { long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update sum = tempData[0] * dataVi[offsetY] + tempData[1] * dataVi[offsetY + 1] + tempData[2] * dataVi[offsetY + 2] + tempData[3] * dataVi[offsetY + 3]; // Interpolation s = (int) ((sum + round) >> precisionBits); sum = 0; // Clamp if (s > Short.MAX_VALUE) { s = Short.MAX_VALUE; } else if (s < Short.MIN_VALUE) { s = Short.MIN_VALUE; } dstData[dstPixelOffset] = (short) s; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { final long[][] pixelKernel = new long[4][4]; final long[] sumArray = new long[4]; final long[] emptyArray = new long[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataShort[k]; } else { int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum tempROI += ((short) (roiDataArray[index]) != 0 ? 1 : 0); } if (!noData.contains((short) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataShort[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHi[offsetX + z]); } if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = ((tempSum + round) >> precisionBits); } long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp if (s > Short.MAX_VALUE) { s = Short.MAX_VALUE; } else if (s < Short.MIN_VALUE) { s = Short.MIN_VALUE; } dstData[dstPixelOffset] = (short) s; } } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { final long[][] pixelKernel = new long[4][4]; final long[] sumArray = new long[4]; final long[] emptyArray = new long[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; tempROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0); if (!noData.contains((short) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataShort[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHi[offsetX + z]); } if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = ((tempSum + round) >> precisionBits); } long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // Clamp if (s > Short.MAX_VALUE) { s = Short.MAX_VALUE; } else if (s < Short.MIN_VALUE) { s = Short.MIN_VALUE; } dstData[dstPixelOffset] = (short) s; } } else { 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; long sum = 0; int s = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value for (int h = 0; h < 4; h++) { // Row temporary sum initialization long temp = 0; for (int z = 0; z < 4; z++) { // Selection of one pixel int pixelValue = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; // Update of the temporary sum temp += (pixelValue * dataHi[offsetX + z]); } // Vertical sum update sum += ((temp + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; int[][] pixelKernel = new int[4][4]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataInt[k]; } else { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum temp += ((roiDataArray[index]) != 0 ? 1 : 0); } } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataInt[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]); } // Vertical sum update sum += ((tempSum + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); 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 int[] srcData = srcDataArrays[k]; final int[] dstData = dstDataArrays[k]; // Line and band Offset initialization int dstlineOffset = dstBandOffsets[k]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; int[][] pixelKernel = new int[4][4]; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (roiBounds.contains(x0, y0)) { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; temp += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0); } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataInt[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHi[offsetX + z]); } // Vertical sum update sum += ((tempSum + round) >> precisionBits) * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); dstData[dstPixelOffset] = s; } } 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) { long[][] pixelKernel = new long[4][4]; long[] sumArray = new long[4]; long[] emptyArray = new long[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // Row temporary sum initialization long tempSum = 0; long sum = 0; // final result initialization int s = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and check if the value is a No Data. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; if (!noData.contains((int) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } temp = (byte) ((weight >> 4 * h) & 0x0F); long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); tempSum = tempData[0] * dataHi[offsetX] + tempData[1] * dataHi[offsetX + 1] + tempData[2] * dataHi[offsetX + 2] + tempData[3] * dataHi[offsetX + 3]; if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = ((tempSum + round) >> precisionBits); } // Control if the 16 pixel are all No Data if (weight == 0) { dstData[dstPixelOffset] = destinationNoDataInt[k]; } else { long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update sum = tempData[0] * dataVi[offsetY] + tempData[1] * dataVi[offsetY + 1] + tempData[2] * dataVi[offsetY + 2] + tempData[3] * dataVi[offsetY + 3]; // Interpolation s = (int) ((sum + round) >> precisionBits); sum = 0; dstData[dstPixelOffset] = s; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { final long[][] pixelKernel = new long[4][4]; final long[] sumArray = new long[4]; final long[] emptyArray = new long[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataInt[k]; } else { int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum tempROI += ((roiDataArray[index]) != 0 ? 1 : 0); } if (!noData.contains((int) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataInt[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHi[offsetX + z]); } if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = ((tempSum + round) >> precisionBits); } long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); dstData[dstPixelOffset] = s; } } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { final long[][] pixelKernel = new long[4][4]; final long[] sumArray = new long[4]; final long[] emptyArray = new long[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; tempROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0); if (!noData.contains((int) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataInt[k]; } else { long sum = 0; int s = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization long tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); long[] tempData = bicubicInpainting(pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHi[offsetX + z]); } if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = ((tempSum + round) >> precisionBits); } long[] tempData = bicubicInpainting(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVi[offsetY + h]; } // Interpolation s = (int) ((sum + round) >> precisionBits); dstData[dstPixelOffset] = s; } } else { 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, 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 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; double sum = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value for (int h = 0; h < 4; h++) { // Row temporary sum initialization double temp = 0; for (int z = 0; z < 4; z++) { // Selection of one pixel float pixelValue = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; // Update of the temporary sum temp += (pixelValue * dataHf[offsetX + z]); } // Vertical sum update sum += temp * dataVf[offsetY + h]; } // Clamp if (sum > Float.MAX_VALUE) { sum = Float.MAX_VALUE; } else if (sum < -Float.MAX_VALUE) { sum = -Float.MAX_VALUE; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (float) sum; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; float[][] pixelKernel = new float[4][4]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum temp += ((roiDataArray[index]) != 0 ? 1 : 0); } } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else { double sum = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization double tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHf[offsetX + z]); } // Vertical sum update sum += tempSum * dataVf[offsetY + h]; } // Clamp if (sum > Float.MAX_VALUE) { sum = Float.MAX_VALUE; } else if (sum < -Float.MAX_VALUE) { sum = -Float.MAX_VALUE; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (float) sum; } } // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; float[][] pixelKernel = new float[4][4]; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (roiBounds.contains(x0, y0)) { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; temp += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0); } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else { double sum = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization double tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHf[offsetX + z]); } // Vertical sum update sum += tempSum * dataVf[offsetY + h]; } // Clamp if (sum > Float.MAX_VALUE) { sum = Float.MAX_VALUE; } else if (sum < -Float.MAX_VALUE) { sum = -Float.MAX_VALUE; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (float) sum; } } 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) { double[][] pixelKernel = new double[4][4]; double[] sumArray = new double[4]; double[] emptyArray = new double[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // Row temporary sum initialization double tempSum = 0; double sum = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and check if the value is a No Data. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; if (!noData.contains((float) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } temp = (byte) ((weight >> 4 * h) & 0x0F); double[] tempData = bicubicInpaintingDouble(pixelKernel[h], temp, emptyArray); tempSum = tempData[0] * dataHf[offsetX] + tempData[1] * dataHf[offsetX + 1] + tempData[2] * dataHf[offsetX + 2] + tempData[3] * dataHf[offsetX + 3]; if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = tempSum; } // Control if the 16 pixel are all No Data if (weight == 0) { dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else { double[] tempData = bicubicInpaintingDouble(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update sum = tempData[0] * dataVf[offsetY] + tempData[1] * dataVf[offsetY + 1] + tempData[2] * dataVf[offsetY + 2] + tempData[3] * dataVf[offsetY + 3]; // Clamp if (sum > Float.MAX_VALUE) { sum = Float.MAX_VALUE; } else if (sum < -Float.MAX_VALUE) { sum = -Float.MAX_VALUE; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (float) sum; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { final double[][] pixelKernel = new double[4][4]; final double[] sumArray = new double[4]; final double[] emptyArray = new double[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else { int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum tempROI += ((roiDataArray[index]) != 0 ? 1 : 0); } if (!noData.contains((float) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else { double sum = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization double tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); double[] tempData = bicubicInpaintingDouble( pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHf[offsetX + z]); } if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = tempSum; } double[] tempData = bicubicInpaintingDouble(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVf[offsetY + h]; } // Clamp if (sum > Float.MAX_VALUE) { sum = Float.MAX_VALUE; } else if (sum < -Float.MAX_VALUE) { sum = -Float.MAX_VALUE; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (float) sum; } } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { final double[][] pixelKernel = new double[4][4]; final double[] sumArray = new double[4]; final double[] emptyArray = new double[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; tempROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0); if (!noData.contains((float) pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataFloat[k]; } else { double sum = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization double tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); double[] tempData = bicubicInpaintingDouble( pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHf[offsetX + z]); } if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = tempSum; } double[] tempData = bicubicInpaintingDouble(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVf[offsetY + h]; } // Clamp if (sum > Float.MAX_VALUE) { sum = Float.MAX_VALUE; } else if (sum < -Float.MAX_VALUE) { sum = -Float.MAX_VALUE; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = (float) sum; } } else { 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, 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 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; double sum = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value for (int h = 0; h < 4; h++) { // Row temporary sum initialization double temp = 0; for (int z = 0; z < 4; z++) { // Selection of one pixel double pixelValue = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; // Update of the temporary sum temp += (pixelValue * dataHd[offsetX + z]); } // Vertical sum update sum += temp * dataVd[offsetY + h]; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = sum; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; double[][] pixelKernel = new double[4][4]; final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum temp += ((roiDataArray[index]) != 0 ? 1 : 0); } } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else { double sum = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization double tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHd[offsetX + z]); } // Vertical sum update sum += tempSum * dataVd[offsetY + h]; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = sum; } } // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; double[][] pixelKernel = new double[4][4]; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (roiBounds.contains(x0, y0)) { int temp = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; temp += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0); } } // Control if the 16 pixel are outside the ROI if (temp == 0) { dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else { double sum = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization double tempSum = 0; for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (pixelKernel[h][z] * dataHd[offsetX + z]); } // Vertical sum update sum += tempSum * dataVd[offsetY + h]; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = sum; } } 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) { double[][] pixelKernel = new double[4][4]; double[] sumArray = new double[4]; double[] emptyArray = new double[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // Row temporary sum initialization double tempSum = 0; double sum = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and check if the value is a No Data. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; if (!noData.contains(pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } temp = (byte) ((weight >> 4 * h) & 0x0F); double[] tempData = bicubicInpaintingDouble(pixelKernel[h], temp, emptyArray); tempSum = tempData[0] * dataHd[offsetX] + tempData[1] * dataHd[offsetX + 1] + tempData[2] * dataHd[offsetX + 2] + tempData[3] * dataHd[offsetX + 3]; if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = tempSum; } // Control if the 16 pixel are all No Data if (weight == 0) { dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else { double[] tempData = bicubicInpaintingDouble(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update sum = tempData[0] * dataVd[offsetY] + tempData[1] * dataVd[offsetY + 1] + tempData[2] * dataVd[offsetY + 2] + tempData[3] * dataVd[offsetY + 3]; // The interpolated value is saved in the destination array dstData[dstPixelOffset] = sum; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { if (useRoiAccessor) { final double[][] pixelKernel = new double[4][4]; final double[] sumArray = new double[4]; final double[] emptyArray = new double[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. final int baseIndex = (posx / dnumBands) + (yposRoi[j]); // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. if (baseIndex > roiDataLength || roiDataArray[baseIndex] == 0) { dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else { int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; int index = baseIndex - 1 + z + (h - 1) * (roiScanlineStride); if (index < roiDataLength) { // Update of the weight sum tempROI += ((roiDataArray[index]) != 0 ? 1 : 0); } if (!noData.contains(pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else { double sum = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization double tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); double[] tempData = bicubicInpaintingDouble( pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHd[offsetX + z]); } if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = tempSum; } double[] tempData = bicubicInpaintingDouble(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVd[offsetY + h]; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = sum; } } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } else { final double[][] pixelKernel = new double[4][4]; final double[] sumArray = new double[4]; final double[] emptyArray = new double[4]; short weight = 0; byte weightVert = 0; byte temp = 0; // 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]; 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 int posy = ypos[j] + bandOffset; // Y offset initialization int offsetY = 4 * yfrac[j]; // cycle on the x values for (int i = 0; i < dwidth; i++) { // x position selection int posx = xpos[i]; // PixelPositions int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + (posy - bandOffset) / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int pos = posx + posy; // Check if the selected index belongs to the roi data array: if it is not present, the weight is 0, // Otherwise it takes the related value. int tempROI = 0; // X offset initialization int offsetX = 4 * xfrac[i]; // Cycle through all the 16 kernel pixel and calculation of the interpolated value // and cycle for filling all the ROI index by shifting of 1 on the x axis // and by roiscanlinestride on the y axis. for (int h = 0; h < 4; h++) { for (int z = 0; z < 4; z++) { // Selection of one pixel pixelKernel[h][z] = srcData[pos + (z - 1) * srcPixelStride + (h - 1) * srcScanlineStride]; tempROI += roiIter.getSample(x0 + h - 1, y0 + z - 1, 0); if (!noData.contains(pixelKernel[h][z])) { weight |= (0x01 << (4 * h + z)); } else { weight &= (0xffff - (0x01 << 4 * h + z)); } } } // Control if the 16 pixel are outside the ROI if (weight == 0 || tempROI == 0) { dstData[dstPixelOffset] = destinationNoDataDouble[k]; } else { double sum = 0; for (int h = 0; h < 4; h++) { // Row temporary sum initialization double tempSum = 0; temp = (byte) ((weight >> 4 * h) & 0x0F); double[] tempData = bicubicInpaintingDouble( pixelKernel[h], temp, emptyArray); for (int z = 0; z < 4; z++) { // Update of the temporary sum tempSum += (tempData[z] * dataHd[offsetX + z]); } if (temp > 0) { weightVert |= (0x01 << h); } else { weightVert &= (0x0F - (0x01 << h)); } sumArray[h] = tempSum; } double[] tempData = bicubicInpaintingDouble(sumArray, weightVert, emptyArray); weight = 0; weightVert = 0; // Vertical sum update for (int h = 0; h < 4; h++) { // Update of the temporary sum sum += tempData[h] * dataVd[offsetY + h]; } // The interpolated value is saved in the destination array dstData[dstPixelOffset] = sum; } } else { dstData[dstPixelOffset] = destinationNoDataDouble[k]; } // destination pixel offset update dstPixelOffset += dstPixelStride; } // destination line offset update dstlineOffset += dstScanlineStride; } } } } } } } // This method is used for filling the no data values inside the interpolation kernel with the values of the adjacent pixels private long[] bicubicInpainting(long[] array, short weightSum, long[] emptyArray) { // Absence of No Data, the pixels are returned. if (weightSum == 15) { return array; } long s_ = array[0]; long s0 = array[1]; long s1 = array[2]; long s2 = array[3]; emptyArray[0] = 0; emptyArray[1] = 0; emptyArray[2] = 0; emptyArray[3] = 0; switch (weightSum) { case 0: // 0 0 0 0 break; case 1: // 0 0 0 x emptyArray[0] = s_; emptyArray[1] = s_; emptyArray[2] = s_; emptyArray[3] = s_; break; case 2: // 0 0 x 0 emptyArray[0] = s0; emptyArray[1] = s0; emptyArray[2] = s0; emptyArray[3] = s0; break; case 3: // 0 0 x x emptyArray[0] = s_; emptyArray[1] = s0; emptyArray[2] = s0; emptyArray[3] = s0; break; case 4: // 0 x 0 0 emptyArray[0] = s1; emptyArray[1] = s1; emptyArray[2] = s1; emptyArray[3] = s1; break; case 5: // 0 x 0 x emptyArray[0] = s_; emptyArray[1] = (s_ + s1) / 2; emptyArray[2] = s1; emptyArray[3] = s1; break; case 6: // 0 x x 0 emptyArray[0] = s0; emptyArray[1] = s0; emptyArray[2] = s1; emptyArray[3] = s1; break; case 7: // 0 x x x emptyArray[0] = s_; emptyArray[1] = s0; emptyArray[2] = s1; emptyArray[3] = s1; break; case 8: // x 0 0 0 emptyArray[0] = s2; emptyArray[1] = s2; emptyArray[2] = s2; emptyArray[3] = s2; break; case 9: // x 0 0 x emptyArray[0] = s_; emptyArray[1] = (s_ + s2) / 2; emptyArray[2] = (s_ + s2) / 2; emptyArray[3] = s2; break; case 10: // x 0 x 0 emptyArray[0] = s0; emptyArray[1] = s0; emptyArray[2] = (s0 + s2) / 2; emptyArray[3] = s2; break; case 11: // x 0 x x emptyArray[0] = s_; emptyArray[1] = s0; emptyArray[2] = (s0 + s2) / 2; emptyArray[3] = s2; break; case 12: // x x 0 0 emptyArray[0] = s1; emptyArray[1] = s1; emptyArray[2] = s1; emptyArray[3] = s2; break; case 13: // x x 0 x emptyArray[0] = s_; emptyArray[1] = (s_ + s1) / 2; emptyArray[2] = s1; emptyArray[3] = s2; break; case 14: // x x x 0 emptyArray[0] = s0; emptyArray[1] = s0; emptyArray[2] = s1; emptyArray[3] = s2; break; default: throw new IllegalArgumentException("Array cannot be composed from more than 4 elements"); } return emptyArray; } // This method is used for filling the no data values inside the interpolation kernel with the values of the adjacent pixels private double[] bicubicInpaintingDouble(double[] array, short weightSum, double[] emptyArray) { // Absence of No Data, the pixels are returned. if (weightSum == 15) { return array; } double s_ = array[0]; double s0 = array[1]; double s1 = array[2]; double s2 = array[3]; emptyArray[0] = 0; emptyArray[1] = 0; emptyArray[2] = 0; emptyArray[3] = 0; switch (weightSum) { case 0: // 0 0 0 0 break; case 1: // 0 0 0 x emptyArray[0] = s_; emptyArray[1] = s_; emptyArray[2] = s_; emptyArray[3] = s_; break; case 2: // 0 0 x 0 emptyArray[0] = s0; emptyArray[1] = s0; emptyArray[2] = s0; emptyArray[3] = s0; break; case 3: // 0 0 x x emptyArray[0] = s_; emptyArray[1] = s0; emptyArray[2] = s0; emptyArray[3] = s0; break; case 4: // 0 x 0 0 emptyArray[0] = s1; emptyArray[1] = s1; emptyArray[2] = s1; emptyArray[3] = s1; break; case 5: // 0 x 0 x emptyArray[0] = s_; emptyArray[1] = (s_ + s1) / 2; emptyArray[2] = s1; emptyArray[3] = s1; break; case 6: // 0 x x 0 emptyArray[0] = s0; emptyArray[1] = s0; emptyArray[2] = s1; emptyArray[3] = s1; break; case 7: // 0 x x x emptyArray[0] = s_; emptyArray[1] = s0; emptyArray[2] = s1; emptyArray[3] = s1; break; case 8: // x 0 0 0 emptyArray[0] = s2; emptyArray[1] = s2; emptyArray[2] = s2; emptyArray[3] = s2; break; case 9: // x 0 0 x emptyArray[0] = s_; emptyArray[1] = (s_ + s2) / 2; emptyArray[2] = (s_ + s2) / 2; emptyArray[3] = s2; break; case 10: // x 0 x 0 emptyArray[0] = s0; emptyArray[1] = s0; emptyArray[2] = (s0 + s2) / 2; emptyArray[3] = s2; break; case 11: // x 0 x x emptyArray[0] = s_; emptyArray[1] = s0; emptyArray[2] = (s0 + s2) / 2; emptyArray[3] = s2; break; case 12: // x x 0 0 emptyArray[0] = s1; emptyArray[1] = s1; emptyArray[2] = s1; emptyArray[3] = s2; break; case 13: // x x 0 x emptyArray[0] = s_; emptyArray[1] = (s_ + s1) / 2; emptyArray[2] = s1; emptyArray[3] = s2; break; case 14: // x x x 0 emptyArray[0] = s0; emptyArray[1] = s0; emptyArray[2] = s1; emptyArray[3] = s2; break; default: throw new IllegalArgumentException("Array cannot be composed from more than 4 elements"); } return emptyArray; } private int clampAndFixOvershootingByte(int s, int k) { // Clamp if (s > 255) { s = 255; } else if (s < 0) { s = 0; } // Handle corner cases for overshooting if (destinationNoDataByte[k] == 0 && s == 0) { s = 1; } else if (destinationNoDataByte[k] == 255 && s == 255) { s = 254; } return s; } private int clampAndFixOvershootingUShort(int s, int k) { // Clamp if (s > 65535) { s = 65535; } else if (s < 0) { s = 0; } // Handle corner cases for overshooting if (destinationNoDataUShort[k] == 0 && s == 0) { s = 1; } else if (destinationNoDataUShort[k] == 65535 && s == 65535) { s = 65534; } return s; } }