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 2023/04/08 16:38:07 UTC
[sis] 01/03: Make `getTileWidth()` and `getTileHeight()` methods final in `ComputedImage`. Add design notes in Javadoc for explaining some rational.
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 65c2a49846fd3aafb3d23415c923ed5f66a6b1f7
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Sat Apr 8 15:27:44 2023 +0200
Make `getTileWidth()` and `getTileHeight()` methods final in `ComputedImage`.
Add design notes in Javadoc for explaining some rational.
---
.../java/org/apache/sis/image/ComputedImage.java | 36 ++++++++++++----------
.../org/apache/sis/image/SourceAlignedImage.java | 8 ++---
.../sis/internal/coverage/j2d/ImageUtilities.java | 30 ++++++++++++++++++
3 files changed, 53 insertions(+), 21 deletions(-)
diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/ComputedImage.java b/core/sis-feature/src/main/java/org/apache/sis/image/ComputedImage.java
index 126fe58caf..c991a18cb4 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/ComputedImage.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/ComputedImage.java
@@ -43,6 +43,7 @@ import org.apache.sis.util.Exceptions;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.coverage.grid.GridExtent; // For javadoc
import org.apache.sis.internal.feature.Resources;
+import org.apache.sis.internal.coverage.j2d.ImageUtilities;
/**
@@ -401,37 +402,41 @@ public abstract class ComputedImage extends PlanarImage implements Disposable {
* @return the sample model of this image.
*/
@Override
- public SampleModel getSampleModel() {
+ public final SampleModel getSampleModel() {
return sampleModel;
}
/**
- * Returns the width of tiles in this image. The default implementation returns {@link SampleModel#getWidth()}.
+ * Returns the width of tiles in this image.
+ * In {@code ComputedImage} implementation, this is fixed to {@link SampleModel#getWidth()}.
*
- * <h4>Note</h4>
- * A raster can have a smaller width than its sample model, for example when a raster is a view over a subregion
- * of another raster. But this is not recommended in the particular case of this {@code ComputedImage} class,
- * because it would cause {@link #createTile(int, int)} to consume more memory than necessary.
+ * <h4>Design note</h4>
+ * In theory it is legal to have a tile width smaller than the sample model width,
+ * for example when a raster is a view over a subregion of another raster.
+ * But this is not allowed in {@code ComputedImage} class, because it would
+ * cause {@link #createTile(int, int)} to consume more memory than necessary.
*
* @return the width of this image in pixels.
*/
@Override
- public int getTileWidth() {
+ public final int getTileWidth() {
return sampleModel.getWidth();
}
/**
- * Returns the height of tiles in this image. The default implementation returns {@link SampleModel#getHeight()}.
+ * Returns the height of tiles in this image.
+ * In {@code ComputedImage} implementation, this is fixed to {@link SampleModel#getHeight()}.
*
- * <h4>Note</h4>
- * A raster can have a smaller height than its sample model, for example when a raster is a view over a subregion
- * of another raster. But this is not recommended in the particular case of this {@code ComputedImage} class,
- * because it would cause {@link #createTile(int, int)} to consume more memory than necessary.
+ * <h4>Design note</h4>
+ * In theory it is legal to have a tile height smaller than the sample model height,
+ * for example when a raster is a view over a subregion of another raster.
+ * But this is not allowed in {@code ComputedImage} class, because it would
+ * cause {@link #createTile(int, int)} to consume more memory than necessary.
*
* @return the height of this image in pixels.
*/
@Override
- public int getTileHeight() {
+ public final int getTileHeight() {
return sampleModel.getHeight();
}
@@ -588,9 +593,8 @@ public abstract class ComputedImage extends PlanarImage implements Disposable {
* @return initially empty tile for the given indices (cannot be null).
*/
protected WritableRaster createTile(final int tileX, final int tileY) {
- // A temporary `int` overflow may occur before the final addition.
- final int x = Math.toIntExact((((long) tileX) - getMinTileX()) * getTileWidth() + getMinX());
- final int y = Math.toIntExact((((long) tileY) - getMinTileY()) * getTileHeight() + getMinY());
+ final int x = ImageUtilities.tileToPixelX(this, tileX);
+ final int y = ImageUtilities.tileToPixelY(this, tileY);
return WritableRaster.createWritableRaster(sampleModel, new Point(x,y));
}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/SourceAlignedImage.java b/core/sis-feature/src/main/java/org/apache/sis/image/SourceAlignedImage.java
index 608c3a3c7e..35df3ce8c6 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/SourceAlignedImage.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/SourceAlignedImage.java
@@ -33,10 +33,10 @@ import org.apache.sis.util.Workaround;
* Tiles in this image have the same size than tiles in the source image.
* See {@link ComputedImage} javadoc for more information about tile computation.
*
- * <div class="note"><b>Relationship with other classes</b><br>
+ * <h2>Relationship with other classes</h2>
* This class is similar to {@link ImageAdapter} except that it extends {@link ComputedImage}
* and does not forward {@link #getTile(int, int)}, {@link #getData()} and other data methods
- * to the source image.</div>
+ * to the source image.
*
* <h2>Sub-classing</h2>
* Subclasses need to implement at least the {@link #computeTile(int, int, WritableRaster)} method.
@@ -46,7 +46,7 @@ import org.apache.sis.util.Workaround;
* The {@link #equals(Object)} and {@link #hashCode()} methods should also be overridden.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.3
+ * @version 1.4
* @since 1.1
*/
abstract class SourceAlignedImage extends ComputedImage {
@@ -182,8 +182,6 @@ abstract class SourceAlignedImage extends ComputedImage {
@Override public final int getMinTileY() {return getSource().getMinTileY();}
@Override public final int getNumXTiles() {return getSource().getNumXTiles();}
@Override public final int getNumYTiles() {return getSource().getNumYTiles();}
- @Override public final int getTileWidth() {return getSource().getTileWidth();}
- @Override public final int getTileHeight() {return getSource().getTileHeight();}
@Override public final int getTileGridXOffset() {return getSource().getTileGridXOffset();}
@Override public final int getTileGridYOffset() {return getSource().getTileGridYOffset();}
diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ImageUtilities.java b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ImageUtilities.java
index 8b6bdbb63c..9c0280ba60 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ImageUtilities.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/j2d/ImageUtilities.java
@@ -486,9 +486,16 @@ public final class ImageUtilities extends Static {
/**
* Converts a <var>x</var> pixel coordinates to a tile index.
*
+ * <h4>Implementation note</h4>
+ * This method performs its calculation using <cite>tile grid offset</cite> instead of minimum coordinate
+ * values because the former does not assume that image coordinates start at the beginning of first tile.
+ * In practice it would be risky to have image {@code minX} different than first tile {@code minX},
+ * but Apache SIS tries to handle the most general cases when possible.
+ *
* @param image the image containing tiles.
* @param x the pixel coordinate for which to get tile index.
* @return tile index for the given pixel coordinate.
+ * @throws ArithmeticException if the result overflows 32 bits integer.
*/
public static int pixelToTileX(final RenderedImage image, final int x) {
return toIntExact(floorDiv((x - (long) image.getTileGridXOffset()), image.getTileWidth()));
@@ -496,10 +503,12 @@ public final class ImageUtilities extends Static {
/**
* Converts a <var>y</var> pixel coordinates to a tile index.
+ * See {@link #pixelToTileX(RenderedImage, int)} for an implementation note.
*
* @param image the image containing tiles.
* @param y the pixel coordinate for which to get tile index.
* @return tile index for the given pixel coordinate.
+ * @throws ArithmeticException if the result overflows 32 bits integer.
*/
public static int pixelToTileY(final RenderedImage image, final int y) {
return toIntExact(floorDiv((y - (long) image.getTileGridYOffset()), image.getTileHeight()));
@@ -509,9 +518,16 @@ public final class ImageUtilities extends Static {
* Converts a tile column index to smallest <var>x</var> pixel coordinate inside the tile.
* The returned value is a coordinate of the pixel in upper-left corner.
*
+ * <h4>Implementation note</h4>
+ * This method performs its calculation using <cite>tile grid offset</cite> instead of minimum coordinate
+ * values because the former does not assume that image coordinates start at the beginning of first tile.
+ * In practice it would be risky to have image {@code minX} different than first tile {@code minX},
+ * but Apache SIS tries to handle the most general cases when possible.
+ *
* @param image the image containing tiles.
* @param tileX the tile index for which to get pixel coordinate.
* @return smallest <var>x</var> pixel coordinate inside the tile.
+ * @throws ArithmeticException if the result overflows 32 bits integer.
*/
public static int tileToPixelX(final RenderedImage image, final int tileX) {
// Following `long` arithmetic never overflows even if all values are `Integer.MAX_VALUE`.
@@ -521,10 +537,12 @@ public final class ImageUtilities extends Static {
/**
* Converts a tile row index to smallest <var>y</var> pixel coordinate inside the tile.
* The returned value is a coordinate of the pixel in upper-left corner.
+ * See {@link #tileToPixelX(RenderedImage, int)} for an implementation note.
*
* @param image the image containing tiles.
* @param tileY the tile index for which to get pixel coordinate.
* @return smallest <var>y</var> pixel coordinate inside the tile.
+ * @throws ArithmeticException if the result overflows 32 bits integer.
*/
public static int tileToPixelY(final RenderedImage image, final int tileY) {
return toIntExact(multiplyFull(tileY, image.getTileHeight()) + image.getTileGridYOffset());
@@ -534,9 +552,15 @@ public final class ImageUtilities extends Static {
* Converts pixel coordinates to pixel indices.
* This method does <strong>not</strong> clip the rectangle to image bounds.
*
+ * <h4>Implementation note</h4>
+ * This method performs its calculation using <cite>tile grid offset</cite> instead of minimum coordinate
+ * values because the former does not assume that image coordinates start at the beginning of first tile.
+ * The intend is to be consistent with {@link #pixelToTileX(RenderedImage, int)}.
+ *
* @param image the image containing tiles.
* @param pixels the pixel coordinates for which to get tile indices.
* @return tile indices that fully contain the pixel coordinates.
+ * @throws ArithmeticException if the result overflows 32 bits integer.
*/
public static Rectangle pixelsToTiles(final RenderedImage image, final Rectangle pixels) {
final Rectangle r = new Rectangle();
@@ -562,9 +586,15 @@ public final class ImageUtilities extends Static {
* Tiles will be fully included in the returned range of pixel indices.
* This method does <strong>not</strong> clip the rectangle to image bounds.
*
+ * <h4>Implementation note</h4>
+ * This method performs its calculation using <cite>tile grid offset</cite> instead of minimum coordinate
+ * values because the former does not assume that image coordinates start at the beginning of first tile.
+ * The intend is to be consistent with {@link #tileToPixelX(RenderedImage, int)}.
+ *
* @param image the image containing tiles.
* @param tiles the tile indices for which to get pixel coordinates.
* @return pixel coordinates that fully contain the tiles.
+ * @throws ArithmeticException if the result overflows 32 bits integer.
*/
public static Rectangle tilesToPixels(final RenderedImage image, final Rectangle tiles) {
final Rectangle r = new Rectangle();