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 92777dd94e Bug fix in the computation of image bounds by 
`ImageCombiner`. Workaround for `BufferedImage.setData(…)` bug, which does not 
handle float and double types correctly.
92777dd94e is described below

commit 92777dd94e0df100a01103dd6992d24a9e7b3b38
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Sun Apr 30 17:00:26 2023 +0200

    Bug fix in the computation of image bounds by `ImageCombiner`.
    Workaround for `BufferedImage.setData(…)` bug, which does not handle float 
and double types correctly.
---
 .../src/main/java/org/apache/sis/image/ImageCombiner.java     | 11 +++++------
 .../src/main/java/org/apache/sis/image/ImageProcessor.java    |  6 +++++-
 .../org/apache/sis/internal/coverage/j2d/ObservableImage.java |  3 ++-
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/image/ImageCombiner.java 
b/core/sis-feature/src/main/java/org/apache/sis/image/ImageCombiner.java
index 47af72eca3..ea30e340ec 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/ImageCombiner.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/ImageCombiner.java
@@ -26,7 +26,6 @@ import org.opengis.referencing.operation.MathTransform;
 import org.apache.sis.internal.coverage.j2d.ImageLayout;
 import org.apache.sis.internal.coverage.j2d.ImageUtilities;
 import org.apache.sis.internal.coverage.j2d.TileOpExecutor;
-import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.measure.Units;
 
@@ -236,13 +235,13 @@ public class ImageCombiner implements 
Consumer<RenderedImage> {
          * of destination tiles. We have to do that because the resample 
operation below is not free to
          * choose a tile size suiting the given bounds.
          */
-        long maxX = (bounds.x + (long) bounds.width)  - 1;                     
        // Inclusive.
+        long maxX = (bounds.x + (long) bounds.width)  - 1;                     
             // Inclusive.
         long maxY = (bounds.y + (long) bounds.height) - 1;
-        maxX = Numerics.ceilDiv((maxX - tileGridXOffset), tileWidth) * 
tileWidth  + tileGridXOffset;
-        maxY = Numerics.ceilDiv((maxY - tileGridYOffset), tileWidth) * 
tileHeight + tileGridYOffset;
+        maxX = ((maxX - tileGridXOffset) / tileWidth  + 1) * tileWidth  + 
tileGridXOffset;  // Exclusive.
+        maxY = ((maxY - tileGridYOffset) / tileHeight + 1) * tileHeight + 
tileGridYOffset;
         bounds = new Rectangle(minX, minY,
-                Math.toIntExact(maxX - minX + 1),
-                Math.toIntExact(maxY - minY + 1));
+                Math.toIntExact(maxX - minX),
+                Math.toIntExact(maxY - minY));
         /*
          * Values of (minTileX, minTileY) computed above will cause 
`ResampledImage.getTileGridOffset()`
          * to return the exact same value than 
`destination.getTileGridOffset()`. This is a requirement
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java 
b/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java
index bb33057a0f..0185e50ae6 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java
@@ -1203,11 +1203,15 @@ public class ImageProcessor implements Cloneable {
                 fillValues              = this.fillValues;
                 positionalAccuracyHints = this.positionalAccuracyHints;
             }
+            final WritableRenderedImage destination = layout.getDestination();
             final SampleModel rsm = layout.createCompatibleSampleModel(source, 
bounds);
             final var image = new ResampledImage(source, rsm, 
layout.getMinTile(), bounds, toSource,
                                                  interpolation, fillValues, 
positionalAccuracyHints);
-            image.setDestination(layout.getDestination());
+            image.setDestination(destination);
             resampled = unique(image);
+            if (destination != null) {
+                return resampled;           // Preserve the color model of the 
destination.
+            }
             break;
         }
         /*
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ObservableImage.java
 
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ObservableImage.java
index e5319541cf..04942d510a 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ObservableImage.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ObservableImage.java
@@ -277,7 +277,8 @@ public class ObservableImage extends BufferedImage {
         }
         fireTileUpdate(count, true);
         try {
-            super.setData(data);
+            // Do not use super.setData(…) because it does not handle 
correctly the float and double types.
+            getRaster().setRect(0, 0, data);
         } finally {
             synchronized (this) {
                 // Similar to `releaseWritableTile(…)` but without throwing 
exception.

Reply via email to