You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2022/02/11 19:44:28 UTC
[sis] branch geoapi-4.0 updated: Rename `ReshapedImage.image` as `source` and add more verifications of image consistency.
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 <ma...@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;
}
/**