/* JAI-Ext - OpenSource Java Advanced Image Extensions Library * http://www.geo-solutions.it/ * Copyright 2014 GeoSolutions * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package it.geosolutions.jaiext.affine; import it.geosolutions.jaiext.interpolators.InterpolationBilinear; import it.geosolutions.jaiext.iterators.RandomIterFactory; import it.geosolutions.jaiext.range.Range; import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import java.awt.image.ColorModel; import java.awt.image.DataBuffer; import java.awt.image.IndexColorModel; import java.awt.image.Raster; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; import java.awt.image.WritableRaster; import java.util.Arrays; import java.util.Map; import javax.media.jai.BorderExtender; import javax.media.jai.ImageLayout; import javax.media.jai.Interpolation; import javax.media.jai.RasterAccessor; import javax.media.jai.RasterFormatTag; import javax.media.jai.iterator.RandomIter; import com.sun.media.jai.util.ImageUtil; public class AffineBilinearOpImage extends AffineOpImage { /** Nearest-Neighbor interpolator */ protected InterpolationBilinear interpB = null; /** Byte lookuptable used if no data are present */ protected byte[][] byteLookupTable; /** ROI extender */ final static BorderExtender roiExtender = BorderExtender .createInstance(BorderExtender.BORDER_ZERO); /** Value indicating if destination No Data must be set if the pixel is outside the source rectangle */ private boolean setDestinationNoData; public AffineBilinearOpImage(RenderedImage source, BorderExtender extender, Map config, ImageLayout layout, AffineTransform transform, Interpolation interp, double[] backgroundValues, boolean setDestinationNoData, boolean useROIAccessor, Range nodata) { super(source, extender, config, layout, transform, interp, backgroundValues); affineOpInitialization(source, interp, layout, backgroundValues, useROIAccessor, setDestinationNoData, nodata); } private void affineOpInitialization(RenderedImage source, Interpolation interp, ImageLayout layout, double[] backgroundValues, boolean useROIAccessor, boolean setDestinationNoData, Range nodata) { SampleModel sm = source.getSampleModel(); // If the source has an IndexColorModel, override the default setting // in OpImage. The dest shall have exactly the same SampleModel and // ColorModel as the source. // Note, in this case, the source should have an integral data type. ColorModel srcColorModel = source.getColorModel(); if (srcColorModel instanceof IndexColorModel && ImageUtil.isBinary(sm)) { sampleModel = source.getSampleModel() .createCompatibleSampleModel(tileWidth, tileHeight); colorModel = srcColorModel; } // Num Bands int numBands = getSampleModel().getNumBands(); // Source image data Type int srcDataType = sm.getDataType(); // If both roiBounds and roiIter are not null, they are used in calculation Range nod = nodata; double[] destNod = null; if (backgroundValues != null && backgroundValues.length > 0) { destNod = backgroundValues; } if (interp instanceof InterpolationBilinear) { interpB = (InterpolationBilinear) interp; this.interp = interpB; interpB.setROIBounds(roiBounds); if (nod == null) { nod = interpB.getNoDataRange(); } if (destNod == null) { destNod = new double[]{interpB.getDestinationNoData()}; } } // Nodata definition if (nod != null) { hasNoData = true; noData = nod; } if (destNod != null) { destinationNoDataDouble = destNod; } else if (this.backgroundValues != null && this.backgroundValues.length > 0) { destinationNoDataDouble = this.backgroundValues; } // Expand the destination nodata values if not defined if(destinationNoDataDouble != null && destinationNoDataDouble.length < numBands){ double[] tmp = new double[numBands]; Arrays.fill(tmp, destinationNoDataDouble[0]); destinationNoDataDouble = tmp; } // ROIAccessor definition if (hasROI) { this.useROIAccessor = useROIAccessor; } // destination No Data set this.setDestinationNoData = setDestinationNoData; this.setBackground = setDestinationNoData; // Create the destination No data arrays destinationNoDataByte = new byte[numBands]; destinationNoDataShort = new short[numBands]; destinationNoDataUShort = new short[numBands]; destinationNoDataInt = new int[numBands]; destinationNoDataFloat = new float[numBands]; // Populate the arrays for (int i = 0; i < numBands; i++) { destinationNoDataByte[i] = (byte) ((int) destinationNoDataDouble[i] & 0xFF); destinationNoDataUShort[i] = (short) (((short) destinationNoDataDouble[i]) & 0xffff); destinationNoDataShort[i] = (short) destinationNoDataDouble[i]; destinationNoDataInt[i] = (int) destinationNoDataDouble[i]; destinationNoDataFloat[i] = (float) destinationNoDataDouble[i]; } // special byte case if (srcDataType == DataBuffer.TYPE_BYTE && hasNoData) { // Creation of a lookuptable containing the values to use for no data byteLookupTable = new byte[numBands][256]; for (int i = 0; i < byteLookupTable[0].length; i++) { byte value = (byte) i; for (int b = 0; b < numBands; b++) { if (noData.contains(value)) { if (setDestinationNoData) { byteLookupTable[b][i] = destinationNoDataByte[b]; } else { byteLookupTable[b][i] = 0; if(i !=0){ byteLookupTable[b][0] = 1; } } } else { byteLookupTable[b][i] = value; } } } } // Definition of the possible cases that can be found // caseA = no ROI nor No Data // caseB = ROI present but No Data not present // caseC = No Data present but ROI not present // Last case not defined = both ROI and No Data are present caseA = !hasROI && !hasNoData; caseB = hasROI && !hasNoData; caseC = !hasROI && hasNoData; } /** Method for evaluating the destination image tile without ROI */ protected void computeRect(Raster[] sources, WritableRaster dest, Rectangle destRect) { RasterFormatTag[] formatTags = getFormatTags(); // Source image Raster source = sources[0]; // Source rectangle Rectangle srcRect = source.getBounds(); // Src upper left pixel coordinates int srcRectX = srcRect.x; int srcRectY = srcRect.y; // // Get data for the source rectangle & the destination rectangle // In the first version source Rectangle is the whole source // image always. RasterAccessor srcAccessor = new RasterAccessor(source, srcRect, formatTags[0], getSourceImage(0).getColorModel()); RasterAccessor dstAccessor = new RasterAccessor(dest, destRect, formatTags[1], getColorModel()); // Roi rasterAccessor initialization RasterAccessor roiAccessor = null; // Roi raster initialization Raster roi = null; RandomIter roiIter = null; // ROI calculation only if the roi raster is present if (hasROI) { if (useROIAccessor) { if(srcROIImage.getBounds().contains(srcRect)){ roi = srcROIImage.getData(srcRect); } else{ roi = srcROIImgExt.getData(srcRect); } roiAccessor = new RasterAccessor(roi, srcRect, RasterAccessor.findCompatibleTags( new RenderedImage[] { srcROIImage }, srcROIImage)[0], srcROIImage.getColorModel()); } else { roiIter = RandomIterFactory.create(srcROIImgExt, roiRect, true, true); } } int dataType = dest.getSampleModel().getDataType(); // If the image is not binary, then for every kind of dataType, the image affine transformation // is performed. switch (dataType) { case DataBuffer.TYPE_BYTE: byteLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor, roiAccessor, roiIter); break; case DataBuffer.TYPE_INT: intLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor, roiAccessor, roiIter); break; case DataBuffer.TYPE_SHORT: shortLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor, roiAccessor, roiIter); break; case DataBuffer.TYPE_USHORT: ushortLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor, roiAccessor, roiIter); break; case DataBuffer.TYPE_FLOAT: floatLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor, roiAccessor, roiIter); break; case DataBuffer.TYPE_DOUBLE: doubleLoop(dataType, srcAccessor, destRect, srcRectX, srcRectY, dstAccessor, roiAccessor, roiIter); break; } // If the RasterAccessor object set up a temporary buffer for the // op to write to, tell the RasterAccessor to write that data // to the raster, that we're done with it. if (dstAccessor.isDataCopy()) { dstAccessor.clampDataArrays(); dstAccessor.copyDataToRaster(); } } private void byteLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX, int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) { final float src_rect_x1 = src.getX(); final float src_rect_y1 = src.getY(); final float src_rect_x2 = src_rect_x1 + src.getWidth(); final float src_rect_y2 = src_rect_y1 + src.getHeight(); double fracx = 0, fracy = 0; int dstPixelOffset; int dstOffset = 0; final Point2D dst_pt = new Point2D.Float(); final Point2D src_pt = new Point2D.Float(); final byte dstDataArrays[][] = dst.getByteDataArrays(); final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); final byte srcDataArrays[][] = src.getByteDataArrays(); final int bandOffsets[] = src.getBandOffsets(); final int srcPixelStride = src.getPixelStride(); final int srcScanlineStride = src.getScanlineStride(); final int dst_num_bands = dst.getNumBands(); final int dst_min_x = destRect.x; final int dst_min_y = destRect.y; final int dst_max_x = destRect.x + destRect.width; final int dst_max_y = destRect.y + destRect.height; // ROI scanline stride final byte[] roiDataArray; final int roiDataLength; final int roiScanlineStride; if (useROIAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; roiScanlineStride = roi.getScanlineStride(); } else { roiDataArray = null; roiDataLength = 0; roiScanlineStride = 0; } if (caseA) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { int posx = (s_ix - srcRectX) * srcPixelStride; int posy = (s_iy - srcRectY) * srcScanlineStride; int posxhigh = posx + srcPixelStride; int posyhigh = posy + srcScanlineStride; int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]] & 0xff; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]] & 0xff; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]] & 0xff; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]] & 0xff; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > 254.5f) { intResult = 255; } else if (result < 0.5f) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (intResult & 0xff); } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else if (caseB) { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]] & 0xff; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]] & 0xff; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]] & 0xff; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]] & 0xff; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > 254.5f) { intResult = 255; } else if (result < 0.5f) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (intResult & 0xff); } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0) & 0xff; final int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; final int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]] & 0xff; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]] & 0xff; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]] & 0xff; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]] & 0xff; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > 254.5f) { intResult = 255; } else if (result < 0.5f) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (intResult & 0xff); } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } else if (caseC) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; int w00 = byteLookupTable[k2][s00&0xFF] == destinationNoDataByte[k2] ? 0 : 1; int w01 = byteLookupTable[k2][s01&0xFF] == destinationNoDataByte[k2] ? 0 : 1; int w10 = byteLookupTable[k2][s10&0xFF] == destinationNoDataByte[k2] ? 0 : 1; int w11 = byteLookupTable[k2][s11&0xFF] == destinationNoDataByte[k2] ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; } } else { double result = computeValue(s00 & 0xff, s01 & 0xff, s10 & 0xff, s11 & 0xff, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > 254.5f) { intResult = 255; } else if (result < 0.5f) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (intResult & 0xff); } } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; final int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; final int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; final int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; w00 = byteLookupTable[k2][s00&0xFF] == destinationNoDataByte[k2] ? 0 : 1; w01 = byteLookupTable[k2][s01&0xFF] == destinationNoDataByte[k2] ? 0 : 1; w10 = byteLookupTable[k2][s10&0xFF] == destinationNoDataByte[k2] ? 0 : 1; w11 = byteLookupTable[k2][s11&0xFF] == destinationNoDataByte[k2] ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; } } else { double result = computeValue(s00 & 0xff, s01 & 0xff, s10 & 0xff, s11 & 0xff, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > 254.5f) { intResult = 255; } else if (result < 0.5f) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (intResult & 0xff); } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0) & 0xff; int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; final int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; final int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; final int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; w00 = byteLookupTable[k2][s00&0xFF] == destinationNoDataByte[k2] ? 0 : 1; w01 = byteLookupTable[k2][s01&0xFF] == destinationNoDataByte[k2] ? 0 : 1; w10 = byteLookupTable[k2][s10&0xFF] == destinationNoDataByte[k2] ? 0 : 1; w11 = byteLookupTable[k2][s11&0xFF] == destinationNoDataByte[k2] ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; } } else { double result = computeValue(s00 & 0xff, s01 & 0xff, s10 & 0xff, s11 & 0xff, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > 254.5f) { intResult = 255; } else if (result < 0.5f) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (byte) (intResult & 0xff); } } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataByte[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } } private void ushortLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX, int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) { final float src_rect_x1 = src.getX(); final float src_rect_y1 = src.getY(); final float src_rect_x2 = src_rect_x1 + src.getWidth(); final float src_rect_y2 = src_rect_y1 + src.getHeight(); double fracx = 0, fracy = 0; int dstPixelOffset; int dstOffset = 0; final Point2D dst_pt = new Point2D.Float(); final Point2D src_pt = new Point2D.Float(); final short dstDataArrays[][] = dst.getShortDataArrays(); final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); final short srcDataArrays[][] = src.getShortDataArrays(); final int bandOffsets[] = src.getBandOffsets(); final int srcPixelStride = src.getPixelStride(); final int srcScanlineStride = src.getScanlineStride(); final int dst_num_bands = dst.getNumBands(); final int dst_min_x = destRect.x; final int dst_min_y = destRect.y; final int dst_max_x = destRect.x + destRect.width; final int dst_max_y = destRect.y + destRect.height; // ROI scanline stride final byte[] roiDataArray; final int roiDataLength; final int roiScanlineStride; if (useROIAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; roiScanlineStride = roi.getScanlineStride(); } else { roiDataArray = null; roiDataLength = 0; roiScanlineStride = 0; } if (caseA) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { int posx = (s_ix - srcRectX) * srcPixelStride; int posy = (s_iy - srcRectY) * srcScanlineStride; int posxhigh = posx + srcPixelStride; int posyhigh = posy + srcScanlineStride; int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]] & 0xffff; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]] & 0xffff; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]] & 0xffff; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]] & 0xffff; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > (float) USHORT_MAX_VALUE) { intResult = USHORT_MAX_VALUE; } else if (result < 0.0) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult & 0xffff); } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else if (caseB) { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]] & 0xffff; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]] & 0xffff; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]] & 0xffff; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]] & 0xffff; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > (float) USHORT_MAX_VALUE) { intResult = USHORT_MAX_VALUE; } else if (result < 0.0) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult & 0xffff); } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0) & 0xff; final int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; final int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]] & 0xffff; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]] & 0xffff; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]] & 0xffff; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]] & 0xffff; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > (float) USHORT_MAX_VALUE) { intResult = USHORT_MAX_VALUE; } else if (result < 0.0) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult & 0xffff); } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } else if (caseC) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array short s00 = (short) (srcDataArrays[k2][posx + posy + bandOffsets[k2]] & 0xffff); short s01 = (short) (srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]] & 0xffff); short s10 = (short) (srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]] & 0xffff); short s11 = (short) (srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]] & 0xffff); int w00 = noData.contains(s00) ? 0 : 1; int w01 = noData.contains(s01) ? 0 : 1; int w10 = noData.contains(s10) ? 0 : 1; int w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > (float) USHORT_MAX_VALUE) { intResult = USHORT_MAX_VALUE; } else if (result < 0.0) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult & 0xffff); } } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final short s00 = (short) (srcDataArrays[k2][posx + posy + bandOffsets[k2]] & 0xffff); final short s01 = (short) (srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]] & 0xffff); final short s10 = (short) (srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]] & 0xffff); final short s11 = (short) (srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]] & 0xffff); w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > (float) USHORT_MAX_VALUE) { intResult = USHORT_MAX_VALUE; } else if (result < 0.0) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult & 0xffff); } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0) & 0xff; int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final short s00 = (short) (srcDataArrays[k2][posx + posy + bandOffsets[k2]] & 0xffff); final short s01 = (short) (srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]] & 0xffff); final short s10 = (short) (srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]] & 0xffff); final short s11 = (short) (srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]] & 0xffff); w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > (float) USHORT_MAX_VALUE) { intResult = USHORT_MAX_VALUE; } else if (result < 0.0) { intResult = 0; } else { intResult = (int) (result + 0.5f); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult & 0xffff); } } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataUShort[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } } private void shortLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX, int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) { final float src_rect_x1 = src.getX(); final float src_rect_y1 = src.getY(); final float src_rect_x2 = src_rect_x1 + src.getWidth(); final float src_rect_y2 = src_rect_y1 + src.getHeight(); double fracx = 0, fracy = 0; int dstPixelOffset; int dstOffset = 0; final Point2D dst_pt = new Point2D.Float(); final Point2D src_pt = new Point2D.Float(); final short dstDataArrays[][] = dst.getShortDataArrays(); final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); final short srcDataArrays[][] = src.getShortDataArrays(); final int bandOffsets[] = src.getBandOffsets(); final int srcPixelStride = src.getPixelStride(); final int srcScanlineStride = src.getScanlineStride(); final int dst_num_bands = dst.getNumBands(); final int dst_min_x = destRect.x; final int dst_min_y = destRect.y; final int dst_max_x = destRect.x + destRect.width; final int dst_max_y = destRect.y + destRect.height; // ROI scanline stride final byte[] roiDataArray; final int roiDataLength; final int roiScanlineStride; if (useROIAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; roiScanlineStride = roi.getScanlineStride(); } else { roiDataArray = null; roiDataLength = 0; roiScanlineStride = 0; } if (caseA) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { int posx = (s_ix - srcRectX) * srcPixelStride; int posy = (s_iy - srcRectY) * srcScanlineStride; int posxhigh = posx + srcPixelStride; int posyhigh = posy + srcScanlineStride; int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > (float) Short.MAX_VALUE) { intResult = Short.MAX_VALUE; } else if (result < (float) Short.MIN_VALUE) { intResult = Short.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult); } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else if (caseB) { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > (float) Short.MAX_VALUE) { intResult = Short.MAX_VALUE; } else if (result < (float) Short.MIN_VALUE) { intResult = Short.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult); } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0) & 0xff; final int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; final int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > (float) Short.MAX_VALUE) { intResult = Short.MAX_VALUE; } else if (result < (float) Short.MIN_VALUE) { intResult = Short.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult); } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } else if (caseC) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array short s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; short s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; short s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; short s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; int w00 = noData.contains(s00) ? 0 : 1; int w01 = noData.contains(s01) ? 0 : 1; int w10 = noData.contains(s10) ? 0 : 1; int w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > (float) Short.MAX_VALUE) { intResult = Short.MAX_VALUE; } else if (result < (float) Short.MIN_VALUE) { intResult = Short.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult); } } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final short s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; final short s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; final short s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; final short s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > (float) Short.MAX_VALUE) { intResult = Short.MAX_VALUE; } else if (result < (float) Short.MIN_VALUE) { intResult = Short.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult); } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0) & 0xff; int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final short s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; final short s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; final short s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; final short s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > (float) Short.MAX_VALUE) { intResult = Short.MAX_VALUE; } else if (result < (float) Short.MIN_VALUE) { intResult = Short.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (short) (intResult); } } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataShort[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } } private void intLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX, int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) { final float src_rect_x1 = src.getX(); final float src_rect_y1 = src.getY(); final float src_rect_x2 = src_rect_x1 + src.getWidth(); final float src_rect_y2 = src_rect_y1 + src.getHeight(); double fracx = 0, fracy = 0; int dstPixelOffset; int dstOffset = 0; final Point2D dst_pt = new Point2D.Float(); final Point2D src_pt = new Point2D.Float(); final int dstDataArrays[][] = dst.getIntDataArrays(); final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); final int srcDataArrays[][] = src.getIntDataArrays(); final int bandOffsets[] = src.getBandOffsets(); final int srcPixelStride = src.getPixelStride(); final int srcScanlineStride = src.getScanlineStride(); final int dst_num_bands = dst.getNumBands(); final int dst_min_x = destRect.x; final int dst_min_y = destRect.y; final int dst_max_x = destRect.x + destRect.width; final int dst_max_y = destRect.y + destRect.height; // ROI scanline stride final byte[] roiDataArray; final int roiDataLength; final int roiScanlineStride; if (useROIAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; roiScanlineStride = roi.getScanlineStride(); } else { roiDataArray = null; roiDataLength = 0; roiScanlineStride = 0; } if (caseA) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { int posx = (s_ix - srcRectX) * srcPixelStride; int posy = (s_iy - srcRectY) * srcScanlineStride; int posxhigh = posx + srcPixelStride; int posyhigh = posy + srcScanlineStride; int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > (float) Integer.MAX_VALUE) { intResult = Integer.MAX_VALUE; } else if (result < (float) Integer.MIN_VALUE) { intResult = Integer.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = intResult; } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else if (caseB) { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > (float) Integer.MAX_VALUE) { intResult = Integer.MAX_VALUE; } else if (result < (float) Integer.MIN_VALUE) { intResult = Integer.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = intResult; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0) & 0xff; final int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; final int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); int intResult = 0; if (result > (float) Integer.MAX_VALUE) { intResult = Integer.MAX_VALUE; } else if (result < (float) Integer.MIN_VALUE) { intResult = Integer.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = intResult; } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } else if (caseC) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; int w00 = noData.contains(s00) ? 0 : 1; int w01 = noData.contains(s01) ? 0 : 1; int w10 = noData.contains(s10) ? 0 : 1; int w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > (float) Integer.MAX_VALUE) { intResult = Integer.MAX_VALUE; } else if (result < (float) Integer.MIN_VALUE) { intResult = Integer.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = intResult; } } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; final int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; final int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; final int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > (float) Integer.MAX_VALUE) { intResult = Integer.MAX_VALUE; } else if (result < (float) Integer.MIN_VALUE) { intResult = Integer.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = intResult; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0) & 0xff; int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final int s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; final int s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; final int s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; final int s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); int intResult = 0; if (result > (float) Integer.MAX_VALUE) { intResult = Integer.MAX_VALUE; } else if (result < (float) Integer.MIN_VALUE) { intResult = Integer.MIN_VALUE; } else if (result > 0) { intResult = (int) (result + 0.5F); } else { intResult = (int) (result - 0.5F); } dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = intResult; } } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataInt[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } } private void floatLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX, int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) { final float src_rect_x1 = src.getX(); final float src_rect_y1 = src.getY(); final float src_rect_x2 = src_rect_x1 + src.getWidth(); final float src_rect_y2 = src_rect_y1 + src.getHeight(); double fracx = 0, fracy = 0; int dstPixelOffset; int dstOffset = 0; final Point2D dst_pt = new Point2D.Float(); final Point2D src_pt = new Point2D.Float(); final float dstDataArrays[][] = dst.getFloatDataArrays(); final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); final float srcDataArrays[][] = src.getFloatDataArrays(); final int bandOffsets[] = src.getBandOffsets(); final int srcPixelStride = src.getPixelStride(); final int srcScanlineStride = src.getScanlineStride(); final int dst_num_bands = dst.getNumBands(); final int dst_min_x = destRect.x; final int dst_min_y = destRect.y; final int dst_max_x = destRect.x + destRect.width; final int dst_max_y = destRect.y + destRect.height; // ROI scanline stride final byte[] roiDataArray; final int roiDataLength; final int roiScanlineStride; if (useROIAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; roiScanlineStride = roi.getScanlineStride(); } else { roiDataArray = null; roiDataLength = 0; roiScanlineStride = 0; } if (caseA) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { int posx = (s_ix - srcRectX) * srcPixelStride; int posy = (s_iy - srcRectY) * srcScanlineStride; int posxhigh = posx + srcPixelStride; int posyhigh = posy + srcScanlineStride; float s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; float s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; float s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; float s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result; } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else if (caseB) { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array float s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; float s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; float s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; float s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0) & 0xff; final int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; final int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array float s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; float s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; float s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; float s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; float s0 = (float) ((s01 - s00) * fracx + s00); float s1 = (float) ((s11 - s10) * fracx + s10); float result = (float) ((s1 - s0) * fracy + s0); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result; } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } else if (caseC) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array float s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; float s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; float s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; float s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; int w00 = 1; int w01 = 1; int w10 = 1; int w11 = 1; w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (float) result; } } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final float s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; final float s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; final float s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; final float s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; w00 = 1; w01 = 1; w10 = 1; w11 = 1; w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (float) (result); } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0) & 0xff; int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final float s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; final float s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; final float s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; final float s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; w00 = 1; w01 = 1; w10 = 1; w11 = 1; w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = (float) (result); } } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataFloat[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } } private void doubleLoop(int dataType, RasterAccessor src, Rectangle destRect, int srcRectX, int srcRectY, RasterAccessor dst, RasterAccessor roi, RandomIter roiIter) { final float src_rect_x1 = src.getX(); final float src_rect_y1 = src.getY(); final float src_rect_x2 = src_rect_x1 + src.getWidth(); final float src_rect_y2 = src_rect_y1 + src.getHeight(); double fracx = 0, fracy = 0; int dstPixelOffset; int dstOffset = 0; final Point2D dst_pt = new Point2D.Float(); final Point2D src_pt = new Point2D.Float(); final double dstDataArrays[][] = dst.getDoubleDataArrays(); final int dstBandOffsets[] = dst.getBandOffsets(); final int dstPixelStride = dst.getPixelStride(); final int dstScanlineStride = dst.getScanlineStride(); final double srcDataArrays[][] = src.getDoubleDataArrays(); final int bandOffsets[] = src.getBandOffsets(); final int srcPixelStride = src.getPixelStride(); final int srcScanlineStride = src.getScanlineStride(); final int dst_num_bands = dst.getNumBands(); final int dst_min_x = destRect.x; final int dst_min_y = destRect.y; final int dst_max_x = destRect.x + destRect.width; final int dst_max_y = destRect.y + destRect.height; // ROI scanline stride final byte[] roiDataArray; final int roiDataLength; final int roiScanlineStride; if (useROIAccessor) { roiDataArray = roi.getByteDataArray(0); roiDataLength = roiDataArray.length; roiScanlineStride = roi.getScanlineStride(); } else { roiDataArray = null; roiDataLength = 0; roiScanlineStride = 0; } if (caseA) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { int posx = (s_ix - srcRectX) * srcPixelStride; int posy = (s_iy - srcRectY) * srcScanlineStride; int posxhigh = posx + srcPixelStride; int posyhigh = posy + srcScanlineStride; double s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; double s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; double s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; double s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; double s0 = ((s01 - s00) * fracx + s00); double s1 = ((s11 - s10) * fracx + s10); double result = ((s1 - s0) * fracy + s0); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result; } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else if (caseB) { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; final int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; final int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; final int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; final int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array double s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; double s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; double s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; double s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; double s0 = ((s01 - s00) * fracx + s00); double s1 = ((s11 - s10) * fracx + s10); double result = ((s1 - s0) * fracy + s0); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { final int w00 = roiIter.getSample(x0, y0, 0) & 0xff; final int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; final int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; final int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array double s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; double s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; double s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; double s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; double s0 = ((s01 - s00) * fracx + s00); double s1 = ((s11 - s10) * fracx + s10); double result = ((s1 - s0) * fracy + s0); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result; } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } else if (caseC) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; for (int x = dst_min_x; x < dst_max_x; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; if ((s_ix >= src_rect_x1) && (s_ix < (src_rect_x2 - 1)) && (s_iy >= src_rect_y1) && (s_iy < (src_rect_y2 - 1))) { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array double s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; double s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; double s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; double s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; int w00 = 1; int w01 = 1; int w10 = 1; int w11 = 1; w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result; } } } else if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { if (useROIAccessor) { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; // If roiAccessor is present, the y position on the roi image is calculated final int posyROI = (s_iy - srcRectY) * roiScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; final int baseIndex = (posx / dst_num_bands) + posyROI; final int w00index = baseIndex; final int w01index = baseIndex + 1; final int w10index = baseIndex + roiScanlineStride; final int w11index = baseIndex + roiScanlineStride + 1; int w00 = w00index < roiDataLength ? roiDataArray[w00index] & 0xff : 0; int w01 = w01index < roiDataLength ? roiDataArray[w01index] & 0xff : 0; int w10 = w10index < roiDataLength ? roiDataArray[w10index] & 0xff : 0; int w11 = w11index < roiDataLength ? roiDataArray[w11index] & 0xff : 0; if (baseIndex > roiDataLength || w00 == 0 || (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0)) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final double s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; final double s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; final double s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; final double s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; w00 = 1; w01 = 1; w10 = 1; w11 = 1; w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } else { for (int y = dst_min_y; y < dst_max_y; y++) { dstPixelOffset = dstOffset; // Backward map the first point in the line // The energy is at the (pt_x + 0.5, pt_y + 0.5) dst_pt.setLocation(dst_min_x + HALF_PIXEL, y + HALF_PIXEL); mapDestPoint(dst_pt, src_pt); // Get the mapped source coordinates float s_x = (float) src_pt.getX(); float s_y = (float) src_pt.getY(); s_x -= 0.5; s_y -= 0.5; // Floor to get the integral coordinate int s_ix = (int) Math.floor(s_x); int s_iy = (int) Math.floor(s_y); fracx = s_x - s_ix * 1.0d; fracy = s_y - s_iy * 1.0d; int ifracx = (int) Math.floor(fracx * GEOM_FRAC_MAX); int ifracy = (int) Math.floor(fracy * GEOM_FRAC_MAX); // Compute clipMinX, clipMinY javax.media.jai.util.Range clipRange = performScanlineClipping(src_rect_x1, src_rect_y1, src_rect_x2, src_rect_y2, s_ix, s_iy, ifracx, ifracy, dst_min_x, dst_max_x, 0, 1, 0, 1); int clipMinX = ((Integer) clipRange.getMinValue()).intValue(); int clipMaxX = ((Integer) clipRange.getMaxValue()).intValue(); // Advance s_ix, s_iy, ifracx, ifracy Point[] startPts = advanceToStartOfScanline(dst_min_x, clipMinX, s_ix, s_iy, ifracx, ifracy); s_ix = startPts[0].x; s_iy = startPts[0].y; if (setDestinationNoData) { for (int x = dst_min_x; x < clipMinX; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; dstPixelOffset += dstPixelStride; } } else // Advance to first pixel dstPixelOffset += (clipMinX - dst_min_x) * dstPixelStride; for (int x = clipMinX; x < clipMaxX; x++) { final int posx = (s_ix - srcRectX) * srcPixelStride; final int posy = (s_iy - srcRectY) * srcScanlineStride; final int posxhigh = posx + srcPixelStride; final int posyhigh = posy + srcScanlineStride; int x0 = src.getX() + posx / srcPixelStride; int y0 = src.getY() + posy / srcScanlineStride; if (roiBounds.contains(x0, y0)) { int w00 = roiIter.getSample(x0, y0, 0) & 0xff; int w01 = roiIter.getSample(x0 + 1, y0, 0) & 0xff; int w10 = roiIter.getSample(x0, y0 + 1, 0) & 0xff; int w11 = roiIter.getSample(x0 + 1, y0 + 1, 0) & 0xff; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; } } } else { for (int k2 = 0; k2 < dst_num_bands; k2++) { // The interpolated value is saved in the destination array final double s00 = srcDataArrays[k2][posx + posy + bandOffsets[k2]]; final double s01 = srcDataArrays[k2][posxhigh + posy + bandOffsets[k2]]; final double s10 = srcDataArrays[k2][posx + posyhigh + bandOffsets[k2]]; final double s11 = srcDataArrays[k2][posxhigh + posyhigh + bandOffsets[k2]]; w00 = 1; w01 = 1; w10 = 1; w11 = 1; w00 = noData.contains(s00) ? 0 : 1; w01 = noData.contains(s01) ? 0 : 1; w10 = noData.contains(s10) ? 0 : 1; w11 = noData.contains(s11) ? 0 : 1; if (w00 == 0 && w01 == 0 && w10 == 0 && w11 == 0) { if (setDestinationNoData) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; } } else { double result = computeValue(s00, s01, s10, s11, w00, w01, w10, w11, fracx, fracy); dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = result; } } } } else { if (setDestinationNoData) { for (int k2 = 0; k2 < dst_num_bands; k2++) { dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; } } } // walk if (fracx < fracdx1) { s_ix += incx; fracx += fracdx; } else { s_ix += incx1; fracx -= fracdx1; } if (fracy < fracdy1) { s_iy += incy; fracy += fracdy; } else { s_iy += incy1; fracy -= fracdy1; } // Go to next pixel dstPixelOffset += dstPixelStride; } if (setDestinationNoData && clipMinX <= clipMaxX) { for (int x = clipMaxX; x < dst_max_x; x++) { for (int k2 = 0; k2 < dst_num_bands; k2++) dstDataArrays[k2][dstPixelOffset + dstBandOffsets[k2]] = destinationNoDataDouble[k2]; dstPixelOffset += dstPixelStride; } } // Go to the next line in the destination rectangle dstOffset += dstScanlineStride; } } } } /* Private method for calculate bilinear interpolation for float/double dataType */ private double computeValue(double s00, double s01, double s10, double s11, double w00, double w01, double w10, double w11, double xfrac, double yfrac) { double s0 = 0; double s1 = 0; double s = 0; // Complementary values of the fractional part double xfracCompl = 1 - xfrac; double yfracCompl = 1 - yfrac; if (w00 == 0 || w01 == 0 || w10 == 0 || w11 == 0) { if (w00 == 0 && w01 == 0) { s0 = 0; } else if (w00 == 0) { // w01 = 1 s0 = s01 * xfrac; } else if (w01 == 0) {// w00 = 1 s0 = s00 * xfracCompl;// s00; } else {// w00 = 1 & W01 = 1 s0 = (s01 - s00) * xfrac + s00; } // lower value if (w10 == 0 && w11 == 0) { s1 = 0; } else if (w10 == 0) { // w11 = 1 s1 = s11 * xfrac; } else if (w11 == 0) { // w10 = 1 s1 = s10 * xfracCompl;// - (s10 * xfrac); //s10; } else { s1 = (s11 - s10) * xfrac + s10; } if (w00 == 0 && w01 == 0) { s = s1 * yfrac; } else { if (w10 == 0 && w11 == 0) { s = s0 * yfracCompl; } else { s = (s1 - s0) * yfrac + s0; } } } else { // Perform the bilinear interpolation because all the weight are not 0. s0 = (s01 - s00) * xfrac + s00; s1 = (s11 - s10) * xfrac + s10; s = (s1 - s0) * yfrac + s0; } return s; } }