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 eb2a41f  Rename `ReshapedImage.image` as `source` and add more 
verifications of image consistency.
eb2a41f is described below

commit eb2a41f164976c2ce58d72bdaa0a221a81188a01
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Fri Feb 11 16:17:05 2022 +0100

    Rename `ReshapedImage.image` as `source` and add more verifications of 
image consistency.
---
 .../apache/sis/coverage/grid/GridCoverage2D.java   |  6 +-
 .../apache/sis/coverage/grid/ReshapedImage.java    | 77 ++++++++++++----------
 .../sis/internal/coverage/j2d/TiledImage.java      | 23 +++++--
 .../coverage/grid/ResampledGridCoverageTest.java   |  2 +-
 4 files changed, 63 insertions(+), 45 deletions(-)

diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage2D.java
 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage2D.java
index 80e895b..3eaf685 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage2D.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage2D.java
@@ -279,9 +279,9 @@ public class GridCoverage2D extends GridCoverage {
      */
     private static RenderedImage unwrapIfSameSize(RenderedImage data) {
         if (data instanceof ReshapedImage) {
-            final RenderedImage image = ((ReshapedImage) data).image;
-            if (image.getWidth() == data.getWidth() && image.getHeight() == 
data.getHeight()) {
-                data = image;
+            final RenderedImage source = ((ReshapedImage) data).source;
+            if (source.getWidth() == data.getWidth() && source.getHeight() == 
data.getHeight()) {
+                data = source;
             }
         }
         return data;
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ReshapedImage.java
 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ReshapedImage.java
index c0efa44..9500a8e 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ReshapedImage.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ReshapedImage.java
@@ -42,7 +42,7 @@ import static java.lang.Math.toIntExact;
  *
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.2
  * @since   1.1
  * @module
  */
@@ -50,7 +50,7 @@ final class ReshapedImage extends PlanarImage {
     /**
      * The image to translate.
      */
-    final RenderedImage image;
+    final RenderedImage source;
 
     /**
      * Value to add for converting a column index from the coordinate system 
of the wrapped image
@@ -67,7 +67,7 @@ final class ReshapedImage extends PlanarImage {
     private final int offsetY;
 
     /**
-     * The image size in pixels. May be smaller than {@link #image} size by an 
integer amount of tiles.
+     * The image size in pixels. May be smaller than {@link #source} size by 
an integer amount of tiles.
      */
     private final int width, height;
 
@@ -87,29 +87,29 @@ final class ReshapedImage extends PlanarImage {
      * Creates a new image with the same data than the given image but located 
at different coordinates.
      * In addition, this constructor can reduce the number of tiles.
      *
-     * @param  image  the image to move.
-     * @param  xmin   minimal <var>x</var> coordinate of the requested region, 
inclusive.
-     * @param  ymin   minimal <var>y</var> coordinate of the requested region, 
inclusive.
-     * @param  xmax   maximal <var>x</var> coordinate of the requested region, 
inclusive.
-     * @param  ymax   maximal <var>y</var> coordinate of the requested region, 
inclusive.
+     * @param  source  the image to move.
+     * @param  xmin    minimal <var>x</var> coordinate of the requested 
region, inclusive.
+     * @param  ymin    minimal <var>y</var> coordinate of the requested 
region, inclusive.
+     * @param  xmax    maximal <var>x</var> coordinate of the requested 
region, inclusive.
+     * @param  ymax    maximal <var>y</var> coordinate of the requested 
region, inclusive.
      * @throws ArithmeticException if image indices would overflow 32 bits 
integer capacity.
      */
-    ReshapedImage(final RenderedImage image, final long xmin, final long ymin, 
final long xmax, final long ymax) {
-        this.image = image;
+    ReshapedImage(final RenderedImage source, final long xmin, final long 
ymin, final long xmax, final long ymax) {
+        this.source = source;
         /*
          * Compute indices of all tiles to retain in this image. All local 
fields are `long` in order to force
          * 64-bits integer arithmetic, because may have temporary 32-bits 
integer overflow during intermediate
          * calculation but still have a final result representable as an 
`int`. The use of `min` and `max` are
          * paranoiac safety against long integer overflow; real clamping will 
be done later.
          */
-        final long lowerX = image.getMinX();                        // Lower 
source index (inclusive)
-        final long lowerY = image.getMinY();
-        final long upperX = image.getWidth()  + lowerX;             // Upper 
image index (exclusive).
-        final long upperY = image.getHeight() + lowerY;
-        final long tw     = image.getTileWidth();
-        final long th     = image.getTileHeight();
-        final long xo     = image.getTileGridXOffset();
-        final long yo     = image.getTileGridYOffset();
+        final long lowerX = source.getMinX();                       // Lower 
source index (inclusive)
+        final long lowerY = source.getMinY();
+        final long upperX = source.getWidth()  + lowerX;            // Upper 
image index (exclusive).
+        final long upperY = source.getHeight() + lowerY;
+        final long tw     = source.getTileWidth();
+        final long th     = source.getTileHeight();
+        final long xo     = source.getTileGridXOffset();
+        final long yo     = source.getTileGridYOffset();
         final long minTX  = floorDiv(max(lowerX, xmin) - xo, tw);   // Indices 
of the first tile to retain.
         final long minTY  = floorDiv(max(lowerY, ymin) - yo, th);
         final long maxTX  = floorDiv(min(upperX, xmax) - xo, tw);   // Indices 
of the last tile to retain (inclusive).
@@ -143,7 +143,7 @@ final class ReshapedImage extends PlanarImage {
      */
     final boolean isIdentity() {
         // The use of >= is a paranoiac check, but the > case should never 
happen actually.
-        return offsetX == 0 && offsetY == 0 && width >= image.getWidth() && 
height >= image.getHeight();
+        return offsetX == 0 && offsetY == 0 && width >= source.getWidth() && 
height >= source.getHeight();
     }
 
     /**
@@ -153,19 +153,19 @@ final class ReshapedImage extends PlanarImage {
     @SuppressWarnings("UseOfObsoleteCollectionType")
     public Vector<RenderedImage> getSources() {
         final Vector<RenderedImage> sources = new Vector<>(1);
-        sources.add(image);
+        sources.add(source);
         return sources;
     }
 
     /**
      * Delegates to the wrapped image with no change.
      */
-    @Override public Object      getProperty(String name) {return 
image.getProperty(name);}
-    @Override public String[]    getPropertyNames()       {return 
image.getPropertyNames();}
-    @Override public ColorModel  getColorModel()          {return 
image.getColorModel();}
-    @Override public SampleModel getSampleModel()         {return 
image.getSampleModel();}
-    @Override public int         getTileWidth()           {return 
image.getTileWidth();}
-    @Override public int         getTileHeight()          {return 
image.getTileHeight();}
+    @Override public Object      getProperty(String name) {return 
source.getProperty(name);}
+    @Override public String[]    getPropertyNames()       {return 
source.getPropertyNames();}
+    @Override public ColorModel  getColorModel()          {return 
source.getColorModel();}
+    @Override public SampleModel getSampleModel()         {return 
source.getSampleModel();}
+    @Override public int         getTileWidth()           {return 
source.getTileWidth();}
+    @Override public int         getTileHeight()          {return 
source.getTileHeight();}
 
     /**
      * Returns properties determined at construction time.
@@ -183,7 +183,7 @@ final class ReshapedImage extends PlanarImage {
      */
     @Override
     public int getTileGridXOffset() {
-        return addExact(image.getTileGridXOffset(), offsetX);
+        return addExact(source.getTileGridXOffset(), offsetX);
     }
 
     /**
@@ -192,7 +192,7 @@ final class ReshapedImage extends PlanarImage {
      */
     @Override
     public int getTileGridYOffset() {
-        return addExact(image.getTileGridYOffset(), offsetY);
+        return addExact(source.getTileGridYOffset(), offsetY);
     }
 
     /**
@@ -214,7 +214,7 @@ final class ReshapedImage extends PlanarImage {
      */
     @Override
     public Raster getTile(final int tileX, final int tileY) {
-        return offset(image.getTile(tileX, tileY));
+        return offset(source.getTile(tileX, tileY));
     }
 
     /**
@@ -230,8 +230,8 @@ final class ReshapedImage extends PlanarImage {
          * in case some implementations provide an optimized method. Otherwise
          * ask only the sub-region covered by this image.
          */
-        if (width >= image.getWidth() && height >= image.getHeight()) {
-            return offset(image.getData());
+        if (width >= source.getWidth() && height >= source.getHeight()) {
+            return offset(source.getData());
         }
         return copyData(new Rectangle(minX, minY, width, height));
     }
@@ -256,7 +256,7 @@ final class ReshapedImage extends PlanarImage {
     private Raster copyData(final Rectangle aoi) {
         aoi.x = subtractExact(aoi.x, offsetX);      // Convert coordinate from 
this image to wrapped image.
         aoi.y = subtractExact(aoi.y, offsetY);
-        final Raster data = image.getData(aoi);
+        final Raster data = source.getData(aoi);
         return data.createTranslatedChild(addExact(data.getMinX(), offsetX),
                                           addExact(data.getMinY(), offsetY));
     }
@@ -278,7 +278,7 @@ final class ReshapedImage extends PlanarImage {
         } else {
             data = null;
         }
-        data = image.copyData(data);
+        data = source.copyData(data);
         if (data.getWritableParent() == raster) {
             return raster;
         }
@@ -290,12 +290,17 @@ final class ReshapedImage extends PlanarImage {
      * Verifies whether image layout information are consistent.
      * This method first checks the properties modified by this class.
      * If okay, then this method completes the check with all verifications
-     * {@linkplain ComputedImage#verify() documented in parent class}
+     * {@linkplain ComputedImage#verify() documented in parent class}.
      */
     @Override
     public String verify() {
-        if (getMinX() != image.getMinX() + (minTileX - image.getMinTileX()) * 
getTileWidth()  + offsetX) return "minX";
-        if (getMinY() != image.getMinY() + (minTileY - image.getMinTileY()) * 
getTileHeight() + offsetY) return "minY";
+        if (source instanceof PlanarImage) {
+            // If the source has inconsistency, the reshaped image will have 
problem as well.
+            final String inconsistency = ((PlanarImage) source).verify();
+            if (inconsistency != null) return "source." + inconsistency;
+        }
+        if (getMinX() != source.getMinX() + (minTileX - source.getMinTileX()) 
* getTileWidth()  + offsetX) return "minX";
+        if (getMinY() != source.getMinY() + (minTileY - source.getMinTileY()) 
* getTileHeight() + offsetY) return "minY";
         if (getTileGridXOffset() != super.getTileGridXOffset()) return 
"tileGridXOffset";
         if (getTileGridYOffset() != super.getTileGridYOffset()) return 
"tileGridYOffset";
         return super.verify();      // "width" and "height" properties should 
be checked last.
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/TiledImage.java
 
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/TiledImage.java
index 19976bf..4d6d65b 100644
--- 
a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/TiledImage.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/TiledImage.java
@@ -38,7 +38,7 @@ import org.apache.sis.util.resources.Errors;
  *
  * @author  Rémi Maréchal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.2
  * @since   1.1
  * @module
  */
@@ -114,14 +114,27 @@ public class TiledImage extends PlanarImage {
         final int numXTiles  = getNumXTiles();
         final int tileWidth  = getTileWidth();
         final int tileHeight = getTileHeight();
+        final SampleModel sm = getSampleModel();
         for (int i=0; i < tiles.length; i++) {
             final Raster tile = tiles[i];
             final int tx = i % numXTiles;
             final int ty = i / numXTiles;
-            if (tile.getWidth()  != tileWidth)              return 
property(tx, ty, "width");
-            if (tile.getHeight() != tileHeight)             return 
property(tx, ty, "height");
-            if (tile.getMinX()   != tileWidth  * tx + minX) return 
property(tx, ty, "x");
-            if (tile.getMinY()   != tileHeight * ty + minY) return 
property(tx, ty, "y");
+            final int ox = minX + tx * tileWidth;
+            final int oy = minY + ty * tileHeight;
+            if (tile.getMinX() != ox) return property(tx, ty, "x");
+            if (tile.getMinY() != oy) return property(tx, ty, "y");
+            /*
+             * We accept two conventions for the raster size: either it is 
exactly equal to the tile size
+             * (possibly extending belong the image size), or either it is 
exactly equal to the tile size
+             * clipped to image size.
+             */
+            final int tw = tile.getWidth();
+            final int th = tile.getHeight();
+            if (tw != tileWidth || th != tileHeight) {
+                if (tw != Math.min(tileWidth,  width  - ox)) return 
property(tx, ty, "width");
+                if (th != Math.min(tileHeight, height - oy)) return 
property(tx, ty, "height");
+            }
+            if (!sm.equals(tile.getSampleModel())) return property(tx, ty, 
"sampleModel");
         }
         return super.verify();      // "width" and "height" properties should 
be checked last.
     }
diff --git 
a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/ResampledGridCoverageTest.java
 
b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/ResampledGridCoverageTest.java
index aa186ef..e635fe4 100644
--- 
a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/ResampledGridCoverageTest.java
+++ 
b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/ResampledGridCoverageTest.java
@@ -321,7 +321,7 @@ public final strictfp class ResampledGridCoverageTest 
extends TestCase {
     private static RenderedImage unwrap(final RenderedImage image) {
         assertEquals("GridCoverage.render(null) should have their origin at 
(0,0).", 0, image.getMinX());
         assertEquals("GridCoverage.render(null) should have their origin at 
(0,0).", 0, image.getMinY());
-        return (image instanceof ReshapedImage) ? ((ReshapedImage) 
image).image : image;
+        return (image instanceof ReshapedImage) ? ((ReshapedImage) 
image).source : image;
     }
 
     /**

Reply via email to