sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: Add a simple interpolation test.
Date Thu, 26 Mar 2020 10:18:58 GMT
This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new c92fbca  Add a simple interpolation test.
c92fbca is described below

commit c92fbca4ea76b61d979ec90d39bf1e2a2b838011
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Thu Mar 26 11:18:35 2020 +0100

    Add a simple interpolation test.
---
 .../java/org/apache/sis/image/Interpolation.java   |   7 +-
 .../org/apache/sis/image/LanczosInterpolation.java |   4 +-
 .../java/org/apache/sis/image/ResampledImage.java  |  13 ++-
 .../org/apache/sis/image/InterpolationTest.java    | 114 +++++++++++++++++++++
 .../apache/sis/test/suite/FeatureTestSuite.java    |   1 +
 5 files changed, 132 insertions(+), 7 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java b/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java
index cdb0498..ef5ac57 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java
@@ -25,6 +25,9 @@ import java.nio.DoubleBuffer;
  * of pixels using a local neighborhood. The sampling is performed by the {@link ResampledImage}
class, which
  * gives the sample values to the {@code interpolate(…)} method of this interpolation.
  *
+ * <p>All methods in this interface shall be safe for concurrent use in multi-threading
context.
+ * For example interpolations may be executed in a different thread for each tile in an image.</p>
+ *
  * <p>This interface is designed for interpolations in a two-dimensional space only.</p>
  *
  * @author  Rémi Marechal (Geomatys)
@@ -134,7 +137,9 @@ public interface Interpolation {
     };
 
     /**
-     * Lanczos interpolation. The kernel is:
+     * Lanczos interpolation for photographic images.
+     * This interpolation is not recommended for images that may contain NaN values.
+     * The Lanczos reconstruction kernel is:
      *
      * <blockquote>
      * <var>L</var>(<var>x</var>) = <var>a</var>⋅sin(π⋅<var>x</var>)⋅sin(π⋅<var>x</var>/<var>a</var>)/(π⋅<var>x</var>)²
diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/LanczosInterpolation.java
b/core/sis-feature/src/main/java/org/apache/sis/image/LanczosInterpolation.java
index 138df5f..91e63e7 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/LanczosInterpolation.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/LanczosInterpolation.java
@@ -22,8 +22,8 @@ import java.nio.DoubleBuffer;
 
 
 /**
- * Lanczos interpolation of arbitrary size.
- * The kernel is:
+ * Lanczos interpolation of arbitrary size. This interpolation is good for photographic images
but
+ * not recommended for images that may contain NaN values. The Lanczos reconstruction kernel
is:
  *
  * <blockquote>
  * <var>L</var>(<var>x</var>) = <var>a</var>⋅sin(π⋅<var>x</var>)⋅sin(π⋅<var>x</var>/<var>a</var>)/(π⋅<var>x</var>)²
diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/ResampledImage.java b/core/sis-feature/src/main/java/org/apache/sis/image/ResampledImage.java
index 5323ce9..ca61728 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/ResampledImage.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/ResampledImage.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.image;
 
+import java.util.Arrays;
 import java.nio.DoubleBuffer;
 import java.awt.Dimension;
 import java.awt.Rectangle;
@@ -103,14 +104,17 @@ public class ResampledImage extends ComputedImage {
      * by a non-linear transform from <em>this</em> image to the specified <em>source</em>
image.
      * That transform should map {@linkplain org.opengis.referencing.datum.PixelInCell#CELL_CENTER
pixel centers}.
      *
+     * <p>If a pixel in this image can not be mapped to a pixel in the source image,
then the sample values are set
+     * to {@code fillValues}. If the given array is {@code null}, or if any element in the
given array is {@code null},
+     * then the default fill value is NaN for floating point data types or zero for integer
data types.</p>
+     *
      * @param  bounds         domain of pixel coordinates of this resampled image.
      * @param  toSource       conversion of pixel coordinates of this image to pixel coordinates
of {@code source} image.
      * @param  source         the image to be resampled.
      * @param  interpolation  the object to use for performing interpolations.
      * @param  fillValues     the values to use for pixels in this image that can not be
mapped to pixels in source image.
-     *                        The array length must be equal to the number of bands. If the
array is {@code null},
-     *                        the default value is zero in all bands. If any element in the
array is {@code null},
-     *                        the default value is zero for the corresponding band.
+     *                        The array length must be equal to the number of bands.
+     *                        May be {@code null} or contain {@code null} elements.
      */
     public ResampledImage(final Rectangle bounds, final MathTransform toSource, final RenderedImage
source,
                           final Interpolation interpolation, final Number[] fillValues)
@@ -168,6 +172,7 @@ public class ResampledImage extends ComputedImage {
             this.fillValues = fill;
         } else {
             final double[] fill = new double[numBands];
+            Arrays.fill(fill, Double.NaN);
             if (fillValues != null) {
                 for (int i=0; i<numBands; i++) {
                     final Number f = fillValues[i];
@@ -345,7 +350,7 @@ public class ResampledImage extends ComputedImage {
             values      = new double[numBands];
             intValues   = new int[scanline * numBands];
             valuesArray = intValues;
-            final NumberRange<?>[] ranges = it.getSampleRanges();
+            final NumberRange<?>[] ranges = it.getSampleRanges();   // Assumes source.sampleModel
== this.sampleModel.
             minValues = new long[ranges.length];
             maxValues = new long[ranges.length];
             for (int i=0; i<ranges.length; i++) {
diff --git a/core/sis-feature/src/test/java/org/apache/sis/image/InterpolationTest.java b/core/sis-feature/src/test/java/org/apache/sis/image/InterpolationTest.java
new file mode 100644
index 0000000..d304163
--- /dev/null
+++ b/core/sis-feature/src/test/java/org/apache/sis/image/InterpolationTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.sis.image;
+
+import java.util.Random;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.image.DataBuffer;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import org.apache.sis.internal.referencing.j2d.AffineTransform2D;
+import org.apache.sis.test.TestCase;
+import org.apache.sis.test.TestUtilities;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests {@link Interpolation} predefined instances.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.1
+ * @since   1.1
+ */
+public final strictfp class InterpolationTest extends TestCase {
+    /**
+     * Size of tiles in this test. The width should be different than the height
+     * for increasing the chances to detect errors in index calculations.
+     */
+    private static final int TILE_WIDTH = 5, TILE_HEIGHT = 4;
+
+    /**
+     * Creates a rendered image with arbitrary tiles.
+     *
+     * @param  dataType  {@link DataBuffer#TYPE_SHORT} or {@link DataBuffer#TYPE_FLOAT}.
+     */
+    private static PlanarImage createImage(final int dataType) {
+        final Random random = TestUtilities.createRandomNumberGenerator();
+        final TiledImageMock image = new TiledImageMock(
+                DataBuffer.TYPE_SHORT, 2,       // dataType and numBands
+                random.nextInt(32) - 10,        // minX
+                random.nextInt(32) - 10,        // minY
+                TILE_WIDTH  * 3,                // width
+                TILE_HEIGHT * 3,                // height
+                TILE_WIDTH,
+                TILE_HEIGHT,
+                random.nextInt(32) - 10,        // minTileX
+                random.nextInt(32) - 10);       // minTileY
+        image.validate();
+        image.initializeAllTiles(0);
+        image.setRandomValues(1, random, 1024);
+        return image;
+    }
+
+    /**
+     * Tests interpolation in the simple case where the image is scaled by a factor 2.
+     * All sample values at even indices in the result should be equal to sample values
+     * at the index divided by 2 in the source image. Sample values at odd indices have
+     * values that depend on the interpolation method.
+     *
+     * @param  interpolation  the interpolation method to test.
+     * @param  isInteger      whether to test with integer values or floating point type.
+     * @throws NoninvertibleTransformException if the test did not setup the transform correctly.
+     */
+    private static void scaleByTwo(final Interpolation interpolation, final boolean isInteger)
throws NoninvertibleTransformException {
+        final PlanarImage     source = createImage(isInteger ? DataBuffer.TYPE_SHORT : DataBuffer.TYPE_FLOAT);
+        final Rectangle       bounds = new Rectangle(-40, 50, source.getWidth() * 2, source.getHeight()
* 2);
+        final AffineTransform tr     = AffineTransform.getTranslateInstance(source.getMinX(),
source.getMinY());
+        tr.scale(0.5, 0.5);
+        tr.translate(-bounds.x, -bounds.y);
+        final ResampledImage target = new ResampledImage(bounds, new AffineTransform2D(tr),
source, interpolation, null);
+        assertNull(target.verify());        // Fails if we did not setup the `toSource` transform
correctly.
+
+        tr.invert();
+        final PixelIterator ps = PixelIterator.create(source);
+        final PixelIterator pt = PixelIterator.create(target);
+        double[] sv = null;
+        double[] tv = null;
+        while (ps.next()) {
+            Point p = ps.getPosition();
+            p = (Point) tr.transform(p, p);
+            pt.moveTo(p.x, p.y);
+            sv = ps.getPixel(sv);
+            tv = pt.getPixel(tv);
+            assertArrayEquals(sv, tv, 1E-12);
+        }
+    }
+
+    /**
+     * Tests {@link Interpolation#BILINEAR}.
+     *
+     * @throws NoninvertibleTransformException if the test did not setup the transform correctly.
+     */
+    @Test
+    public void testBilinear() throws NoninvertibleTransformException {
+        scaleByTwo(Interpolation.BILINEAR, true);
+        scaleByTwo(Interpolation.BILINEAR, false);
+    }
+}
diff --git a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
index 355cc3e..7c90233 100644
--- a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
+++ b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java
@@ -81,6 +81,7 @@ import org.junit.runners.Suite;
     org.apache.sis.image.DefaultIteratorTest.class,
     org.apache.sis.image.LinearIteratorTest.class,
     org.apache.sis.image.StatisticsCalculatorTest.class,
+    org.apache.sis.image.InterpolationTest.class,
     org.apache.sis.coverage.CategoryTest.class,
     org.apache.sis.coverage.CategoryListTest.class,
     org.apache.sis.coverage.SampleDimensionTest.class,


Mime
View raw message