diff --git a/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/DoubleDataInterpolator.java b/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/DoubleDataInterpolator.java index 2a38083c308..791bcc2e966 100644 --- a/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/DoubleDataInterpolator.java +++ b/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/DoubleDataInterpolator.java @@ -3,9 +3,7 @@ import org.esa.snap.core.datamodel.RasterDataNode; import javax.media.jai.RasterAccessor; -import javax.media.jai.RasterFormatTag; import java.awt.Rectangle; -import java.awt.image.Raster; /** * @author Tonio Fincke @@ -20,11 +18,11 @@ public void init(RasterDataNode rasterDataNode, RasterAccessor srcAccessor, Rast this.accessor = DataAccessorFactory.createDoubleDataAccessor(srcAccessor, dstAccessor, noDataValue); } - protected double getSrcData(int index) { + double getSrcData(int index) { return accessor.getSrcData(index); } - protected void setDstData(int index, double value) { + void setDstData(int index, double value) { accessor.setDstData(index, value); } @@ -50,8 +48,7 @@ int getDstOffset() { public void dispose(){ - }; - + } static class NearestNeighbour extends DoubleDataInterpolator { @@ -62,11 +59,11 @@ public void interpolate(Rectangle destRect, Rectangle srcRect, double scaleX, do double subPixelOffsetY = offsetY - (int) offsetY; double subPixelOffsetX = offsetX - (int) offsetX; for (int dstY = 0; dstY < destRect.getHeight(); dstY++) { - int srcY = (int) (subPixelOffsetY + scaleY * dstY); + int srcY = (int) Math.round(subPixelOffsetY + scaleY * dstY); int srcIndexY = getSrcOffset() + srcY * getSrcScalineStride(); boolean yValid = srcY < srcRect.getHeight(); for (int dstX = 0; dstX < destRect.getWidth(); dstX++) { - int srcX = (int) (subPixelOffsetX + scaleX * dstX); + int srcX = (int) Math.round(subPixelOffsetX + scaleX * dstX); if (yValid && srcX < srcRect.getWidth()) { setDstData(dstIndexY + dstX, getSrcData(srcIndexY + srcX)); } else { @@ -90,13 +87,11 @@ public void interpolate(Rectangle destRect, Rectangle srcRect, double scaleX, do double subPixelOffsetX = offsetX - (int) offsetX; for (int dstY = 0; dstY < destRect.getHeight(); dstY++) { double srcYF = subPixelOffsetY + (scaleY * (dstY + 0.5)) - 0.5; -// double srcYF = subPixelOffsetY + (scaleY * (dstY)); int srcY = (int) srcYF; int srcIndexY = getSrcOffset() + srcY * getSrcScalineStride(); double wy = srcYF - srcY; for (int dstX = 0; dstX < destRect.getWidth(); dstX++) { double srcXF = subPixelOffsetX + (scaleX * (dstX + 0.5)) - 0.5; -// double srcXF = subPixelOffsetX + (scaleX * (dstX)); int srcX = (int) srcXF; double wx = srcXF - srcX; boolean withinSrcH = srcY + 1 < srcH; diff --git a/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/InterpolatorFactory.java b/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/InterpolatorFactory.java index db9cc021062..dd3412d983a 100644 --- a/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/InterpolatorFactory.java +++ b/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/InterpolatorFactory.java @@ -23,6 +23,8 @@ public static Interpolator createInterpolator(InterpolationType type, int dataTy return new LongDataInterpolator.NearestNeighbour(); case Bilinear: return new LongDataInterpolator.Bilinear(); + case Cubic_Convolution: + return new LongDataInterpolator.CubicConvolution(); } } throw new IllegalArgumentException("Interpolation method not supported"); diff --git a/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/LongDataInterpolator.java b/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/LongDataInterpolator.java index 632dacd442c..efba4c2e4d4 100644 --- a/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/LongDataInterpolator.java +++ b/snap-gpf/src/main/java/org/esa/snap/core/gpf/common/resample/LongDataInterpolator.java @@ -18,11 +18,11 @@ public void init(RasterDataNode rasterDataNode, RasterAccessor srcAccessor, Rast this.accessor = DataAccessorFactory.createLongDataAccessor(srcAccessor, dstAccessor, noDataValue); } - protected long getSrcData(int index) { + long getSrcData(int index) { return accessor.getSrcData(index); } - protected void setDstData(int index, long value) { + void setDstData(int index, long value) { accessor.setDstData(index, value); } @@ -44,7 +44,7 @@ int getDstScalineStride() { public void dispose(){ - }; + } static class NearestNeighbour extends LongDataInterpolator { @@ -55,11 +55,11 @@ public void interpolate(Rectangle destRect, Rectangle srcRect, double scaleX, do double subPixelOffsetY = offsetY - (int) offsetY; double subPixelOffsetX = offsetX - (int) offsetX; for (int dstY = 0; dstY < destRect.getHeight(); dstY++) { - int srcY = (int) (subPixelOffsetY + scaleY * dstY); + int srcY = (int) Math.round(subPixelOffsetY + (scaleY * (dstY + 0.5)) - 0.5); int srcIndexY = getSrcOffset() + srcY * getSrcScalineStride(); boolean yValid = srcY < srcRect.getHeight(); for (int dstX = 0; dstX < destRect.getWidth(); dstX++) { - int srcX = (int) (subPixelOffsetX + scaleX * dstX); + int srcX = (int) Math.round(subPixelOffsetX + (scaleX * (dstX + 0.5)) - 0.5); if (yValid && srcX < srcRect.getWidth()) { setDstData(dstIndexY + dstX, getSrcData(srcIndexY + srcX)); } else { @@ -82,13 +82,11 @@ public void interpolate(Rectangle destRect, Rectangle srcRect, double scaleX, do double subPixelOffsetX = offsetX - (int) offsetX; for (int dstY = 0; dstY < destRect.getHeight(); dstY++) { double srcYF = subPixelOffsetY + (scaleY * (dstY + 0.5)) - 0.5; -// double srcYF = subPixelOffsetY + (scaleY * (dstY)); int srcY = (int) srcYF; double wy = srcYF - srcY; int srcIndexY = getSrcOffset() + srcY * getSrcScalineStride(); for (int dstX = 0; dstX < destRect.getWidth(); dstX++) { double srcXF = subPixelOffsetX + (scaleX * (dstX + 0.5)) - 0.5; -// double srcXF = subPixelOffsetX + (scaleX * (dstX)); int srcX = (int) srcXF; double wx = srcXF - srcX; boolean withinSrcH = srcY + 1 < srcH; @@ -96,7 +94,7 @@ public void interpolate(Rectangle destRect, Rectangle srcRect, double scaleX, do double v00 = getSrcData(srcIndexY + srcX); final int dstIndex = dstIndexY + dstX; if (!withinSrcW && !withinSrcH) { - setDstData(dstIndex, (long) v00); + setDstData(dstIndex, Math.round(v00)); continue; } double v01 = withinSrcW ? getSrcData(srcIndexY + srcX + 1) : getNoDataValue(); @@ -117,36 +115,36 @@ public void interpolate(Rectangle destRect, Rectangle srcRect, double scaleX, do double v0 = v00 + wx * (v01 - v00); double v1 = v10 + wx * (v11 - v10); double v = v0 + wy * (v1 - v0); - setDstData(dstIndex, (long) v); + setDstData(dstIndex, Math.round(v)); } else if (validityCounter == 1) { if (v00Valid) { - setDstData(dstIndex, (long) v00); + setDstData(dstIndex, Math.round(v00)); } else if (v01Valid) { - setDstData(dstIndex, (long) v01); + setDstData(dstIndex, Math.round(v01)); } else if (v10Valid) { - setDstData(dstIndex, (long) v10); + setDstData(dstIndex, Math.round(v10)); } else { - setDstData(dstIndex, (long) v11); + setDstData(dstIndex, Math.round(v11)); } } else if (validityCounter == 2) { if (v00Valid && v01Valid) { - setDstData(dstIndex, (long) ((v00 * (1 - wx)) + (v01 * wx))); + setDstData(dstIndex, Math.round((v00 * (1 - wx)) + (v01 * wx))); } else if (v10Valid && v11Valid) { - setDstData(dstIndex, (long) ((v10 * (1 - wx)) + (v11 * wx))); + setDstData(dstIndex, Math.round((v10 * (1 - wx)) + (v11 * wx))); } else if (v00Valid && v10Valid) { - setDstData(dstIndex, (long) ((v00 * (1 - wy)) + (v10 * wy))); + setDstData(dstIndex, Math.round((v00 * (1 - wy)) + (v10 * wy))); } else if (v01Valid && v11Valid) { - setDstData(dstIndex, (long) ((v01 * (1 - wy)) + (v11 * wy))); + setDstData(dstIndex, Math.round((v01 * (1 - wy)) + (v11 * wy))); } else if (v00Valid && v11Valid) { double ws = 1 / ((wx * wy) + ((1 - wx) * (1 - wy))); double v = ((v00 * (1 - wx)) * (1 - wy)) + (v11 * wx * wy); v *= ws; - setDstData(dstIndex, (long) v); + setDstData(dstIndex, Math.round(v)); } else { double ws = 1 / (((1 - wx) * wy) + (wx * (1 - wy))); double v = (v01 * wx * (1 - wy)) + (v10 * (1 - wx) * wy); v *= ws; - setDstData(dstIndex, (long) v); + setDstData(dstIndex, Math.round(v)); } } else { //validityCounter == 3 double w00 = (1 - wx) * (1 - wy); @@ -157,22 +155,22 @@ public void interpolate(Rectangle destRect, Rectangle srcRect, double scaleX, do w01 += (0.5 * w00); w10 += (0.5 * w00); double v = v01 * w01 + v10 * w10 + v11 * w11; - setDstData(dstIndex, (long) v); + setDstData(dstIndex, Math.round(v)); } else if (!v01Valid) { w00 += (0.5 * w01); w11 += (0.5 * w01); double v = v00 * w00 + v10 * w10 + v11 * w11; - setDstData(dstIndex, (long) v); + setDstData(dstIndex, Math.round(v)); } else if (!v10Valid) { w00 += (0.5 * w10); w11 += (0.5 * w10); double v = v00 * w00 + v01 * w01 + v11 * w11; - setDstData(dstIndex, (long) v); + setDstData(dstIndex, Math.round(v)); } else { w01 += (0.5 * w11); w10 += (0.5 * w11); double v = v00 * w00 + v01 * w01 + v10 * w10; - setDstData(dstIndex, (long) v); + setDstData(dstIndex, Math.round(v)); } } } @@ -186,4 +184,166 @@ private boolean isValid(double v) { } + static class CubicConvolution extends LongDataInterpolator { + + @Override + public void interpolate(Rectangle destRect, Rectangle srcRect, double scaleX, double scaleY, + double offsetX, double offsetY) { + final int srcH = (int) srcRect.getHeight(); + final int srcW = (int) srcRect.getWidth(); + int dstIndexY = getDstOffset(); + double subPixelOffsetY = offsetY - (int) offsetY; + double subPixelOffsetX = offsetX - (int) offsetX; + for (int dstY = 0; dstY < destRect.getHeight(); dstY++) { + double srcYF = subPixelOffsetY + (scaleY * (dstY + 0.5)) - 0.5; + int srcY = (int) srcYF; + int srcIndexY = getSrcOffset() + srcY * getSrcScalineStride(); + double wy = srcYF - srcY; + for (int dstX = 0; dstX < destRect.getWidth(); dstX++) { + double srcXF = subPixelOffsetX + (scaleX * (dstX + 0.5)) - 0.5; + int srcX = (int) srcXF; + double wx = srcXF - srcX; + final double[][] validRectangle = getValidRectangle(srcX, srcY, srcIndexY, srcW, srcH); + double[] rowMeans = new double[4]; + for (int i = 0; i < 4; i++) { + rowMeans[i] = + (validRectangle[i][0] * (4 - 8 * (1 + wx) + 5 * Math.pow(1 + wx, 2) - Math.pow(1 + wx, 3))) + + (validRectangle[i][1] * (1 - 2 * Math.pow(wx, 2) + Math.pow(wx, 3))) + + (validRectangle[i][2] * (1 - 2 * Math.pow(1 - wx, 2) + Math.pow(1 - wx, 3))) + + (validRectangle[i][3] * (4 - 8 * (2 - wx) + 5 * Math.pow(2 - wx, 2) - Math.pow(2 - wx, 3))); + } + double v = + (rowMeans[0] * (4 - 8 * (1 + wy) + 5 * Math.pow(1 + wy, 2) - Math.pow(1 + wy, 3))) + + (rowMeans[1] * (1 - 2 * Math.pow(wy, 2) + Math.pow(wy, 3))) + + (rowMeans[2] * (1 - 2 * Math.pow(1 - wy, 2) + Math.pow(1 - wy, 3))) + + (rowMeans[3] * (4 - 8 * (2 - wy) + 5 * Math.pow(2 - wy, 2) - Math.pow(2 - wy, 3))); + if (Double.isNaN(v) || Math.abs(v - getNoDataValue()) < 1e-8) { + setDstData(dstIndexY + dstX, getNoDataValue()); + } else { + setDstData(dstIndexY + dstX, Math.round(v)); + } + } + dstIndexY += getDstScalineStride(); + } + } + + double[][] getValidRectangle(int srcX, int srcY, int srcIndexY, int srcW, int srcH) { + double[][] validRectangle = new double[4][4]; + validRectangle[1][1] = getSrcData(srcIndexY + srcX); + + final boolean notAtLeftBorder = srcX - 1 >= 0; + final boolean notAtUpperBorder = srcY - 1 >= 0; + final boolean notAtRightBorder = srcX + 1 < srcW; + final boolean notAtRightBorder2 = srcX + 2 < srcW; + final boolean notAtLowerBorder = srcY + 1 < srcH; + final boolean notAtLowerBorder2 = srcY + 2 < srcH; + validRectangle[0][1] = notAtLeftBorder ? getSrcData(srcIndexY, srcX, 0, 1) : validRectangle[1][1]; + validRectangle[1][0] = notAtUpperBorder ? getSrcData(srcIndexY, srcX, 1, 0) : validRectangle[1][1]; + validRectangle[2][1] = notAtRightBorder ? getSrcData(srcIndexY, srcX, 2, 1) : validRectangle[1][1]; + validRectangle[1][2] = notAtLowerBorder ? getSrcData(srcIndexY, srcX, 1, 2) : validRectangle[1][1]; + validRectangle[3][1] = notAtRightBorder2 ? getSrcData(srcIndexY, srcX, 3, 1) : validRectangle[2][1]; + validRectangle[1][3] = notAtLowerBorder2 ? getSrcData(srcIndexY, srcX, 1, 3) : validRectangle[1][2]; + + if (notAtLeftBorder) { + if (notAtUpperBorder) { + validRectangle[0][0] = getSrcData(srcIndexY, srcX, 0, 0); + } else { + validRectangle[0][0] = validRectangle[0][1]; + } + } else if (notAtUpperBorder) { + validRectangle[0][0] = validRectangle[1][0]; + } else { + validRectangle[0][0] = validRectangle[1][1]; + } + if (notAtRightBorder) { + if (notAtUpperBorder) { + validRectangle[2][0] = getSrcData(srcIndexY, srcX, 2, 0); + } else { + validRectangle[2][0] = validRectangle[2][1]; + } + } else if (notAtUpperBorder) { + validRectangle[2][0] = validRectangle[1][0]; + } else { + validRectangle[2][0] = validRectangle[1][1]; + } + if (notAtRightBorder) { + if (notAtLowerBorder) { + validRectangle[2][2] = getSrcData(srcIndexY, srcX, 2, 2); + } else { + validRectangle[2][2] = validRectangle[2][1]; + } + } else if (notAtLowerBorder) { + validRectangle[2][2] = validRectangle[1][2]; + } else { + validRectangle[2][2] = validRectangle[1][1]; + } + if (notAtLeftBorder) { + if (notAtLowerBorder) { + validRectangle[0][2] = getSrcData(srcIndexY, srcX, 0, 2); + } else { + validRectangle[0][2] = validRectangle[0][1]; + } + } else if (notAtLowerBorder) { + validRectangle[0][2] = validRectangle[1][2]; + } else { + validRectangle[0][2] = validRectangle[1][1]; + } + if (notAtRightBorder2) { + if (notAtUpperBorder) { + validRectangle[3][0] = getSrcData(srcIndexY, srcX, 3, 0); + } else { + validRectangle[3][0] = validRectangle[3][1]; + } + } else { + validRectangle[3][0] = validRectangle[2][0]; + } + if (notAtRightBorder2) { + if (notAtLowerBorder) { + validRectangle[3][2] = getSrcData(srcIndexY, srcX, 3, 2); + } else { + validRectangle[3][2] = validRectangle[3][1]; + } + } else { + validRectangle[3][2] = validRectangle[2][2]; + } + if (notAtRightBorder) { + if (notAtLowerBorder2) { + validRectangle[2][3] = getSrcData(srcIndexY, srcX, 2, 3); + } else { + validRectangle[2][3] = validRectangle[2][2]; + } + } else { + validRectangle[2][3] = validRectangle[1][3]; + } + if (notAtLeftBorder) { + if (notAtLowerBorder2) { + validRectangle[0][3] = getSrcData(srcIndexY, srcX, 0, 3); + } else { + validRectangle[0][3] = validRectangle[0][2]; + } + } else { + validRectangle[0][3] = validRectangle[1][3]; + } + if (notAtRightBorder2) { + if (notAtLowerBorder2) { + validRectangle[3][3] = getSrcData(srcIndexY, srcX, 3, 3); + } else { + validRectangle[3][3] = validRectangle[3][2]; + } + } else if (notAtLowerBorder2) { + validRectangle[3][3] = validRectangle[2][3]; + } else { + validRectangle[3][3] = validRectangle[2][2]; + } + return validRectangle; + } + + private double getSrcData(int srcIndexY, int srcX, int x, int y) { + int yOffset = (y - 1) * getSrcScalineStride(); + int xOffset = srcX + (x - 1); + return getSrcData(srcIndexY + yOffset + xOffset); + } + + } + } diff --git a/snap-gpf/src/test/java/org/esa/snap/core/gpf/common/resample/InterpolatedOpImageTest.java b/snap-gpf/src/test/java/org/esa/snap/core/gpf/common/resample/InterpolatedOpImageTest.java index 9d8767903b8..639d41893d6 100644 --- a/snap-gpf/src/test/java/org/esa/snap/core/gpf/common/resample/InterpolatedOpImageTest.java +++ b/snap-gpf/src/test/java/org/esa/snap/core/gpf/common/resample/InterpolatedOpImageTest.java @@ -8,7 +8,6 @@ import org.esa.snap.core.datamodel.ProductData; import org.esa.snap.core.image.ImageManager; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import javax.media.jai.ImageLayout; @@ -33,7 +32,7 @@ public void setUp() { int referenceWidth = 3; int referenceHeight = 3; referenceBand = new Band("referenceBand", ProductData.TYPE_INT8, 3, 3); - final AffineTransform imageToModelTransform = new AffineTransform(2, 0, 0, 2, 2, 2); + final AffineTransform imageToModelTransform = new AffineTransform(3, 0, 0, 3, 2, 2); final DefaultMultiLevelModel referenceModel = new DefaultMultiLevelModel(imageToModelTransform, 3, 3); referenceBand.setSourceImage(new DefaultMultiLevelImage(new AbstractMultiLevelSource(referenceModel) { @Override @@ -108,7 +107,7 @@ public void testInterpolate_Int_Bilinear() throws NoninvertibleTransformExceptio @Test public void testBilinear_FirstAndLastPixelValid() throws NoninvertibleTransformException { String expression = "(X%2 == 0.5) ^ (Y%2 == 0.5) ? 123 :(X + 0.5) + ((Y + 0.5) * 2)"; - final Band sourceBand = createSourceBand(ProductData.TYPE_FLOAT32, expression); + final Band sourceBand = createSourceBand(expression); sourceBand.getSourceImage().getData().createCompatibleWritableRaster(); final int dataBufferType = sourceBand.getSourceImage().getSampleModel().getDataType(); final ImageLayout imageLayout = ImageManager.createSingleBandedImageLayout(referenceBand, dataBufferType); @@ -123,11 +122,11 @@ public void testBilinear_FirstAndLastPixelValid() throws NoninvertibleTransformE assertEquals(referenceBand.getRasterHeight(), image.getHeight()); assertEquals(dataBufferType, image.getSampleModel().getDataType()); final Raster targetData = image.getData(); - assertEquals(3.11538457, targetData.getSampleDouble(0, 0, 0), 1e-6); + assertEquals(3.059999942779541, targetData.getSampleDouble(0, 0, 0), 1e-6); assertEquals(4.5, targetData.getSampleDouble(1, 0, 0), 1e-6); assertEquals(6.0, targetData.getSampleDouble(2, 0, 0), 1e-6); assertEquals(4.5, targetData.getSampleDouble(0, 1, 0), 1e-6); - assertEquals(5.88461542, targetData.getSampleDouble(1, 1, 0), 1e-6); + assertEquals(5.940000057220459, targetData.getSampleDouble(1, 1, 0), 1e-6); assertEquals(6.0, targetData.getSampleDouble(2, 1, 0), 1e-6); assertEquals(6.0, targetData.getSampleDouble(0, 2, 0), 1e-6); assertEquals(6.0, targetData.getSampleDouble(1, 2, 0), 1e-6); @@ -137,7 +136,7 @@ public void testBilinear_FirstAndLastPixelValid() throws NoninvertibleTransformE @Test public void testBilinear_MiddlePixelsValid() throws NoninvertibleTransformException { String expression = "(X%2 == 0.5) ^ (Y%2 == 0.5) ? (X + 0.5) + ((Y + 0.5) * 2) : 123"; - final Band sourceBand = createSourceBand(ProductData.TYPE_FLOAT32, expression); + final Band sourceBand = createSourceBand(expression); sourceBand.getSourceImage().getData().createCompatibleWritableRaster(); final int dataBufferType = sourceBand.getSourceImage().getSampleModel().getDataType(); final ImageLayout imageLayout = ImageManager.createSingleBandedImageLayout(referenceBand, dataBufferType); @@ -153,9 +152,9 @@ public void testBilinear_MiddlePixelsValid() throws NoninvertibleTransformExcept assertEquals(dataBufferType, image.getSampleModel().getDataType()); final Raster targetData = image.getData(); assertEquals(4.5, targetData.getSampleDouble(0, 0, 0), 1e-6); - assertEquals(4.038461685180664, targetData.getSampleDouble(1, 0, 0), 1e-6); + assertEquals(4.019999980926514, targetData.getSampleDouble(1, 0, 0), 1e-6); assertEquals(4.0, targetData.getSampleDouble(2, 0, 0), 1e-6); - assertEquals(4.961538314819336, targetData.getSampleDouble(0, 1, 0), 1e-6); + assertEquals(4.980000019073486, targetData.getSampleDouble(0, 1, 0), 1e-6); assertEquals(4.5, targetData.getSampleDouble(1, 1, 0), 1e-6); assertEquals(4.0, targetData.getSampleDouble(2, 1, 0), 1e-6); assertEquals(5.0, targetData.getSampleDouble(0, 2, 0), 1e-6); @@ -166,7 +165,7 @@ public void testBilinear_MiddlePixelsValid() throws NoninvertibleTransformExcept @Test public void testBilinear_FirstPixelIsInvalid() throws NoninvertibleTransformException { String expression = "(X == 0.5) && (Y == 0.5) ? 123 : (X + 0.5) + ((Y + 0.5) * 2)"; - final Band sourceBand = createSourceBand(ProductData.TYPE_FLOAT32, expression); + final Band sourceBand = createSourceBand(expression); sourceBand.getSourceImage().getData().createCompatibleWritableRaster(); final int dataBufferType = sourceBand.getSourceImage().getSampleModel().getDataType(); final ImageLayout imageLayout = ImageManager.createSingleBandedImageLayout(referenceBand, dataBufferType); @@ -181,21 +180,21 @@ public void testBilinear_FirstPixelIsInvalid() throws NoninvertibleTransformExce assertEquals(referenceBand.getRasterHeight(), image.getHeight()); assertEquals(dataBufferType, image.getSampleModel().getDataType()); final Raster targetData = image.getData(); - assertEquals(4.541666507720947, targetData.getSampleDouble(0, 0, 0), 1e-6); - assertEquals(4.375, targetData.getSampleDouble(1, 0, 0), 1e-6); - assertEquals(4.333333492279053, targetData.getSampleDouble(2, 0, 0), 1e-6); - assertEquals(5.041666507720947, targetData.getSampleDouble(0, 1, 0), 1e-6); - assertEquals(5.541666507720947, targetData.getSampleDouble(1, 1, 0), 1e-6); - assertEquals(5.66666666, targetData.getSampleDouble(2, 1, 0), 1e-6); - assertEquals(5.16666666, targetData.getSampleDouble(0, 2, 0), 1e-6); - assertEquals(5.83333333, targetData.getSampleDouble(1, 2, 0), 1e-6); + assertEquals(4.5234375, targetData.getSampleDouble(0, 0, 0), 1e-6); + assertEquals(4.2890625, targetData.getSampleDouble(1, 0, 0), 1e-6); + assertEquals(4.25, targetData.getSampleDouble(2, 0, 0), 1e-6); + assertEquals(5.0390625, targetData.getSampleDouble(0, 1, 0), 1e-6); + assertEquals(5.6484375, targetData.getSampleDouble(1, 1, 0), 1e-6); + assertEquals(5.75, targetData.getSampleDouble(2, 1, 0), 1e-6); + assertEquals(5.125, targetData.getSampleDouble(0, 2, 0), 1e-6); + assertEquals(5.875, targetData.getSampleDouble(1, 2, 0), 1e-6); assertEquals(6.0, targetData.getSampleDouble(2, 2, 0)); } @Test public void testBilinear_SecondPixelIsInvalid() throws NoninvertibleTransformException { String expression = "(X == 1.5) && (Y == 0.5) ? 123 : (X + 0.5) + ((Y + 0.5) * 2)"; - final Band sourceBand = createSourceBand(ProductData.TYPE_FLOAT32, expression); + final Band sourceBand = createSourceBand(expression); sourceBand.getSourceImage().getData().createCompatibleWritableRaster(); final int dataBufferType = sourceBand.getSourceImage().getSampleModel().getDataType(); final ImageLayout imageLayout = ImageManager.createSingleBandedImageLayout(referenceBand, dataBufferType); @@ -210,21 +209,21 @@ public void testBilinear_SecondPixelIsInvalid() throws NoninvertibleTransformExc assertEquals(referenceBand.getRasterHeight(), image.getHeight()); assertEquals(dataBufferType, image.getSampleModel().getDataType()); final Raster targetData = image.getData(); - assertEquals(3.569444417953491, targetData.getSampleDouble(0, 0, 0), 1e-6); - assertEquals(4.513888835906982, targetData.getSampleDouble(1, 0, 0), 1e-6); + assertEquals(3.4296875, targetData.getSampleDouble(0, 0, 0), 1e-6); + assertEquals(4.5078125, targetData.getSampleDouble(1, 0, 0), 1e-6); assertEquals(6.0, targetData.getSampleDouble(2, 0, 0), 1e-6); - assertEquals(4.847222328186035, targetData.getSampleDouble(0, 1, 0), 1e-6); - assertEquals(5.56944465637207, targetData.getSampleDouble(1, 1, 0), 1e-6); + assertEquals(4.8828125, targetData.getSampleDouble(0, 1, 0), 1e-6); + assertEquals(5.6796875, targetData.getSampleDouble(1, 1, 0), 1e-6); assertEquals(6.0, targetData.getSampleDouble(2, 1, 0), 1e-6); - assertEquals(5.16666666, targetData.getSampleDouble(0, 2, 0), 1e-6); - assertEquals(5.83333333, targetData.getSampleDouble(1, 2, 0), 1e-6); + assertEquals(5.125, targetData.getSampleDouble(0, 2, 0), 1e-6); + assertEquals(5.875, targetData.getSampleDouble(1, 2, 0), 1e-6); assertEquals(6.0, targetData.getSampleDouble(2, 2, 0)); } @Test public void testBilinear_ThirdPixelIsInvalid() throws NoninvertibleTransformException { String expression = "(X == 0.5) && (Y == 1.5) ? 123 : (X + 0.5) + ((Y + 0.5) * 2)"; - final Band sourceBand = createSourceBand(ProductData.TYPE_FLOAT32, expression); + final Band sourceBand = createSourceBand(expression); sourceBand.getSourceImage().getData().createCompatibleWritableRaster(); final int dataBufferType = sourceBand.getSourceImage().getSampleModel().getDataType(); final ImageLayout imageLayout = ImageManager.createSingleBandedImageLayout(referenceBand, dataBufferType); @@ -239,12 +238,12 @@ public void testBilinear_ThirdPixelIsInvalid() throws NoninvertibleTransformExce assertEquals(referenceBand.getRasterHeight(), image.getHeight()); assertEquals(dataBufferType, image.getSampleModel().getDataType()); final Raster targetData = image.getData(); - assertEquals(3.430555582046509, targetData.getSampleDouble(0, 0, 0), 1e-6); - assertEquals(4.152777671813965, targetData.getSampleDouble(1, 0, 0), 1e-6); - assertEquals(4.333333492279053, targetData.getSampleDouble(2, 0, 0), 1e-6); - assertEquals(4.486111164093018, targetData.getSampleDouble(0, 1, 0), 1e-6); - assertEquals(5.430555820465088, targetData.getSampleDouble(1, 1, 0), 1e-6); - assertEquals(5.666666507720947, targetData.getSampleDouble(2, 1, 0), 1e-6); + assertEquals(3.3203125, targetData.getSampleDouble(0, 0, 0), 1e-6); + assertEquals(4.1171875, targetData.getSampleDouble(1, 0, 0), 1e-6); + assertEquals(4.25, targetData.getSampleDouble(2, 0, 0), 1e-6); + assertEquals(4.4921875, targetData.getSampleDouble(0, 1, 0), 1e-6); + assertEquals(5.5703125, targetData.getSampleDouble(1, 1, 0), 1e-6); + assertEquals(5.75, targetData.getSampleDouble(2, 1, 0), 1e-6); assertEquals(6.0, targetData.getSampleDouble(0, 2, 0), 1e-6); assertEquals(6.0, targetData.getSampleDouble(1, 2, 0), 1e-6); assertEquals(6.0, targetData.getSampleDouble(2, 2, 0)); @@ -253,7 +252,7 @@ public void testBilinear_ThirdPixelIsInvalid() throws NoninvertibleTransformExce @Test public void testBilinear_FourthPixelIsInvalid() throws NoninvertibleTransformException { String expression = "(X == 1.5) && (Y == 1.5) ? 123 : (X + 0.5) + ((Y + 0.5) * 2)"; - final Band sourceBand = createSourceBand(ProductData.TYPE_FLOAT32, expression); + final Band sourceBand = createSourceBand(expression); sourceBand.getSourceImage().getData().createCompatibleWritableRaster(); final int dataBufferType = sourceBand.getSourceImage().getSampleModel().getDataType(); final ImageLayout imageLayout = ImageManager.createSingleBandedImageLayout(referenceBand, dataBufferType); @@ -268,11 +267,11 @@ public void testBilinear_FourthPixelIsInvalid() throws NoninvertibleTransformExc assertEquals(referenceBand.getRasterHeight(), image.getHeight()); assertEquals(dataBufferType, image.getSampleModel().getDataType()); final Raster targetData = image.getData(); - assertEquals(3.4583332538604736, targetData.getSampleDouble(0, 0, 0), 1e-6); - assertEquals(3.9583332538604736, targetData.getSampleDouble(1, 0, 0), 1e-6); + assertEquals(3.3515625, targetData.getSampleDouble(0, 0, 0), 1e-6); + assertEquals(3.9609375, targetData.getSampleDouble(1, 0, 0), 1e-6); assertEquals(4.0, targetData.getSampleDouble(2, 0, 0), 1e-6); - assertEquals(4.625, targetData.getSampleDouble(0, 1, 0), 1e-6); - assertEquals(4.458333492279053, targetData.getSampleDouble(1, 1, 0), 1e-6); + assertEquals(4.7109375, targetData.getSampleDouble(0, 1, 0), 1e-6); + assertEquals(4.4765625, targetData.getSampleDouble(1, 1, 0), 1e-6); assertEquals(4.0, targetData.getSampleDouble(2, 1, 0), 1e-6); assertEquals(5.0, targetData.getSampleDouble(0, 2, 0), 1e-6); assertEquals(5.0, targetData.getSampleDouble(1, 2, 0), 1e-6); @@ -280,37 +279,31 @@ public void testBilinear_FourthPixelIsInvalid() throws NoninvertibleTransformExc } @Test - @Ignore("Needs to be fixed. SNAP-1241") public void testInterpolate_Double_CubicConvolution() throws NoninvertibleTransformException { testCubicConvolution(ProductData.TYPE_FLOAT64); } @Test - @Ignore("Needs to be fixed. SNAP-1241") public void testInterpolate_Float_CubicConvolution() throws NoninvertibleTransformException { testCubicConvolution(ProductData.TYPE_FLOAT32); } @Test - @Ignore("Needs to be fixed. SNAP-1241") public void testInterpolate_Byte_CubicConvolution() throws NoninvertibleTransformException { testCubicConvolution(ProductData.TYPE_INT8); } @Test - @Ignore("Needs to be fixed. SNAP-1241") public void testInterpolate_Short_CubicConvolution() throws NoninvertibleTransformException { testCubicConvolution(ProductData.TYPE_INT16); } @Test - @Ignore("Needs to be fixed. SNAP-1241") public void testInterpolate_UShort_CubicConvolution() throws NoninvertibleTransformException { testCubicConvolution(ProductData.TYPE_UINT16); } @Test - @Ignore("Needs to be fixed. SNAP-1241") public void testInterpolate_Int_CubicConvolution() throws NoninvertibleTransformException { testCubicConvolution(ProductData.TYPE_INT32); } @@ -330,15 +323,27 @@ private void testCubicConvolution(int dataType) throws NoninvertibleTransformExc assertEquals(referenceBand.getRasterHeight(), image.getHeight()); assertEquals(dataBufferType, image.getSampleModel().getDataType()); final Raster targetData = image.getData(); - assertEquals(3.0, targetData.getSampleDouble(0, 0, 0), 1e-8); - assertEquals(4.0, targetData.getSampleDouble(1, 0, 0), 1e-8); - assertEquals(4.0, targetData.getSampleDouble(2, 0, 0), 1e-8); - assertEquals(5.0, targetData.getSampleDouble(0, 1, 0), 1e-8); - assertEquals(6.0, targetData.getSampleDouble(1, 1, 0), 1e-8); - assertEquals(6.0, targetData.getSampleDouble(2, 1, 0), 1e-8); - assertEquals(5.0, targetData.getSampleDouble(0, 2, 0), 1e-8); - assertEquals(6.0, targetData.getSampleDouble(1, 2, 0), 1e-8); - assertEquals(6.0, targetData.getSampleDouble(2, 2, 0), 1e-8); + if ((dataType == ProductData.TYPE_FLOAT32) || (dataType == ProductData.TYPE_FLOAT64)) { + assertEquals(3.333984375, targetData.getSampleDouble(0, 0, 0), 1e-6); + assertEquals(4.669921875, targetData.getSampleDouble(1, 0, 0), 1e-6); + assertEquals(5.1640625, targetData.getSampleDouble(2, 0, 0), 1e-6); + assertEquals(4.001953125, targetData.getSampleDouble(0, 1, 0), 1e-6); + assertEquals(5.337890625, targetData.getSampleDouble(1, 1, 0), 1e-6); + assertEquals(5.75, targetData.getSampleDouble(2, 1, 0), 1e-6); + assertEquals(5.892578125, targetData.getSampleDouble(0, 2, 0), 1e-6); + assertEquals(7.064453125, targetData.getSampleDouble(1, 2, 0), 1e-6); + assertEquals(7.69921875, targetData.getSampleDouble(2, 2, 0), 1e-6); + } else { + assertEquals(3.0, targetData.getSampleDouble(0, 0, 0), 1e-6); + assertEquals(5.0, targetData.getSampleDouble(1, 0, 0), 1e-6); + assertEquals(5.0, targetData.getSampleDouble(2, 0, 0), 1e-6); + assertEquals(4.0, targetData.getSampleDouble(0, 1, 0), 1e-6); + assertEquals(5.0, targetData.getSampleDouble(1, 1, 0), 1e-6); + assertEquals(6.0, targetData.getSampleDouble(2, 1, 0), 1e-6); + assertEquals(6.0, targetData.getSampleDouble(0, 2, 0), 1e-6); + assertEquals(7.0, targetData.getSampleDouble(1, 2, 0), 1e-6); + assertEquals(8.0, targetData.getSampleDouble(2, 2, 0), 1e-6); + } } private void testBilinear(int dataType) throws NoninvertibleTransformException { @@ -359,23 +364,23 @@ private void testBilinear(int dataType) throws NoninvertibleTransformException { if (!(dataType == ProductData.TYPE_FLOAT32) && !(dataType == ProductData.TYPE_FLOAT64)) { assertEquals(3.0, targetData.getSampleDouble(0, 0, 0), 1e-6); assertEquals(4.0, targetData.getSampleDouble(1, 0, 0), 1e-6); - assertEquals(4.0, targetData.getSampleDouble(2, 0, 0), 1e-6); - assertEquals(4.0, targetData.getSampleDouble(0, 1, 0), 1e-6); - assertEquals(5.0, targetData.getSampleDouble(1, 1, 0), 1e-6); - assertEquals(5.0, targetData.getSampleDouble(2, 1, 0), 1e-6); - assertEquals(5.0, targetData.getSampleDouble(0, 2, 0), 1e-6); - assertEquals(5.0, targetData.getSampleDouble(1, 2, 0), 1e-6); - assertEquals(6.0, targetData.getSampleDouble(2, 2, 0), 1e-6); + assertEquals(5.0, targetData.getSampleDouble(2, 0, 0), 1e-6); + assertEquals(5.0, targetData.getSampleDouble(0, 1, 0), 1e-6); + assertEquals(6.0, targetData.getSampleDouble(1, 1, 0), 1e-6); + assertEquals(6.0, targetData.getSampleDouble(2, 1, 0), 1e-6); + assertEquals(6.0, targetData.getSampleDouble(0, 2, 0), 1e-6); + assertEquals(7.0, targetData.getSampleDouble(1, 2, 0), 1e-6); + assertEquals(8.0, targetData.getSampleDouble(2, 2, 0), 1e-6); } else { - assertEquals(3.5, targetData.getSampleDouble(0, 0, 0), 1e-6); - assertEquals(4.16666666, targetData.getSampleDouble(1, 0, 0), 1e-6); - assertEquals(4.33333333, targetData.getSampleDouble(2, 0, 0), 1e-6); - assertEquals(4.83333333, targetData.getSampleDouble(0, 1, 0), 1e-6); - assertEquals(5.5, targetData.getSampleDouble(1, 1, 0), 1e-6); - assertEquals(5.66666666, targetData.getSampleDouble(2, 1, 0), 1e-6); - assertEquals(5.16666666, targetData.getSampleDouble(0, 2, 0), 1e-6); - assertEquals(5.83333333, targetData.getSampleDouble(1, 2, 0), 1e-6); - assertEquals(6.0, targetData.getSampleDouble(2, 2, 0)); + assertEquals(3.375, targetData.getSampleDouble(0, 0, 0), 1e-6); + assertEquals(4.125, targetData.getSampleDouble(1, 0, 0), 1e-6); + assertEquals(4.875, targetData.getSampleDouble(2, 0, 0), 1e-6); + assertEquals(4.875, targetData.getSampleDouble(0, 1, 0), 1e-6); + assertEquals(5.625, targetData.getSampleDouble(1, 1, 0), 1e-6); + assertEquals(6.375, targetData.getSampleDouble(2, 1, 0), 1e-6); + assertEquals(6.375, targetData.getSampleDouble(0, 2, 0), 1e-6); + assertEquals(7.125, targetData.getSampleDouble(1, 2, 0), 1e-6); + assertEquals(7.875, targetData.getSampleDouble(2, 2, 0), 1e-6); } } @@ -397,28 +402,30 @@ private void testNearestNeighbour(int dataType) throws NoninvertibleTransformExc final Raster targetData = image.getData(); assertEquals(3.0, targetData.getSampleDouble(0, 0, 0), 1e-8); assertEquals(4.0, targetData.getSampleDouble(1, 0, 0), 1e-8); - assertEquals(4.0, targetData.getSampleDouble(2, 0, 0), 1e-8); + assertEquals(5.0, targetData.getSampleDouble(2, 0, 0), 1e-8); assertEquals(5.0, targetData.getSampleDouble(0, 1, 0), 1e-8); assertEquals(6.0, targetData.getSampleDouble(1, 1, 0), 1e-8); - assertEquals(6.0, targetData.getSampleDouble(2, 1, 0), 1e-8); - assertEquals(5.0, targetData.getSampleDouble(0, 2, 0), 1e-8); - assertEquals(6.0, targetData.getSampleDouble(1, 2, 0), 1e-8); - assertEquals(6.0, targetData.getSampleDouble(2, 2, 0), 1e-8); + assertEquals(7.0, targetData.getSampleDouble(2, 1, 0), 1e-8); + assertEquals(7.0, targetData.getSampleDouble(0, 2, 0), 1e-8); + assertEquals(8.0, targetData.getSampleDouble(1, 2, 0), 1e-8); + assertEquals(9.0, targetData.getSampleDouble(2, 2, 0), 1e-8); } private Band createSourceBand(int dataType) { - return createSourceBand(dataType, "(X + 0.5) + ((Y + 0.5) * 2)"); + return createSourceBand(dataType, "(X + 0.5) + ((Y + 0.5) * 2)", 4); + } + + private Band createSourceBand(String expression) { + return createSourceBand(ProductData.TYPE_FLOAT32, expression, 2); } - private Band createSourceBand(int dataType, String expression) { - int sourceWidth = 2; - int sourceHeight = 2; - int sourceScaleX = 3; - int sourceScaleY = 3; + private Band createSourceBand(int dataType, String expression, int widthAndHeight) { + int sourceScaleX = 4; + int sourceScaleY = 4; int sourceTranslateX = 1; int sourceTranslateY = 1; final AffineTransform imageToModelTransform = new AffineTransform(sourceScaleX, 0, 0, sourceScaleY, sourceTranslateX, sourceTranslateY); - final Product sourceProduct = new Product("dummy", "dummy", sourceWidth, sourceHeight); + final Product sourceProduct = new Product("dummy", "dummy", widthAndHeight, widthAndHeight); final Band sourceBand = sourceProduct.addBand("sourceBand", expression, dataType); sourceBand.setNoDataValue(123); sourceBand.setImageToModelTransform(imageToModelTransform);