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 c910ee0 Fix erroneous tile indices when subsampling is larger than
tile size.
c910ee0 is described below
commit c910ee0db60f2b0b9a8bfedf9bb615c05581a687
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Oct 13 18:53:06 2021 +0200
Fix erroneous tile indices when subsampling is larger than tile size.
---
.../apache/sis/coverage/grid/GridDerivation.java | 7 +++++-
.../java/org/apache/sis/image/PixelIterator.java | 7 ++++--
.../sis/internal/storage/TiledGridCoverage.java | 25 +++++++++++++++++-----
.../apache/sis/internal/storage/package-info.java | 2 +-
4 files changed, 32 insertions(+), 9 deletions(-)
diff --git
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java
index 6d921de..35f1893 100644
---
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java
+++
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridDerivation.java
@@ -1261,8 +1261,13 @@ public class GridDerivation {
return 1;
}
if (chunkSize != null) {
+ /*
+ * If the coverage is divided in tiles (or "chunk" in
n-dimensional case), we want the subsampling
+ * to be a divisor of tile size. In the special case where the
subsampling is larger than tile size,
+ * we can remove an integer amount of tiles because tiles can be
fully skipped at read time.
+ */
final int size = chunkSize[dimension];
- final int r = subsampling % size;
+ final int r = subsampling % size; // Reduced subsampling
(with integer amont of tiles removed).
if (r > 1 && (size % r) != 0) {
final int[] divisors = MathFunctions.divisors(size);
final int i = ~Arrays.binarySearch(divisors, r);
diff --git
a/core/sis-feature/src/main/java/org/apache/sis/image/PixelIterator.java
b/core/sis-feature/src/main/java/org/apache/sis/image/PixelIterator.java
index 4724b5b..64f0f30 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/PixelIterator.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/PixelIterator.java
@@ -83,7 +83,7 @@ import static org.apache.sis.internal.util.Numerics.ceilDiv;
* @author Rémi Maréchal (Geomatys)
* @author Martin Desruisseaux (Geomatys)
* @author Johann Sorel (Geomatys)
- * @version 1.1
+ * @version 1.2
* @since 1.0
* @module
*/
@@ -723,7 +723,10 @@ public class PixelIterator {
releaseTile(); // Release
current writable raster, if any.
tileX = tx;
tileY = ty;
- if (fetchTile() > py || currentLowerX > px) { //
`fetchTile()` must be before `currentLowerX`.
+ int currentLowerY = fetchTile(); // Also
update `currentLowerX` field value.
+ if (currentLowerY > py || py >= currentUpperY ||
+ currentLowerX > px || px >= currentUpperX)
+ {
throw new
RasterFormatException(Resources.format(Resources.Keys.IncompatibleTile_2,
tileX, tileY));
}
}
diff --git
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/TiledGridCoverage.java
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/TiledGridCoverage.java
index 7bf8026..bf12aa3 100644
---
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/TiledGridCoverage.java
+++
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/TiledGridCoverage.java
@@ -62,7 +62,7 @@ import static org.apache.sis.internal.util.Numerics.ceilDiv;
* in order to avoid integer overflow.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.2
* @since 1.1
* @module
*/
@@ -460,7 +460,8 @@ public abstract class TiledGridCoverage extends
GridCoverage {
private final int[] tileUpper;
/**
- * Pixel coordinates to assign to the upper-left corner of the region
to read, ignoring subsampling.
+ * Pixel coordinates to assign to the upper-left corner of the region
to render, ignoring subsampling.
+ * This is the difference between the region requested by user and the
region which will be rendered.
*/
private final int[] offsetAOI;
@@ -570,11 +571,25 @@ public abstract class TiledGridCoverage extends
GridCoverage {
/**
* Returns the origin to assign to the tile at current iterator
position.
- * Note that if there is more than one tile, then the subsampling
should be
- * a divisor of tile size, otherwise a drift in pixel coordinates will
appear.
+ * Note that the subsampling should be a divisor of tile size,
+ * otherwise a drift in pixel coordinates will appear.
+ * There is two exceptions to this rule:
+ *
+ * <ul>
+ * <li>If image is untiled (i.e. there is only one tile),
+ * we allow to read a sub-region of the unique tile.</li>
+ * <li>If subsampling is larger than tile size.</li>
+ * </ul>
*/
final int getTileOrigin(final int dimension) {
- return floorDiv(tileOffsetAOI[dimension], subsampling[dimension]);
+ /*
+ * We really need `ceilDiv(…)` below, not `floorDiv(…)`. It makes
no difference in the usual
+ * case where the subsampling is a divisor of the tile size. But
if we are in the case where
+ * subsampling is larger than tile size, we need the `ceilDiv(…)`.
At first the results seem
+ * inconsistent, but after we discard the tiles where
`getRegionInsideTile(…)` returns false
+ * it become consistent.
+ */
+ return ceilDiv(tileOffsetAOI[dimension], subsampling[dimension]);
}
/**
diff --git
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java
index b072411..d07eeac 100644
---
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java
+++
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/package-info.java
@@ -25,7 +25,7 @@
*
* @author Martin Desruisseaux (Geomatys)
* @author Johann Sorel (Geomatys)
- * @version 1.1
+ * @version 1.2
* @since 0.4
* @module
*/