/* 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.warp; import it.geosolutions.jaiext.range.Range; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.IndexColorModel; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.util.Map; import javax.media.jai.BorderExtender; import javax.media.jai.ImageLayout; import javax.media.jai.Interpolation; import javax.media.jai.PlanarImage; import javax.media.jai.ROI; import javax.media.jai.RasterAccessor; import javax.media.jai.Warp; import javax.media.jai.iterator.RandomIter; import com.sun.media.jai.util.ImageUtil; /** * An <code>OpImage</code> implementing the general "Warp" operation as described in <code>javax.media.jai.operator.WarpDescriptor</code>. It supports * all interpolation cases. * * <p> * The layout for the destination image may be specified via the <code>ImageLayout</code> parameter. However, only those settings suitable for this * operation will be used. The unsuitable settings will be replaced by default suitable values. An optional ROI object and a NoData Range can be used. * If a backward mapped pixel lies outside ROI or it is a NoData, then the destination pixel value is a background value. * * If the input image contains an IndexColorModel, then pixel values are taken directly from the input color table. * * @since EA2 * @see javax.media.jai.Warp * @see javax.media.jai.WarpOpImage * @see javax.media.jai.operator.WarpDescriptor * @see WarpRIF * */ @SuppressWarnings("unchecked") final class WarpGeneralOpImage extends WarpOpImage { private static final int NODATA_VALUE = 0; /** Color table representing source's IndexColorModel. */ private byte[][] ctable = null; /** LookupTable used for a faster NoData check */ private byte[][] byteLookupTable; /** * Constructs a WarpGeneralOpImage. * * @param source The source image. * @param extender A BorderExtender, or null. * @param extender A BorderExtender, or null. * @param layout The destination image layout. * @param warp An object defining the warp algorithm. * @param interp An object describing the interpolation method. * @param background background values to set. * @param roi input ROI object used. * @param noData NoData Range object used for checking if NoData are present. */ public WarpGeneralOpImage(RenderedImage source, BorderExtender extender, Map<?, ?> config, ImageLayout layout, Warp warp, Interpolation interp, double[] background, ROI sourceROI, Range noData) { super(source, layout, config, false, extender, interp, warp, background, sourceROI, noData); /* * If the source has IndexColorModel, get the RGB color table. Note, in this case, the source should have an integral data type. And dest * always has data type byte. */ ColorModel srcColorModel = source.getColorModel(); if (srcColorModel instanceof IndexColorModel) { IndexColorModel icm = (IndexColorModel) srcColorModel; ctable = new byte[3][icm.getMapSize()]; icm.getReds(ctable[0]); icm.getGreens(ctable[1]); icm.getBlues(ctable[2]); } /* * Selection of a destinationNoData value for each datatype */ //backgroundValues[b] = backgroundValues[0]; SampleModel sm = source.getSampleModel(); // Source image data Type int srcDataType = sm.getDataType(); // Creation of a lookuptable containing the values to use for no data if (hasNoData && srcDataType == DataBuffer.TYPE_BYTE) { int numBands = getNumBands(); byteLookupTable = new byte[numBands][256]; for (int b = 0; b < numBands; b++) { for (int i = 0; i < byteLookupTable[0].length; i++) { byte value = (byte) i; if (noDataRange.contains(value)) { byteLookupTable[b][i] = (byte) backgroundValues[b]; } else { byteLookupTable[b][i] = value; } } } } // Definition of the padding if (interp != null) { leftPad = interp.getLeftPadding(); rightPad = interp.getRightPadding(); topPad = interp.getTopPadding(); bottomPad = interp.getBottomPadding(); } else { leftPad = rightPad = topPad = bottomPad = 0; } } protected void computeRectByte(PlanarImage src, RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Setting of the Random iterator keeping into account the presence of the Borderextender int minX, maxX, minY, maxY; RandomIter iter; if (extended) { // Creation of an iterator on the image extended by the padding factors iter = getRandomIterator(src, leftPad, rightPad, topPad, bottomPad, extender); // Definition of the image bounds minX = src.getMinX(); maxX = src.getMaxX(); minY = src.getMinY(); maxY = src.getMaxY(); } else { // Creation of an iterator on the image iter = getRandomIterator(src, null); // Definition of the image bounds minX = src.getMinX() + leftPad; // Left padding maxX = src.getMaxX() - rightPad; // Right padding minY = src.getMinY() + topPad; // Top padding maxY = src.getMaxY() - bottomPad; // Bottom padding } final int dstWidth = dst.getWidth(); final int dstHeight = dst.getHeight(); final int dstBands = dst.getNumBands(); final int lineStride = dst.getScanlineStride(); final int pixelStride = dst.getPixelStride(); final int[] bandOffsets = dst.getBandOffsets(); final byte[][] data = dst.getByteDataArrays(); final float[] warpData = new float[2 * dstWidth]; int lineOffset = 0; int kwidth = interp.getWidth(); int kheight = interp.getHeight(); int precH = 1 << interp.getSubsampleBitsH(); int precV = 1 << interp.getSubsampleBitsV(); int[][] samples = new int[kheight][kwidth]; boolean roiWeight; if (ctable == null) { // source does not have IndexColorModel // ONLY VALID DATA if (caseA || (caseB && roiContainsTile)) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } else { // Interpolation xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSample(xint + i, yint + j, b) & 0xFF; } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil.clampByte(interp .interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // ONLY ROI } else if (caseB) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSample(xint + i, yint + j, b) & 0xFF; } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil .clampByte(interp.interpolate(samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } pixelOffset += pixelStride; } } // ONLY NODATA } else if (caseC || (hasROI && hasNoData && roiContainsTile)) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // NODATA check // // for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { // If the value is a NODATA, is substituted with 0 samples[j][i] = byteLookupTable[b][iter.getSample(xint + i, yint + j, b) & 0xFF]; } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil.clampByte(interp .interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // BOTH ROI AND NODATA } else { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { // // NODATA check // // for (int i = 0; i < kwidth; i++) { // If the value is a NODATA, is substituted with 0 samples[j][i] = byteLookupTable[b][iter.getSample( xint + i, yint + j, b) & 0xFF]; } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil .clampByte(interp.interpolate(samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } pixelOffset += pixelStride; } } } } else { // source has IndexColorModel // ONLY VALID DATA if (caseA || (caseB && roiContainsTile)) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { byte[] t = ctable[b]; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = t[iter.getSample(xint + i, yint + j, 0) & 0xFF] & 0xFF; } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil.clampByte(interp .interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // ONLY ROI } else if (caseB) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { byte[] t = ctable[b]; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = t[iter.getSample(xint + i, yint + j, 0) & 0xFF] & 0xFF; } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil .clampByte(interp.interpolate(samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } pixelOffset += pixelStride; } } // ONLY NODATA } else if (caseC || (hasROI && hasNoData && roiContainsTile)) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; // // NODATA check // // for (int b = 0; b < dstBands; b++) { byte[] t = ctable[b]; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { // If the value is a NODATA, is substituted with 0 samples[j][i] = byteLookupTable[b][t[iter.getSample(xint + i, yint + j, 0) & 0xFF] & 0xFF]; } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil.clampByte(interp .interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // BOTH ROI AND NODATA } else { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { byte[] t = ctable[b]; // // NODATA check // // for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { // If the value is a NODATA, is substituted with 0 samples[j][i] = byteLookupTable[b][t[iter.getSample(xint + i, yint + j, 0) & 0xFF] & 0xFF]; } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil .clampByte(interp.interpolate(samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte) backgroundValues[b]; } } } pixelOffset += pixelStride; } } } } iter.done(); } protected void computeRectUShort(PlanarImage src, RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Setting of the Random iterator keeping into account the presence of the Borderextender int minX, maxX, minY, maxY; RandomIter iter; if (extended) { // Creation of an iterator on the image extended by the padding factors iter = getRandomIterator(src, leftPad, rightPad, topPad, bottomPad, extender); // Definition of the image bounds minX = src.getMinX(); maxX = src.getMaxX(); minY = src.getMinY(); maxY = src.getMaxY(); } else { // Creation of an iterator on the image iter = getRandomIterator(src, null); // Definition of the image bounds minX = src.getMinX() + leftPad; // Left padding maxX = src.getMaxX() - rightPad; // Right padding minY = src.getMinY() + topPad; // Top padding maxY = src.getMaxY() - bottomPad; // Bottom padding } int kwidth = interp.getWidth(); int kheight = interp.getHeight(); int dstWidth = dst.getWidth(); int dstHeight = dst.getHeight(); int dstBands = dst.getNumBands(); int lineStride = dst.getScanlineStride(); int pixelStride = dst.getPixelStride(); int[] bandOffsets = dst.getBandOffsets(); short[][] data = dst.getShortDataArrays(); int precH = 1 << interp.getSubsampleBitsH(); int precV = 1 << interp.getSubsampleBitsV(); float[] warpData = new float[2 * dstWidth]; int[][] samples = new int[kheight][kwidth]; boolean roiWeight; int lineOffset = 0; // ONLY VALID DATA if (caseA || (caseB && roiContainsTile)) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSample(xint + i, yint + j, b) & 0xFFFF; } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil.clampUShort(interp .interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // ONLY ROI } else if (caseB) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSample(xint + i, yint + j, b) & 0xFFFF; } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil .clampUShort(interp.interpolate(samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b]; } } } pixelOffset += pixelStride; } } // ONLY NODATA } else if (caseC || (hasROI && hasNoData && roiContainsTile)) { int value = 0; for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { // // NODATA check // // for (int i = 0; i < kwidth; i++) { value = iter.getSample(xint + i, yint + j, b) & 0xFFFF; // If the value is a NODATA, is substituted with 0 inside the kernel if (noDataRange.contains((short) value)) { samples[j][i] = NODATA_VALUE; } else { samples[j][i] = value; } } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil.clampUShort(interp .interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // BOTH ROI AND NODATA } else { int value = 0; for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { // // NODATA check // // for (int i = 0; i < kwidth; i++) { value = iter.getSample(xint + i, yint + j, b) & 0xFFFF; // If the value is a NODATA, is substituted with 0 inside the kernel if (noDataRange.contains((short) value)) { samples[j][i] = NODATA_VALUE; } else { samples[j][i] = value; } } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil .clampUShort(interp.interpolate(samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b]; } } } pixelOffset += pixelStride; } } } iter.done(); } protected void computeRectShort(PlanarImage src, RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Setting of the Random iterator keeping into account the presence of the Borderextender int minX, maxX, minY, maxY; RandomIter iter; if (extended) { // Creation of an iterator on the image extended by the padding factors iter = getRandomIterator(src, leftPad, rightPad, topPad, bottomPad, extender); // Definition of the image bounds minX = src.getMinX(); maxX = src.getMaxX(); minY = src.getMinY(); maxY = src.getMaxY(); } else { // Creation of an iterator on the image iter = getRandomIterator(src, null); // Definition of the image bounds minX = src.getMinX() + leftPad; // Left padding maxX = src.getMaxX() - rightPad; // Right padding minY = src.getMinY() + topPad; // Top padding maxY = src.getMaxY() - bottomPad; // Bottom padding } int kwidth = interp.getWidth(); int kheight = interp.getHeight(); int dstWidth = dst.getWidth(); int dstHeight = dst.getHeight(); int dstBands = dst.getNumBands(); int lineStride = dst.getScanlineStride(); int pixelStride = dst.getPixelStride(); int[] bandOffsets = dst.getBandOffsets(); short[][] data = dst.getShortDataArrays(); int precH = 1 << interp.getSubsampleBitsH(); int precV = 1 << interp.getSubsampleBitsV(); float[] warpData = new float[2 * dstWidth]; int[][] samples = new int[kheight][kwidth]; boolean roiWeight; int lineOffset = 0; // ONLY VALID DATA if (caseA || (caseB && roiContainsTile)) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSample(xint + i, yint + j, b); } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil.clampShort(interp .interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // ONLY ROI } else if (caseB) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSample(xint + i, yint + j, b); } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil.clampShort(interp .interpolate(samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b]; } } } pixelOffset += pixelStride; } } // ONLY NODATA } else if (caseC || (hasROI && hasNoData && roiContainsTile)) { int value = 0; for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { // // NODATA check // // for (int i = 0; i < kwidth; i++) { value = iter.getSample(xint + i, yint + j, b); // If the value is a NODATA, is substituted with 0 inside the kernel if (noDataRange.contains((short) value)) { samples[j][i] = NODATA_VALUE; } else { samples[j][i] = value; } } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil.clampShort(interp .interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // BOTH ROI AND NODATA } else { int value = 0; for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short) backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { // // NODATA check // // for (int i = 0; i < kwidth; i++) { value = iter.getSample(xint + i, yint + j, b); // If the value is a NODATA, is substituted with 0 inside the kernel if (noDataRange.contains((short) value)) { samples[j][i] = NODATA_VALUE; } else { samples[j][i] = value; } } } data[b][pixelOffset + bandOffsets[b]] = ImageUtil.clampShort(interp .interpolate(samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short)backgroundValues[b]; } } } pixelOffset += pixelStride; } } } iter.done(); } protected void computeRectInt(PlanarImage src, RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Setting of the Random iterator keeping into account the presence of the Borderextender int minX, maxX, minY, maxY; RandomIter iter; if (extended) { // Creation of an iterator on the image extended by the padding factors iter = getRandomIterator(src, leftPad, rightPad, topPad, bottomPad, extender); // Definition of the image bounds minX = src.getMinX(); maxX = src.getMaxX(); minY = src.getMinY(); maxY = src.getMaxY(); } else { // Creation of an iterator on the image iter = getRandomIterator(src, null); // Definition of the image bounds minX = src.getMinX() + leftPad; // Left padding maxX = src.getMaxX() - rightPad; // Right padding minY = src.getMinY() + topPad; // Top padding maxY = src.getMaxY() - bottomPad; // Bottom padding } int kwidth = interp.getWidth(); int kheight = interp.getHeight(); int dstWidth = dst.getWidth(); int dstHeight = dst.getHeight(); int dstBands = dst.getNumBands(); int lineStride = dst.getScanlineStride(); int pixelStride = dst.getPixelStride(); int[] bandOffsets = dst.getBandOffsets(); int[][] data = dst.getIntDataArrays(); int precH = 1 << interp.getSubsampleBitsH(); int precV = 1 << interp.getSubsampleBitsV(); float[] warpData = new float[2 * dstWidth]; int[][] samples = new int[kheight][kwidth]; boolean roiWeight; int lineOffset = 0; // ONLY VALID DATA if (caseA || (caseB && roiContainsTile)) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (int)backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSample(xint + i, yint + j, b); } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // ONLY ROI } else if (caseB) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (int)backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSample(xint + i, yint + j, b); } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate( samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (int)backgroundValues[b]; } } } pixelOffset += pixelStride; } } // ONLY NODATA } else if (caseC || (hasROI && hasNoData && roiContainsTile)) { int value = 0; for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (int)backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { // // NODATA check // // for (int i = 0; i < kwidth; i++) { value = iter.getSample(xint + i, yint + j, b); // If the value is a NODATA, is substituted with 0 inside the kernel if (noDataRange.contains(value)) { samples[j][i] = NODATA_VALUE; } else { samples[j][i] = value; } } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // BOTH ROI AND NODATA } else { int value = 0; for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); int xfrac = (int) ((sx - xint) * precH); int yfrac = (int) ((sy - yint) * precV); if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (int)backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { // // NODATA check // // for (int i = 0; i < kwidth; i++) { value = iter.getSample(xint + i, yint + j, b); // If the value is a NODATA, is substituted with 0 inside the kernel if (noDataRange.contains(value)) { samples[j][i] = NODATA_VALUE; } else { samples[j][i] = value; } } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate( samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (int)backgroundValues[b]; } } } pixelOffset += pixelStride; } } } iter.done(); } protected void computeRectFloat(PlanarImage src, RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Setting of the Random iterator keeping into account the presence of the Borderextender int minX, maxX, minY, maxY; RandomIter iter; if (extended) { // Creation of an iterator on the image extended by the padding factors iter = getRandomIterator(src, leftPad, rightPad, topPad, bottomPad, extender); // Definition of the image bounds minX = src.getMinX(); maxX = src.getMaxX(); minY = src.getMinY(); maxY = src.getMaxY(); } else { // Creation of an iterator on the image iter = getRandomIterator(src, null); // Definition of the image bounds minX = src.getMinX() + leftPad; // Left padding maxX = src.getMaxX() - rightPad; // Right padding minY = src.getMinY() + topPad; // Top padding maxY = src.getMaxY() - bottomPad; // Bottom padding } int kwidth = interp.getWidth(); int kheight = interp.getHeight(); int dstWidth = dst.getWidth(); int dstHeight = dst.getHeight(); int dstBands = dst.getNumBands(); int lineStride = dst.getScanlineStride(); int pixelStride = dst.getPixelStride(); int[] bandOffsets = dst.getBandOffsets(); float[][] data = dst.getFloatDataArrays(); float[] warpData = new float[2 * dstWidth]; float[][] samples = new float[kheight][kwidth]; boolean roiWeight; int lineOffset = 0; // ONLY VALID DATA if (caseA || (caseB && roiContainsTile)) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); float xfrac = sx - xint; float yfrac = sy - yint; if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (float)backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSampleFloat(xint + i, yint + j, b); } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // ONLY ROI } else if (caseB) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); float xfrac = sx - xint; float yfrac = sy - yint; if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (float)backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSampleFloat(xint + i, yint + j, b); } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate( samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (float)backgroundValues[b]; } } } pixelOffset += pixelStride; } } // ONLY NODATA } else if (caseC || (hasROI && hasNoData && roiContainsTile)) { float value = 0; for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); float xfrac = sx - xint; float yfrac = sy - yint; if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (float)backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { // // NODATA check // // for (int i = 0; i < kwidth; i++) { value = iter.getSampleFloat(xint + i, yint + j, b); // If the value is a NODATA, is substituted with 0 inside the kernel if (noDataRange.contains(value)) { samples[j][i] = NODATA_VALUE; } else { samples[j][i] = value; } } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // BOTH ROI AND NODATA } else { float value = 0; for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); float xfrac = sx - xint; float yfrac = sy - yint; if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (float)backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { // // NODATA check // // for (int i = 0; i < kwidth; i++) { value = iter.getSampleFloat(xint + i, yint + j, b); // If the value is a NODATA, is substituted with 0 inside the kernel if (noDataRange.contains(value)) { samples[j][i] = NODATA_VALUE; } else { samples[j][i] = value; } } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate( samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (float)backgroundValues[b]; } } } pixelOffset += pixelStride; } } } iter.done(); } protected void computeRectDouble(PlanarImage src, RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Setting of the Random iterator keeping into account the presence of the Borderextender int minX, maxX, minY, maxY; RandomIter iter; if (extended) { // Creation of an iterator on the image extended by the padding factors iter = getRandomIterator(src, leftPad, rightPad, topPad, bottomPad, extender); // Definition of the image bounds minX = src.getMinX(); maxX = src.getMaxX(); minY = src.getMinY(); maxY = src.getMaxY(); } else { // Creation of an iterator on the image iter = getRandomIterator(src, null); // Definition of the image bounds minX = src.getMinX() + leftPad; // Left padding maxX = src.getMaxX() - rightPad; // Right padding minY = src.getMinY() + topPad; // Top padding maxY = src.getMaxY() - bottomPad; // Bottom padding } int kwidth = interp.getWidth(); int kheight = interp.getHeight(); int dstWidth = dst.getWidth(); int dstHeight = dst.getHeight(); int dstBands = dst.getNumBands(); int lineStride = dst.getScanlineStride(); int pixelStride = dst.getPixelStride(); int[] bandOffsets = dst.getBandOffsets(); double[][] data = dst.getDoubleDataArrays(); float[] warpData = new float[2 * dstWidth]; double[][] samples = new double[kheight][kwidth]; boolean roiWeight; int lineOffset = 0; // ONLY VALID DATA if (caseA || (caseB && roiContainsTile)) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); float xfrac = sx - xint; float yfrac = sy - yint; if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSampleDouble(xint + i, yint + j, b); } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // ONLY ROI } else if (caseB) { for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); float xfrac = sx - xint; float yfrac = sy - yint; if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { samples[j][i] = iter.getSampleDouble(xint + i, yint + j, b); } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate( samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b]; } } } pixelOffset += pixelStride; } } // ONLY NODATA } else if (caseC || (hasROI && hasNoData && roiContainsTile)) { double value = 0; for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); float xfrac = sx - xint; float yfrac = sy - yint; if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { // // NODATA check // // for (int i = 0; i < kwidth; i++) { value = iter.getSampleDouble(xint + i, yint + j, b); // If the value is a NODATA, is substituted with 0 inside the kernel if (noDataRange.contains(value)) { samples[j][i] = NODATA_VALUE; } else { samples[j][i] = value; } } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate(samples, xfrac, yfrac)); } } pixelOffset += pixelStride; } } // BOTH ROI AND NODATA } else { double value = 0; for (int h = 0; h < dstHeight; h++) { int pixelOffset = lineOffset; lineOffset += lineStride; warp.warpRect(dst.getX(), dst.getY() + h, dstWidth, 1, warpData); int count = 0; for (int w = 0; w < dstWidth; w++) { float sx = warpData[count++]; float sy = warpData[count++]; int xint = floor(sx); int yint = floor(sy); float xfrac = sx - xint; float yfrac = sy - yint; if (xint < minX || xint >= maxX || yint < minY || yint >= maxY) { /* Fill with a background color. */ if (setBackground) { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b]; } } } else { xint -= leftPad; yint -= topPad; roiWeight = false; for (int j = 0; j < kheight; j++) { for (int i = 0; i < kwidth; i++) { int x = xint + i; int y = yint + j; if (roiBounds.contains(x, y)) { roiWeight |= roiIter.getSample(x, y, 0) > 0; } } } // // ROI check // // if (roiWeight) { for (int b = 0; b < dstBands; b++) { for (int j = 0; j < kheight; j++) { // // NODATA check // // for (int i = 0; i < kwidth; i++) { value = iter.getSampleDouble(xint + i, yint + j, b); // If the value is a NODATA, is substituted with 0 inside the kernel if (noDataRange.contains(value)) { samples[j][i] = NODATA_VALUE; } else { samples[j][i] = value; } } } data[b][pixelOffset + bandOffsets[b]] = (interp.interpolate( samples, xfrac, yfrac)); } } else { for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b]; } } } pixelOffset += pixelStride; } } } iter.done(); } }