/* 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; /** * An <code>OpImage</code> implementing the general "Warp" operation as described in <code>javax.media.jai.operator.WarpDescriptor</code>. It supports * the bilinear interpolation. * * <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 WarpBilinearOpImage extends WarpOpImage { /** Color table representing source's IndexColorModel. */ private byte[][] ctable = null; /** LookupTable used for a faster NoData check */ private boolean[] booleanLookupTable; /** * Constructs a WarpBilinearOpImage. * * @param source The source image. * @param extender A BorderExtender, or null. * @param config RenderingHints used in calculations. * @param layout The destination image layout. * @param warp An object defining the warp algorithm. * @param interp An object describing the interpolation method. * @param roi input ROI object used. * @param noData NoData Range object used for checking if NoData are present. */ public WarpBilinearOpImage(final RenderedImage source, final BorderExtender extender, final Map<?, ?> config, final ImageLayout layout, final Warp warp, final Interpolation interp, final ROI sourceROI, Range noData, double[] bkg) { super(source, layout, config, false, extender, interp, warp, bkg, 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. */ final ColorModel srcColorModel = source.getColorModel(); if (srcColorModel instanceof IndexColorModel) { final 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 (srcDataType == DataBuffer.TYPE_BYTE && hasNoData) { booleanLookupTable = new boolean[256]; for (int i = 0; i < booleanLookupTable.length; i++) { byte value = (byte) i; booleanLookupTable[i] = noDataRange.contains(value); } } } protected void computeRectByte(final PlanarImage src, final RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Random iterator initialization. If an extender is used, then an extended image is taken. RandomIter iterSource = getRandomIterator(src, extender); final int minX = src.getMinX(); final int maxX = src.getMaxX() - (extended ? 0 : 1); // Right padding final int minY = src.getMinY(); final int maxY = src.getMaxY() - (extended ? 0 : 1); // 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; 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (byte)backgroundValues[b]; } } } else { // // NO ROI // for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b) & 0xFF; int s01 = iterSource.getSample(xint + 1, yint, b) & 0xFF; int s10 = iterSource.getSample(xint, yint + 1, b) & 0xFF; int s11 = iterSource.getSample(xint + 1, yint + 1, b) & 0xFF; float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = (byte) s; } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (byte)backgroundValues[b]; } } } else { // // ROI // // checks with roi final boolean w00 = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01 = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10 = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11 = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00 && w01 && w10 && w11) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b) & 0xFF; int s01 = iterSource.getSample(xint + 1, yint, b) & 0xFF; int s10 = iterSource.getSample(xint, yint + 1, b) & 0xFF; int s11 = iterSource.getSample(xint + 1, yint + 1, b) & 0xFF; float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = (byte) s; } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (byte)backgroundValues[b]; } } } else { // // NODATA // // checks with nodata for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b) & 0xFF; int s01 = iterSource.getSample(xint + 1, yint, b) & 0xFF; int s10 = iterSource.getSample(xint, yint + 1, b) & 0xFF; int s11 = iterSource.getSample(xint + 1, yint + 1, b) & 0xFF; final boolean w00 = booleanLookupTable[s00]; final boolean w01 = booleanLookupTable[s01]; final boolean w10 = booleanLookupTable[s10]; final boolean w11 = booleanLookupTable[s11]; if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (byte)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (byte) ((int) computePoint( s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11) & 0xFF); } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (byte)backgroundValues[b]; } } } else { // // ROI // // checks with roi final boolean w00Roi = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01Roi = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10Roi = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11Roi = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00Roi && w01Roi && w10Roi && w11Roi) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { // // NODATA // // checks with nodata int s00 = iterSource.getSample(xint, yint, b) & 0xFF; int s01 = iterSource.getSample(xint + 1, yint, b) & 0xFF; int s10 = iterSource.getSample(xint, yint + 1, b) & 0xFF; int s11 = iterSource.getSample(xint + 1, yint + 1, b) & 0xFF; final boolean w00 = booleanLookupTable[s00]; final boolean w01 = booleanLookupTable[s01]; final boolean w10 = booleanLookupTable[s10]; final boolean w11 = booleanLookupTable[s11]; if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (byte)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (byte) ((int) computePoint( s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11) & 0xFF); } } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP } } 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (byte)backgroundValues[b]; } } } else { // // NO ROI // for (int b = 0; b < dstBands; b++) { final byte[] t = ctable[b]; int s00 = t[iterSource.getSample(xint, yint, 0) & 0xFF] & 0xFF; int s01 = t[iterSource.getSample(xint + 1, yint, 0) & 0xFF] & 0xFF; int s10 = t[iterSource.getSample(xint, yint + 1, 0) & 0xFF] & 0xFF; int s11 = t[iterSource.getSample(xint + 1, yint + 1, 0) & 0xFF] & 0xFF; float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = (byte) s; } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (byte)backgroundValues[b]; } } } else { // // ROI // // checks with roi final boolean w00 = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01 = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10 = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11 = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00 && w01 && w10 && w11) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { final byte[] t = ctable[b]; int s00 = t[iterSource.getSample(xint, yint, 0) & 0xFF] & 0xFF; int s01 = t[iterSource.getSample(xint + 1, yint, 0) & 0xFF] & 0xFF; int s10 = t[iterSource.getSample(xint, yint + 1, 0) & 0xFF] & 0xFF; int s11 = t[iterSource.getSample(xint + 1, yint + 1, 0) & 0xFF] & 0xFF; float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = (byte) s; } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (byte)backgroundValues[b]; } } } else { // // NODATA // // checks with nodata for (int b = 0; b < dstBands; b++) { final byte[] t = ctable[b]; int s00 = t[iterSource.getSample(xint, yint, 0) & 0xFF] & 0xFF; int s01 = t[iterSource.getSample(xint + 1, yint, 0) & 0xFF] & 0xFF; int s10 = t[iterSource.getSample(xint, yint + 1, 0) & 0xFF] & 0xFF; int s11 = t[iterSource.getSample(xint + 1, yint + 1, 0) & 0xFF] & 0xFF; final boolean w00 = booleanLookupTable[s00]; final boolean w01 = booleanLookupTable[s01]; final boolean w10 = booleanLookupTable[s10]; final boolean w11 = booleanLookupTable[s11]; if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (byte)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (byte) ((int) computePoint( s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11) & 0xFF); } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (byte)backgroundValues[b]; } } } else { // // ROI // // checks with roi final boolean w00Roi = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01Roi = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10Roi = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11Roi = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00Roi && w01Roi && w10Roi && w11Roi) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (byte)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { // // NODATA // // checks with nodata final byte[] t = ctable[b]; int s00 = t[iterSource.getSample(xint, yint, 0) & 0xFF] & 0xFF; int s01 = t[iterSource.getSample(xint + 1, yint, 0) & 0xFF] & 0xFF; int s10 = t[iterSource.getSample(xint, yint + 1, 0) & 0xFF] & 0xFF; int s11 = t[iterSource.getSample(xint + 1, yint + 1, 0) & 0xFF] & 0xFF; final boolean w00 = booleanLookupTable[s00]; final boolean w01 = booleanLookupTable[s01]; final boolean w10 = booleanLookupTable[s10]; final boolean w11 = booleanLookupTable[s11]; if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (byte)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (byte) ((int) computePoint( s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11) & 0xFF); } } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP } } iterSource.done(); } protected void computeRectUShort(final PlanarImage src, final RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Random iterator initialization. If an extender is used, then an extended image is taken. RandomIter iterSource = getRandomIterator(src, extender); final int minX = src.getMinX(); final int maxX = src.getMaxX() - (extended ? 0 : 1); // Right padding final int minY = src.getMinY(); final int maxY = src.getMaxY() - (extended ? 0 : 1); // 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 short[][] data = dst.getShortDataArrays(); final float[] warpData = new float[2 * dstWidth]; 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (short)backgroundValues[b]; } } } else { // // NO ROI // for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b) & 0xFFFF; int s01 = iterSource.getSample(xint + 1, yint, b) & 0xFFFF; int s10 = iterSource.getSample(xint, yint + 1, b) & 0xFFFF; int s11 = iterSource.getSample(xint + 1, yint + 1, b) & 0xFFFF; float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = (short) s; } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (short)backgroundValues[b]; } } } else { // // ROI // // checks with roi final boolean w00 = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01 = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10 = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11 = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00 && w01 && w10 && w11) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b) & 0xFFFF; int s01 = iterSource.getSample(xint + 1, yint, b) & 0xFFFF; int s10 = iterSource.getSample(xint, yint + 1, b) & 0xFFFF; int s11 = iterSource.getSample(xint + 1, yint + 1, b) & 0xFFFF; float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = (short) s; } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (short)backgroundValues[b]; } } } else { // // NODATA // // checks with nodata for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b) & 0xFFFF; int s01 = iterSource.getSample(xint + 1, yint, b) & 0xFFFF; int s10 = iterSource.getSample(xint, yint + 1, b) & 0xFFFF; int s11 = iterSource.getSample(xint + 1, yint + 1, b) & 0xFFFF; final boolean w00 = noDataRange.contains((short) s00); final boolean w01 = noDataRange.contains((short) s01); final boolean w10 = noDataRange.contains((short) s10); final boolean w11 = noDataRange.contains((short) s11); if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (short)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (short) ((int) computePoint( s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11) & 0xFFFF); } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (short)backgroundValues[b]; } } } else { // // ROI // // checks with roi final boolean w00Roi = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01Roi = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10Roi = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11Roi = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00Roi && w01Roi && w10Roi && w11Roi) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { // // NODATA // // checks with nodata int s00 = iterSource.getSample(xint, yint, b) & 0xFFFF; int s01 = iterSource.getSample(xint + 1, yint, b) & 0xFFFF; int s10 = iterSource.getSample(xint, yint + 1, b) & 0xFFFF; int s11 = iterSource.getSample(xint + 1, yint + 1, b) & 0xFFFF; final boolean w00 = noDataRange.contains((short) s00); final boolean w01 = noDataRange.contains((short) s01); final boolean w10 = noDataRange.contains((short) s10); final boolean w11 = noDataRange.contains((short) s11); if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (short)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (short) ((int) computePoint( s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11) & 0xFFFF); } } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP } iterSource.done(); } protected void computeRectShort(final PlanarImage src, final RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Random iterator initialization. If an extender is used, then an extended image is taken. RandomIter iterSource = getRandomIterator(src, extender); final int minX = src.getMinX(); final int maxX = src.getMaxX() - (extended ? 0 : 1); // Right padding final int minY = src.getMinY(); final int maxY = src.getMaxY() - (extended ? 0 : 1); // 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 short[][] data = dst.getShortDataArrays(); final float[] warpData = new float[2 * dstWidth]; 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (short)backgroundValues[b]; } } } else { // // NO ROI // for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b); int s01 = iterSource.getSample(xint + 1, yint, b); int s10 = iterSource.getSample(xint, yint + 1, b); int s11 = iterSource.getSample(xint + 1, yint + 1, b); float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = (short) s; } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (short)backgroundValues[b]; } } } else { // // ROI // // checks with roi final boolean w00 = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01 = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10 = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11 = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00 && w01 && w10 && w11) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b); int s01 = iterSource.getSample(xint + 1, yint, b); int s10 = iterSource.getSample(xint, yint + 1, b); int s11 = iterSource.getSample(xint + 1, yint + 1, b); float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = (short) s; } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (short)backgroundValues[b]; } } } else { // // NODATA // // checks with nodata for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b); int s01 = iterSource.getSample(xint + 1, yint, b); int s10 = iterSource.getSample(xint, yint + 1, b); int s11 = iterSource.getSample(xint + 1, yint + 1, b); final boolean w00 = noDataRange.contains((short) s00); final boolean w01 = noDataRange.contains((short) s01); final boolean w10 = noDataRange.contains((short) s10); final boolean w11 = noDataRange.contains((short) s11); if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (short)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (short) (computePoint(s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11)); } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (short)backgroundValues[b]; } } } else { // // ROI // // checks with roi final boolean w00Roi = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01Roi = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10Roi = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11Roi = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00Roi && w01Roi && w10Roi && w11Roi) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (short)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { // // NODATA // // checks with nodata int s00 = iterSource.getSample(xint, yint, b); int s01 = iterSource.getSample(xint + 1, yint, b); int s10 = iterSource.getSample(xint, yint + 1, b); int s11 = iterSource.getSample(xint + 1, yint + 1, b); final boolean w00 = noDataRange.contains((short) s00); final boolean w01 = noDataRange.contains((short) s01); final boolean w10 = noDataRange.contains((short) s10); final boolean w11 = noDataRange.contains((short) s11); if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (short)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (short) (computePoint( s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11)); } } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP } iterSource.done(); } protected void computeRectInt(final PlanarImage src, final RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Random iterator initialization. If an extender is used, then an extended image is taken. RandomIter iterSource = getRandomIterator(src, extender); final int minX = src.getMinX(); final int maxX = src.getMaxX() - (extended ? 0 : 1); // Right padding final int minY = src.getMinY(); final int maxY = src.getMaxY() - (extended ? 0 : 1); // 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 int[][] data = dst.getIntDataArrays(); final float[] warpData = new float[2 * dstWidth]; 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (int)backgroundValues[b]; } } } else { // // NO ROI // for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b); int s01 = iterSource.getSample(xint + 1, yint, b); int s10 = iterSource.getSample(xint, yint + 1, b); int s11 = iterSource.getSample(xint + 1, yint + 1, b); float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = (int) s; } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (int)backgroundValues[b]; } } } else { // // ROI // // checks with roi final boolean w00 = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01 = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10 = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11 = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00 && w01 && w10 && w11) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (int)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b); int s01 = iterSource.getSample(xint + 1, yint, b); int s10 = iterSource.getSample(xint, yint + 1, b); int s11 = iterSource.getSample(xint + 1, yint + 1, b); float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = (int) s; } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (int)backgroundValues[b]; } } } else { // // NODATA // // checks with nodata for (int b = 0; b < dstBands; b++) { int s00 = iterSource.getSample(xint, yint, b); int s01 = iterSource.getSample(xint + 1, yint, b); int s10 = iterSource.getSample(xint, yint + 1, b); int s11 = iterSource.getSample(xint + 1, yint + 1, b); final boolean w00 = noDataRange.contains(s00); final boolean w01 = noDataRange.contains(s01); final boolean w10 = noDataRange.contains(s10); final boolean w11 = noDataRange.contains(s11); if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (int)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = ((int) computePoint(s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11)); } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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]] = (int)backgroundValues[b]; } } } else { // // ROI // // checks with roi final boolean w00Roi = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01Roi = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10Roi = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11Roi = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00Roi && w01Roi && w10Roi && w11Roi) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (int)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { // // NODATA // // checks with nodata int s00 = iterSource.getSample(xint, yint, b); int s01 = iterSource.getSample(xint + 1, yint, b); int s10 = iterSource.getSample(xint, yint + 1, b); int s11 = iterSource.getSample(xint + 1, yint + 1, b); final boolean w00 = noDataRange.contains(s00); final boolean w01 = noDataRange.contains(s01); final boolean w10 = noDataRange.contains(s10); final boolean w11 = noDataRange.contains(s11); if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (int)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = ((int) computePoint( s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11)); } } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP } iterSource.done(); } protected void computeRectFloat(final PlanarImage src, final RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Random iterator initialization. If an extender is used, then an extended image is taken. RandomIter iterSource = getRandomIterator(src, extender); final int minX = src.getMinX(); final int maxX = src.getMaxX() - (extended ? 0 : 1); // Right padding final int minY = src.getMinY(); final int maxY = src.getMaxY() - (extended ? 0 : 1); // 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 float[][] data = dst.getFloatDataArrays(); final float[] warpData = new float[2 * dstWidth]; 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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 { // // NO ROI // for (int b = 0; b < dstBands; b++) { float s00 = iterSource.getSampleFloat(xint, yint, b); float s01 = iterSource.getSampleFloat(xint + 1, yint, b); float s10 = iterSource.getSampleFloat(xint, yint + 1, b); float s11 = iterSource.getSampleFloat(xint + 1, yint + 1, b); float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = s; } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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 { // // ROI // // checks with roi final boolean w00 = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01 = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10 = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11 = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00 && w01 && w10 && w11) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (float)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { float s00 = iterSource.getSampleFloat(xint, yint, b); float s01 = iterSource.getSampleFloat(xint + 1, yint, b); float s10 = iterSource.getSampleFloat(xint, yint + 1, b); float s11 = iterSource.getSampleFloat(xint + 1, yint + 1, b); float s0 = (s01 - s00) * xfrac + s00; float s1 = (s11 - s10) * xfrac + s10; float s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = s; } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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 { // // NODATA // // checks with nodata for (int b = 0; b < dstBands; b++) { float s00 = iterSource.getSampleFloat(xint, yint, b); float s01 = iterSource.getSampleFloat(xint + 1, yint, b); float s10 = iterSource.getSampleFloat(xint, yint + 1, b); float s11 = iterSource.getSampleFloat(xint + 1, yint + 1, b); final boolean w00 = noDataRange.contains(s00); final boolean w01 = noDataRange.contains(s01); final boolean w10 = noDataRange.contains(s10); final boolean w11 = noDataRange.contains(s11); if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (float)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (float) (computePoint(s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11)); } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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 { // // ROI // // checks with roi final boolean w00Roi = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01Roi = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10Roi = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11Roi = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00Roi && w01Roi && w10Roi && w11Roi) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = (float)backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { // // NODATA // // checks with nodata float s00 = iterSource.getSampleFloat(xint, yint, b); float s01 = iterSource.getSampleFloat(xint + 1, yint, b); float s10 = iterSource.getSampleFloat(xint, yint + 1, b); float s11 = iterSource.getSampleFloat(xint + 1, yint + 1, b); final boolean w00 = noDataRange.contains(s00); final boolean w01 = noDataRange.contains(s01); final boolean w10 = noDataRange.contains(s10); final boolean w11 = noDataRange.contains(s11); if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = (float)backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (float) (computePoint( s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11)); } } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP } iterSource.done(); } protected void computeRectDouble(final PlanarImage src, final RasterAccessor dst, final RandomIter roiIter, boolean roiContainsTile) { // Random iterator initialization. If an extender is used, then an extended image is taken. RandomIter iterSource = getRandomIterator(src, extender); final int minX = src.getMinX(); final int maxX = src.getMaxX() - (extended ? 0 : 1); // Right padding final int minY = src.getMinY(); final int maxY = src.getMaxY() - (extended ? 0 : 1); // 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 double[][] data = dst.getDoubleDataArrays(); final float[] warpData = new float[2 * dstWidth]; 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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 { // // NO ROI // for (int b = 0; b < dstBands; b++) { double s00 = iterSource.getSampleDouble(xint, yint, b); double s01 = iterSource.getSampleDouble(xint + 1, yint, b); double s10 = iterSource.getSampleDouble(xint, yint + 1, b); double s11 = iterSource.getSampleDouble(xint + 1, yint + 1, b); double s0 = (s01 - s00) * xfrac + s00; double s1 = (s11 - s10) * xfrac + s10; double s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = s; } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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 { // // ROI // // checks with roi final boolean w00 = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01 = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10 = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11 = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00 && w01 && w10 && w11) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { double s00 = iterSource.getSampleDouble(xint, yint, b); double s01 = iterSource.getSampleDouble(xint + 1, yint, b); double s10 = iterSource.getSampleDouble(xint, yint + 1, b); double s11 = iterSource.getSampleDouble(xint + 1, yint + 1, b); double s0 = (s01 - s00) * xfrac + s00; double s1 = (s11 - s10) * xfrac + s10; double s = (s1 - s0) * yfrac + s0; data[b][pixelOffset + bandOffsets[b]] = s; } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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 { // // NODATA // // checks with nodata for (int b = 0; b < dstBands; b++) { double s00 = iterSource.getSampleDouble(xint, yint, b); double s01 = iterSource.getSampleDouble(xint + 1, yint, b); double s10 = iterSource.getSampleDouble(xint, yint + 1, b); double s11 = iterSource.getSampleDouble(xint + 1, yint + 1, b); final boolean w00 = noDataRange.contains(s00); final boolean w01 = noDataRange.contains(s01); final boolean w10 = noDataRange.contains(s10); final boolean w11 = noDataRange.contains(s11); if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (float) (computePoint(s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11)); } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP // 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++) { final float sx = warpData[count++]; final float sy = warpData[count++]; final int xint = floor(sx); final int yint = floor(sy); final float xfrac = sx - xint; final 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 { // // ROI // // checks with roi final boolean w00Roi = !(roiBounds.contains(xint, yint) && roiIter.getSample(xint, yint, 0) > 0); final boolean w01Roi = !(roiBounds.contains(xint + 1, yint) && roiIter.getSample(xint + 1, yint, 0) > 0); final boolean w10Roi = !(roiBounds.contains(xint, yint + 1) && roiIter.getSample(xint, yint + 1, 0) > 0); final boolean w11Roi = !(roiBounds.contains(xint + 1, yint + 1) && roiIter.getSample(xint + 1, yint + 1, 0) > 0); if (w00Roi && w01Roi && w10Roi && w11Roi) { // SG should not happen for (int b = 0; b < dstBands; b++) { data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b]; } } else { for (int b = 0; b < dstBands; b++) { // // NODATA // // checks with nodata double s00 = iterSource.getSampleDouble(xint, yint, b); double s01 = iterSource.getSampleDouble(xint + 1, yint, b); double s10 = iterSource.getSampleDouble(xint, yint + 1, b); double s11 = iterSource.getSampleDouble(xint + 1, yint + 1, b); final boolean w00 = noDataRange.contains(s00); final boolean w01 = noDataRange.contains(s01); final boolean w10 = noDataRange.contains(s10); final boolean w11 = noDataRange.contains(s11); if (w00 && w01 && w10 && w11) { data[b][pixelOffset + bandOffsets[b]] = backgroundValues[b]; } else { data[b][pixelOffset + bandOffsets[b]] = (float) (computePoint( s00, s01, s10, s11, xfrac, yfrac, w00, w01, w10, w11)); } } } } // next desination pixel pixelOffset += pixelStride; } // COLS LOOP } // ROWS LOOP } iterSource.done(); } /** * Computes the bilinear interpolation when No Data are present * * @param s00 upper-left pixel * @param s01 upper-right pixel * @param s10 lower-left pixel * @param s11 lower-right pixel * @param w00 upper-left pixel nodata flag * @param w01 upper-right pixel nodata flag * @param w10 lower-left pixel nodata flag * @param w11 lower-right pixel nodata flag * @param dataType * @return bilinear interpolation */ private double computePoint(double s00, double s01, double s10, double s11, double xfrac, double yfrac, boolean w00, boolean w01, boolean w10, boolean w11) { // Initialization double s0 = 0; double s1 = 0; double s = 0; // Complementary values of the fractional part double xfracCompl = 1 - xfrac; double yfracCompl = 1 - yfrac; if (!w00 && !w01 && !w10 && !w11) { // Perform the bilinear interpolation because all the weight are not 0. s0 = (s01 - s00) * xfrac + s00; s1 = (s11 - s10) * xfrac + s10; s = (s1 - s0) * yfrac + s0; } else { // upper value if (w00 && w01) { s0 = 0; } else if (w00) { // w01 = false s0 = s01 * xfrac; } else if (w01) {// w00 = false s0 = s00 * xfracCompl;// s00; } else {// w00 = false & W01 = false s0 = (s01 - s00) * xfrac + s00; } // lower value if (w10 && w11) { s1 = 0; } else if (w10) { // w11 = false s1 = s11 * xfrac; } else if (w11) { // w10 = false s1 = s10 * xfracCompl;// - (s10 * xfrac); //s10; } else { s1 = (s11 - s10) * xfrac + s10; } if (w00 && w01) { s = s1 * yfrac; } else { if (w10 && w11) { s = s0 * yfracCompl; } else { s = (s1 - s0) * yfrac + s0; } } } return s; } }