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

commit 4a44a2b511a0beca0c9e28d383a4acba719e179e
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Sep 3 15:13:51 2020 +0200

    Fix a 0.5 pixel offset when Interpolation.NEAREST is used.
---
 .../src/main/java/org/apache/sis/image/Interpolation.java        | 1 +
 .../src/main/java/org/apache/sis/image/ResampledImage.java       | 9 +++++----
 2 files changed, 6 insertions(+), 4 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 3eee8df..60916ab 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
@@ -117,6 +117,7 @@ public interface Interpolation {
         @Override public void interpolate(final DoubleBuffer source, final int 
numBands,
                 final double xfrac, final double yfrac, final double[] 
writeTo, int writeToOffset)
         {
+            // TODO: use `get(position(), …)` with JDK13 for avoiding 
mark/reset.
             source.mark();
             source.get(writeTo, writeToOffset, numBands);
             source.reset();
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 de94d0d..f053baa 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
@@ -327,6 +327,7 @@ public class ResampledImage extends ComputedImage {
      * @see #toSourceSupport
      */
     static double interpolationSupportOffset(final int span) {
+        if (span <= 1) return 0.5;                  // Nearest-neighbor 
(special case).
         return -Math.max(0, (span - 1) / 2);        // Round toward 0.
     }
 
@@ -634,7 +635,7 @@ public class ResampledImage extends ComputedImage {
             ymax = domain.getMaxY() - 1;
             xlim = xmax + support.width  - 0.5;         // Limit of 
coordinates where we can interpolate.
             ylim = ymax + support.height - 0.5;
-            xoff = interpolationSupportOffset(support.width)  - 0.5;           
       // Always negative.
+            xoff = interpolationSupportOffset(support.width)  - 0.5;    // 
Always negative (or 0 for nearest-neighbor).
             yoff = interpolationSupportOffset(support.height) - 0.5;
         }
         /*
@@ -643,7 +644,7 @@ public class ResampledImage extends ComputedImage {
          * for minimal and maximal values. Shortcut may apply to both integer 
values and floating point values.
          */
         final boolean useFillValues = (getDestination() == null);
-        final boolean shortcut = useFillValues && (interpolation == 
Interpolation.NEAREST) &&
+        final boolean shortcut = useFillValues && 
Interpolation.NEAREST.equals(interpolation) &&
                     ImageUtilities.isLosslessConversion(sampleModel, 
tile.getSampleModel());
         /*
          * Prepare a buffer where to store a line of interpolated values. We 
use this buffer for transferring
@@ -719,9 +720,9 @@ public class ResampledImage extends ComputedImage {
                 int ci = 0;     // Index in `coordinates` array.
                 int vi = 0;     // Index in `values` or `intValues` array.
                 for (int tx=tileMinX; tx<tileMaxX; tx++, ci+=tgtDim, 
vi+=numBands) {
-                    final long x = Math.round(coordinates[ci]);
+                    final long x = (long) Math.floor(coordinates[ci]);
                     if (x >= it.lowerX && x < it.upperX) {
-                        final long y = Math.round(coordinates[ci+1]);
+                        final long y = (long) Math.floor(coordinates[ci+1]);
                         if (y >= it.lowerY && y < it.upperY) {
                             if (sx != (sx = (int) x)  |                 // 
Really |, not ||.
                                 sy != (sy = (int) y))

Reply via email to