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 f87196f3bd75e44a9df100e435e25b24dc892d7c
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Mon Nov 8 17:03:52 2021 +0100

    Fix `IndexOutOfBoundsException` when filling a tile having an origin other 
than (0,0).
    Fix the conditions for deciding when to return an empty tile or the 
existing tile.
---
 .../java/org/apache/sis/image/MaskedImage.java     | 34 +++++++++++++++-------
 .../sis/internal/coverage/j2d/FillValues.java      |  4 +--
 2 files changed, 25 insertions(+), 13 deletions(-)

diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/image/MaskedImage.java 
b/core/sis-feature/src/main/java/org/apache/sis/image/MaskedImage.java
index 63ec657..9654e14 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/MaskedImage.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/MaskedImage.java
@@ -257,10 +257,12 @@ final class MaskedImage extends SourceAlignedImage {
          */
         final Rectangle maskBounds = this.maskBounds;
         final LongBuffer mask = getMask().asLongBuffer();
+        final int xmax   = xmin + source.getTileWidth();
+        final int ymax   = ymin + source.getTileHeight();
+        final int xEnd   = Math.min(xmax, maskBounds.x + maskBounds.width);
+        final int yEnd   = Math.min(ymax, maskBounds.y + maskBounds.height);
         final int xStart = Math.max(xmin, maskBounds.x);
         final int yStart = Math.max(ymin, maskBounds.y);
-        final int xEnd   = Math.min(xmin + source.getTileWidth(),  
maskBounds.x + maskBounds.width);
-        final int yEnd   = Math.min(ymin + source.getTileHeight(), 
maskBounds.y + maskBounds.height);
         final int imax   = xEnd   - maskBounds.x;                   // Maximum 
x index in mask, exclusive.
         final int xoff   = xStart - maskBounds.x;
         Raster    data   = null;
@@ -367,17 +369,30 @@ final class MaskedImage extends SourceAlignedImage {
         }
         /*
          * The tile is fetched only if at least one pixel needs to be copied 
from the source tile.
-         * If the source tile is still null at this point, it means that 
target tile is fully empty.
-         * Note that the target tile may be non-null because it was an 
argument to this method.
+         * If the source tile is still null at this point, it means that 
masked region is fully empty.
+         * Note that the `target` variable may be non-null because it was an 
argument to this method.
          */
+        final boolean isFullTile = (xStart == xmin && yStart == ymin && xEnd 
== xmax && yEnd == ymax);
         if (data == null) {
-            return createEmptyTile(xmin, ymin);
+            if (isFullTile) {
+                return createEmptyTile(xmin, ymin);
+            }
+            data = source.getTile(tileX, tileY);
+            boolean clean = needCreate(tile, data);
+            if (clean) {
+                tile = createTile(tileX, tileY);
+                clean = fillValues.isFullyZero;
+            }
+            if (!clean) {
+                fillValues.fill(tile);
+            }
         }
         /*
          * If no bit from the `present` mask have been cleared, then it means 
that all pixels
          * have been copied. In such case the source tile can be returned 
directly.
          */
-        if (present == -1) {
+        assert data.getMinX() == xmin && data.getMinY() == ymin;
+        if (present == -1 && (isFullTile | maskInside)) {
             return data;
         }
         /*
@@ -385,11 +400,8 @@ final class MaskedImage extends SourceAlignedImage {
          * there is some pixels that we need to copy here.
          */
         if (maskInside) {
-            final int width  = tile.getWidth();
-                  int height = tile.getHeight();
-            final int xmax   = xmin + width;
-            final int ymax   = ymin + height;
-            height -= (yStart - ymin) + (ymax - yEnd);
+            final int width  = xmax - xmin;
+            final int height = yEnd - yStart;
 complete:   for (int border = 0; ; border++) {
                 final int start, span;
                 switch (border) {
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/FillValues.java
 
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/FillValues.java
index f620ad1..1533717 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/FillValues.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/FillValues.java
@@ -156,14 +156,14 @@ public final class FillValues {
         chunk = tile.getDataElements(xmin, y, chunkWidth, 1, null);
         final int ymax = y + tile.getHeight();
         final int xmax = xmin + width;
-        int x = chunkWidth;
+        int x = xmin + chunkWidth;
         do {
             int remaining;
             while ((remaining = xmax - x) > 0) {
                 tile.setDataElements(x, y, Math.min(chunkWidth, remaining), 1, 
chunk);
                 x += chunkWidth;
             }
-            x = 0;
+            x = xmin;
         } while (++y < ymax);
     }
 

Reply via email to