This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits 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 f3fd0c2c60 Be more conservative with files without georeferencing 
information. Instead of inferring a "grid to CRS" far from the reading process, 
use a new `getGridGeometryWithDefaults()` method.
f3fd0c2c60 is described below

commit f3fd0c2c600b32aba4810e4621cda789b7dc5aee
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Jul 10 18:14:43 2026 +0200

    Be more conservative with files without georeferencing information.
    Instead of inferring a "grid to CRS" far from the reading process,
    use a new `getGridGeometryWithDefaults()` method.
---
 .../sis/coverage/grid/BufferedGridCoverage.java    |  5 +-
 .../apache/sis/coverage/grid/DefaultEvaluator.java | 26 +++-----
 .../apache/sis/coverage/grid/GridCoverage2D.java   |  5 +-
 .../org/apache/sis/map/coverage/RenderingData.java |  5 +-
 .../sis/storage/geotiff/ImageFileDirectory.java    |  8 +--
 .../apache/sis/storage/base/StoreUtilities.java    | 55 ++++++++++++++++-
 .../apache/sis/storage/tiling/ImageTileMatrix.java |  6 +-
 .../apache/sis/storage/tiling/TileReadEvent.java   | 16 +----
 .../storage/tiling/TiledGridCoverageResource.java  | 71 +++++++++++++++++++---
 .../org/apache/sis/util/resources/Vocabulary.java  |  5 ++
 .../sis/util/resources/Vocabulary.properties       |  1 +
 .../sis/util/resources/Vocabulary_fr.properties    |  1 +
 .../apache/sis/storage/geoheif/ImageResource.java  | 14 +++--
 .../org/apache/sis/storage/geoheif/Pyramid.java    |  6 +-
 .../apache/sis/gui/coverage/CoverageCanvas.java    |  9 ++-
 .../apache/sis/gui/coverage/CoverageExplorer.java  |  3 +-
 .../main/org/apache/sis/gui/coverage/GridView.java |  3 +-
 .../org/apache/sis/gui/coverage/ImageRequest.java  | 43 -------------
 .../sis/gui/coverage/StyledRenderingData.java      |  3 +-
 .../org/apache/sis/gui/map/ValuesFormatter.java    |  5 --
 .../org/apache/sis/gui/map/ValuesUnderCursor.java  | 21 +------
 .../gui/referencing/RecentReferenceSystems.java    |  1 -
 .../main/org/apache/sis/gui/referencing/Utils.java | 11 ----
 23 files changed, 169 insertions(+), 154 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/BufferedGridCoverage.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/BufferedGridCoverage.java
index 24177c6f92..20827f4fb9 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/BufferedGridCoverage.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/BufferedGridCoverage.java
@@ -335,10 +335,13 @@ public class BufferedGridCoverage extends GridCoverage {
          * Returns a sequence of double values for a given point in the 
coverage.
          * The CRS of the given point may be any coordinate reference system,
          * or {@code null} for the same CRS as the coverage.
+         *
+         * @throws IncompleteGridGeometryException if the "grid to 
<abbr>CRS</abbr>" transform is missing.
+         * @throws CannotEvaluateException if the values cannot be computed 
for another reason.
          */
         @Override
         @SuppressWarnings("ReturnOfCollectionOrArrayField")
-        public double[] apply(final DirectPosition point) throws 
CannotEvaluateException {
+        public double[] apply(final DirectPosition point) {
             final int pos;
             try {
                 final double[] gridCoords = toGridPosition(point);
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DefaultEvaluator.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DefaultEvaluator.java
index 19a7f10f1b..68e43e647f 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DefaultEvaluator.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/DefaultEvaluator.java
@@ -325,13 +325,14 @@ abstract class DefaultEvaluator implements 
GridCoverage.Evaluator {
      *
      * @param  point  the position where to evaluate.
      * @return the sample values at the specified point, or {@code null} if 
the point is outside the coverage.
+     * @throws IncompleteGridGeometryException if the "grid to 
<abbr>CRS</abbr>" transform is missing.
      * @throws PointOutsideCoverageException if the evaluation failed because 
the input point
      *         has invalid coordinates and the {@link #isNullIfOutside()} flag 
is {@code false}.
      * @throws CannotEvaluateException if the values cannot be computed for 
another reason.
      */
     @Override
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
-    public double[] apply(final DirectPosition point) throws 
CannotEvaluateException {
+    public double[] apply(final DirectPosition point) {
         try {
             final double[] gridCoords = toGridPosition(point);
             final IntFunction<PointOutsideCoverageException> ifOutside;
@@ -361,6 +362,7 @@ abstract class DefaultEvaluator implements 
GridCoverage.Evaluator {
      * @param  points   the positions where to evaluate.
      * @param  parallel {@code true} for a parallel stream, or {@code false} 
for a sequential stream.
      * @return the sample values at the specified positions.
+     * @throws IncompleteGridGeometryException if the "grid to 
<abbr>CRS</abbr>" transform is missing.
      */
     @Override
     public Stream<double[]> stream(final Collection<? extends DirectPosition> 
points, final boolean parallel) {
@@ -379,6 +381,7 @@ abstract class DefaultEvaluator implements 
GridCoverage.Evaluator {
      *
      * @param  points  the positions where to evaluate.
      * @return iterator over the sample values at the specified positions.
+     * @throws IncompleteGridGeometryException if the "grid to 
<abbr>CRS</abbr>" transform is missing.
      * @throws FactoryException if an exception occurred while search an 
operation to the <abbr>CRS</abbr> of a point.
      * @throws TransformException if a coordinate transformation failed.
      */
@@ -498,6 +501,7 @@ abstract class DefaultEvaluator implements 
GridCoverage.Evaluator {
      *
      * @param  point  the geospatial position.
      * @return the given position converted to grid coordinates (possibly out 
of grid bounds).
+     * @throws IncompleteGridGeometryException if the "grid to 
<abbr>CRS</abbr>" transform is missing.
      * @throws FactoryException if no operation is found form given point CRS 
to coverage CRS.
      * @throws TransformException if the given position cannot be converted.
      */
@@ -617,22 +621,6 @@ next:   while (--numPoints >= 0) {
         }
     }
 
-    /**
-     * Returns the grid to <abbr>CRS</abbr> transform or infers a transform 
from the resolution.
-     *
-     * @param  grid  the grid geometry.
-     * @return the transform from grid coordinates to <abbr>CRS</abbr> 
coordinates.
-     * @throws IncompleteGridGeometryException if there is neither transform 
or resolution.
-     */
-    private static MathTransform getOfInferGridToCRS(final GridGeometry grid) {
-        if (!grid.isDefined(GridGeometry.GRID_TO_CRS) && 
grid.isDefined(GridGeometry.RESOLUTION)) {
-            return MathTransforms.concatenate(
-                    MathTransforms.uniformTranslation(grid.getDimension(), 
0.5),
-                    MathTransforms.scale(grid.getResolution(false)));
-        }
-        return grid.getGridToCRS(PixelInCell.CELL_CENTER);
-    }
-
     /**
      * Recomputes the {@link #inputToGrid} field if the <abbr>CRS</abbr> 
changed.
      * This method should be invoked when the transform has not yet been 
computed
@@ -645,6 +633,7 @@ next:   while (--numPoints >= 0) {
      *
      * @param  crs  the new value to assign to {@link #inputCRS}. Can be 
{@code null}.
      * @return the new {@link #inputToGrid} value.
+     * @throws IncompleteGridGeometryException if the "grid to 
<abbr>CRS</abbr>" transform is missing.
      */
     private synchronized MathTransform getInputToGrid(final 
CoordinateReferenceSystem crs)
             throws FactoryException, NoninvertibleTransformException
@@ -654,7 +643,7 @@ next:   while (--numPoints >= 0) {
         }
         final GridCoverage coverage = getCoverage();
         final GridGeometry gridGeometry = coverage.getGridGeometry();
-        MathTransform gridToCRS = getOfInferGridToCRS(gridGeometry);
+        MathTransform gridToCRS = 
gridGeometry.getGridToCRS(PixelInCell.CELL_CENTER);
         MathTransform crsToGrid = 
TranslatedTransform.resolveNaN(gridToCRS.inverse(), gridGeometry);
         if (crs != null) {
             final CoordinateReferenceSystem stepCRS = 
coverage.getCoordinateReferenceSystem();
@@ -737,6 +726,7 @@ next:   while (--numPoints >= 0) {
      *
      * @param  point  the point which is outside the grid.
      * @return the exception to throw
+     * @throws IncompleteGridGeometryException if the "grid to 
<abbr>CRS</abbr>" transform is missing.
      */
     final synchronized PointOutsideCoverageException 
pointOutsideCoverage(final DirectPosition point) {
         String details = null;
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverage2D.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverage2D.java
index 72cab7f656..54696787f7 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverage2D.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverage2D.java
@@ -528,9 +528,12 @@ public class GridCoverage2D extends GridCoverage {
          * Returns a sequence of double values for a given point in the 
coverage.
          * The CRS of the given point may be any coordinate reference system,
          * or {@code null} for the same CRS as the coverage.
+         *
+         * @throws IncompleteGridGeometryException if the "grid to 
<abbr>CRS</abbr>" transform is missing.
+         * @throws CannotEvaluateException if the values cannot be computed 
for another reason.
          */
         @Override
-        public double[] apply(final DirectPosition point) throws 
CannotEvaluateException {
+        public double[] apply(final DirectPosition point) {
             try {
                 final double[] gridCoords = toGridPosition(point);
                 final double cx = gridCoords[xDimension];
diff --git 
a/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/coverage/RenderingData.java
 
b/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/coverage/RenderingData.java
index abeb7a695d..68b9c18187 100644
--- 
a/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/coverage/RenderingData.java
+++ 
b/endorsed/src/org.apache.sis.portrayal/main/org/apache/sis/map/coverage/RenderingData.java
@@ -324,8 +324,11 @@ public class RenderingData implements CloneAccess {
     @SuppressWarnings("AssignmentToCollectionOrArrayFieldFromParameter")
     public final void setImageSpace(GridGeometry domain, final 
List<SampleDimension> ranges, final int[] xyDims) {
         /*
-         * If the grid geometry does not define a "grid to CRS" transform, set 
it to an identity transform.
+         * If the grid geometry does not define a "grid to CRS" transform, use 
an approximate transform inferred
+         * from the resolution. If the resolution is not available neither, 
fallback to an identity transform.
          * We do that because this class needs a complete `GridGeometry` as 
much as possible.
+         * We accept the risk that the transform may be wrong because it will 
be used for rendering to screen,
+         * in which case we hope that the user will see if an image is not at 
the correct location.
          */
         if (domain != null && !domain.isDefined(GridGeometry.GRID_TO_CRS)
                            &&  domain.isDefined(GridGeometry.EXTENT))
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
index b3063a1a72..e35b1a01e9 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
@@ -1498,9 +1498,6 @@ final class ImageFileDirectory extends DataCube {
                 if (source != null) {
                     domain = reader.store.customizer.customize(source, domain);
                 }
-                if (overviews != null) {
-                    domain = domain.defaultToGridCRS(null);
-                }
                 gridGeometry = domain;
             }
             return domain;
@@ -2036,9 +2033,6 @@ final class ImageFileDirectory extends DataCube {
     final void setOverviews(final List<ImageFileDirectory> images) throws 
DataStoreException {
         if (!images.isEmpty()) {
             overviews = new Overviews(images);
-            if (gridGeometry != null) {
-                gridGeometry = gridGeometry.defaultToGridCRS(null);
-            }
         }
     }
 
@@ -2125,7 +2119,7 @@ final class ImageFileDirectory extends DataCube {
                          * which is the image at full resolution. Information 
about bands are also copied if compatible.
                          */
                         if (image.referencing == null) {
-                            final GridGeometry geometry = getGridGeometry();
+                            final GridGeometry geometry = 
getGridGeometryWithDefaults();
                             final GridExtent fullExtent = geometry.getExtent();
                             final int dimension = fullExtent.getDimension();
                             final var scales    = new double[dimension];
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/StoreUtilities.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/StoreUtilities.java
index f4975053e4..7dd7880725 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/StoreUtilities.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/StoreUtilities.java
@@ -16,20 +16,20 @@
  */
 package org.apache.sis.storage.base;
 
+import java.util.Locale;
 import java.util.Optional;
 import java.util.stream.Stream;
 import java.util.logging.Filter;
 import java.util.logging.Logger;
 import java.util.logging.LogRecord;
+import org.opengis.util.NameSpace;
 import org.opengis.util.GenericName;
 import org.opengis.geometry.Envelope;
 import org.opengis.metadata.Metadata;
+import org.opengis.metadata.Identifier;
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.metadata.identification.Identification;
 import org.opengis.metadata.identification.DataIdentification;
-import org.apache.sis.util.CharSequences;
-import org.apache.sis.util.Classes;
-import org.apache.sis.util.ArraysExt;
 import org.apache.sis.storage.FeatureSet;
 import org.apache.sis.storage.Resource;
 import org.apache.sis.storage.DataStore;
@@ -37,15 +37,24 @@ import org.apache.sis.storage.DataStores;
 import org.apache.sis.storage.DataStoreProvider;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.WritableFeatureSet;
+import org.apache.sis.storage.GridCoverageResource;
 import org.apache.sis.storage.UnsupportedStorageException;
 import org.apache.sis.storage.event.StoreListeners;
 import org.apache.sis.storage.internal.Resources;
+import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.geometry.GeneralEnvelope;
 import org.apache.sis.metadata.internal.shared.Identifiers;
 import org.apache.sis.metadata.iso.extent.Extents;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.referencing.ImmutableIdentifier;
 import org.apache.sis.system.Configuration;
 import org.apache.sis.system.Modules;
+import org.apache.sis.util.ArraysExt;
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.Classes;
+import org.apache.sis.util.Localized;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Vocabulary;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.feature.Feature;
@@ -191,6 +200,46 @@ public final class StoreUtilities {
         return title;
     }
 
+    /**
+     * Returns a name for the grid <abbr>CRS</abbr> derived from the resource 
identifier.
+     *
+     * @param  resource  resource from which to get the identifier, or {@code 
null} if none.
+     * @param  domain    grid geometry of the resource or coverage loaded from 
the resource.
+     * @return name derived from the identifier which can be used for the grid 
<abbr>CRS</abbr>.
+     * @throws DataStoreException if an error occurred while fetching the 
identifier.
+     */
+    public static Identifier gridCrsName(final GridCoverageResource resource, 
final GridGeometry domain)
+            throws DataStoreException
+    {
+        if (resource != null) {
+            final GenericName name = resource.getIdentifier().orElse(null);
+            if (name != null) {
+                if (name instanceof Identifier) {
+                    return (Identifier) name;
+                }
+                /*
+                 * Do not use `NamedIdentifier` because we want the full name 
as identifier code.
+                 * By contrast, `NamedIdentifier` takes only the tip (because 
it is better suited
+                 * to datum names or projection parameter names). In the 
context of resource, the
+                 * tip alone is not sufficient because it is often only an 
image number in a file
+                 * specified by the name component before the tip.
+                 */
+                String codeSpace = null;
+                final NameSpace scope = name.scope();
+                if (scope != null && !scope.isGlobal()) {
+                    codeSpace = scope.name().toString();
+                }
+                Locale locale = (resource instanceof Localized) ? ((Localized) 
resource).getLocale() : null;
+                String code = 
Vocabulary.forLocale(locale).getString(Vocabulary.Keys.GridOf_1, 
name.toString());
+                return new ImmutableIdentifier(null, codeSpace, code);
+            }
+        }
+        return (domain.isDefined(GridGeometry.GRID_TO_CRS)
+                        ? CommonCRS.Engineering.GRID.datum()    // "Unknown 
grid"
+                        : CommonCRS.Engineering.GRID.crs())     // "Cell 
indices"
+                .getName();
+    }
+
     /**
      * Returns the spatiotemporal envelope of the given metadata.
      * This method computes the union of all {@link GeographicBoundingBox} 
instances
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ImageTileMatrix.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ImageTileMatrix.java
index 278ef89ced..c2a8f213fd 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ImageTileMatrix.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ImageTileMatrix.java
@@ -189,7 +189,7 @@ final class ImageTileMatrix implements TileMatrix {
         this.processor  = processor;
         this.resource   = resource;
         this.tileSize   = resource.getTileSize();
-        final GridGeometry cellGrid = resource.getGridGeometry();
+        final GridGeometry cellGrid = resource.getGridGeometryWithDefaults();
         final GridExtent extent     = cellGrid.getExtent();
         final int        dimension  = extent.getDimension();
         final long[]     tileCount  = new long[dimension];
@@ -239,7 +239,7 @@ final class ImageTileMatrix implements TileMatrix {
     @Override
     public double[] getResolution() {
         try {
-            return resource.getGridGeometry().getResolution(false);
+            return resource.getGridGeometryWithDefaults().getResolution(false);
         } catch (DataStoreException e) {
             throw new BackingStoreException(e);
         }
@@ -272,7 +272,7 @@ final class ImageTileMatrix implements TileMatrix {
      * @throws DataStoreException if an error occurred while fecthing the grid 
geometry.
      */
     final GridExtent getResourceExtent() throws DataStoreException {
-        return resource.getGridGeometry().getExtent();
+        return resource.getGridGeometryWithDefaults().getExtent();
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileReadEvent.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileReadEvent.java
index 2c4970d6ce..ec4132250f 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileReadEvent.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TileReadEvent.java
@@ -117,20 +117,6 @@ public final class TileReadEvent extends StoreEvent {
             offsetY = aoi.getLow(yDimension);
         }
 
-        /**
-         * Returns the grid to <abbr>CRS</abbr> transform or infers a 
transform from the resolution.
-         *
-         * @param  grid  the grid geometry.
-         * @return the transform from grid coordinates to <abbr>CRS</abbr> 
coordinates.
-         * @throws IncompleteGridGeometryException if there is neither 
transform or resolution.
-         */
-        private static MathTransform getOfInferGridToCRS(final GridGeometry 
grid) {
-            if (!grid.isDefined(GridGeometry.GRID_TO_CRS) && 
grid.isDefined(GridGeometry.RESOLUTION)) {
-                return MathTransforms.scale(grid.getResolution(false));
-            }
-            return grid.getGridToCRS(PixelInCell.CELL_CORNER);
-        }
-
         /**
          * Returns the transform from pixel coordinates to real world 
coordinates in the given <abbr>CRS</abbr>.
          *
@@ -145,7 +131,7 @@ public final class TileReadEvent extends StoreEvent {
             if (crsToObjective == null || 
!CRS.equivalent(crsToObjective.getTargetCRS(), crs)) try {
                 crsToObjective = sliceGeometry.createChangeOfCRS(crs);
                 MathTransform tr = MathTransforms.translation(offsetX, 
offsetY);
-                tr = MathTransforms.concatenate(tr, 
getOfInferGridToCRS(sliceGeometry));
+                tr = MathTransforms.concatenate(tr, 
sliceGeometry.getGridToCRS(PixelInCell.CELL_CORNER));
                 tr = MathTransforms.concatenate(tr, 
crsToObjective.getMathTransform());
                 imageToObjective = MathTransforms.bidimensional(tr);
                 this.crsToObjective = crsToObjective;   // Store only after 
the rest was successful.
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java
index 5234c3ec1b..ea67f7dfcb 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java
@@ -52,6 +52,7 @@ import org.apache.sis.storage.AbstractGridCoverageResource;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.RasterLoadingStrategy;
 import org.apache.sis.storage.event.StoreListeners;
+import org.apache.sis.storage.base.StoreUtilities;
 import org.apache.sis.measure.NumberRange;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.ArgumentChecks;
@@ -161,6 +162,18 @@ public abstract class TiledGridCoverageResource extends 
AbstractGridCoverageReso
      */
     private Collection<TileMatrixSet> tileMatrixSets;
 
+    /**
+     * Grid geometry with the addition of a default resolution if the latter 
was missing.
+     * In the normal situation where this {@code TiledGridCoverageResource} is 
georeferenced,
+     * the value of this field should be identical to the value returned by 
{@link #getGridGeometry()}.
+     * However, if the latter has no resolution, no transform and no 
<abbr>CRS</abbr>, then this field
+     * is set to a grid geometry with a resolution of 1. The corresponding 
"grid to <abbr>CRS</abbr>"
+     * (an identity transform) is added only if an engineering 
<abbr>CRS</abbr> for the grid can be built.
+     *
+     * @see #getGridGeometryWithDefaults()
+     */
+    private GridGeometry gridGeometryWithDefaults;
+
     /**
      * Zero-based index of the pyramid level of this grid coverage resource.
      * This is not used directly by this class, but this information is stored
@@ -483,7 +496,9 @@ check:  if (dataType.isInteger()) {
                 @Override public double[] get(final int level) {
                     try {
                         TiledGridCoverageResource c = 
pyramid.forPyramidLevel(level);
-                        if (c != null) return 
c.getGridGeometry().getResolution(false);
+                        if (c != null) {
+                            return 
c.getGridGeometryWithDefaults().getResolution(false);
+                        }
                     } catch (DataStoreException e) {
                         throw new BackingStoreException(e);
                     }
@@ -662,13 +677,13 @@ check:  if (dataType.isInteger()) {
             /*
              * Normally, the number of dimensions of `tileSize` should be 
equal to the number of dimensions
              * of the grid geometry (determined by its `GridExtent`). However, 
we are tolerant to situation
-             * where the `TiledGridCoverageResource` is a two dimensional 
image associated to a 3-dimensional CRS.
+             * where `TiledGridCoverageResource` extent is two dimensional but 
the CRS is three-dimensional.
              * This is not recommended, but can happen with GeoTIFF for 
example. What to do with the extra
              * dimension is unclear (the GeoTIFF specification itself said 
nothing), so we just ignore it.
              */
             final int[] tileSize = getTileSize();
             final int dimension = tileSize.length;          // May be shorter 
than the grid geometry dimension.
-            GridGeometry gridGeometry = getGridGeometry();
+            GridGeometry gridGeometry = getGridGeometryWithDefaults();
             if ((domain == null || domain.getDimension() == dimension) && 
gridGeometry.getDimension() > dimension) {
                 gridGeometry = 
gridGeometry.selectDimensions(ArraysExt.range(0, dimension));
             }
@@ -772,6 +787,9 @@ check:  if (dataType.isInteger()) {
             if (colorsForBandSubset == null) {
                 colorsForBandSubset = rangeIndices.select(getColorModel(null));
             }
+            /*
+             * If the domain has no "grid to CRS" transform, set a default 
value
+             */
             this.domain              = domain;
             this.ranges              = bands;
             this.includedBands       = includedBands;
@@ -941,7 +959,7 @@ check:  if (dataType.isInteger()) {
                     bestFit = c;
                     level++;
                     if (request != null) {
-                        final double[] resolution = 
c.getGridGeometry().getResolution(true);
+                        final double[] resolution = 
c.getGridGeometryWithDefaults().getResolution(true);
                         if (!(request[xDimension] < resolution[xDimension] ||  
// Use `!` for catching NaN.
                               request[yDimension] < resolution[yDimension])) 
break;
                     }
@@ -976,6 +994,7 @@ check:  if (dataType.isInteger()) {
         final GridCoverage loaded;
         final boolean preload;
         final long startTime;
+        final GridGeometry gridGeometry;
         synchronized (getSynchronizationLock()) {
             // Note: `loadingStrategy` may still be null if unitialized.
             preload = (loadingStrategy == null || loadingStrategy == 
RasterLoadingStrategy.AT_READ_TIME);
@@ -991,11 +1010,15 @@ check:  if (dataType.isInteger()) {
                  * We apply it anyway in case the coverage geometry is not 
what was announced.
                  * This condition is also necessary if `loadingStrategy` has 
not been initialized.
                  */
-                if (!preload || coverage.getGridGeometry().getDimension() != 
BIDIMENSIONAL) {
+                if (!preload) {
+                    return coverage;
+                }
+                gridGeometry = coverage.getGridGeometry();
+                if (gridGeometry.getDimension() != BIDIMENSIONAL) {
                     return coverage;
                 }
                 final RenderedImage image = coverage.render(null);
-                loaded = new GridCoverage2D(coverage.getGridGeometry(), 
coverage.getSampleDimensions(), image);
+                loaded = new GridCoverage2D(gridGeometry, 
coverage.getSampleDimensions(), image);
             } catch (RuntimeException e) {
                 /*
                  * The `coverage.render(…)` implementation may have wrapped 
the checked `DataStoreException`
@@ -1017,7 +1040,7 @@ check:  if (dataType.isInteger()) {
                 throw canNotRead(listeners.getSourceName(), domain, cause);
             }
         }
-        logReadOperation(coverage.getContentPath(null), 
coverage.getGridGeometry(), startTime);
+        logReadOperation(coverage.getContentPath(null), gridGeometry, 
startTime);
         return loaded;
     }
 
@@ -1165,8 +1188,8 @@ check:  if (dataType.isInteger()) {
      * @see #getTileMatrixSets()
      */
     protected List<Pyramid> getPyramids() throws DataStoreException {
-        final GridGeometry gridGeometry = getGridGeometry();
-        if (gridGeometry.isDefined(GridGeometry.EXTENT | 
GridGeometry.GRID_TO_CRS | GridGeometry.RESOLUTION)) {
+        final GridGeometry gridGeometry = getGridGeometryWithDefaults();
+        if (gridGeometry.isDefined(GridGeometry.EXTENT | 
GridGeometry.RESOLUTION)) {
             if (isTiled(gridGeometry.getExtent())) {
                 return List.of(new Pyramid() {
                     @Override public OptionalInt numberOfLevels() {return 
OptionalInt.of(1);}
@@ -1179,6 +1202,35 @@ check:  if (dataType.isInteger()) {
         return List.of();
     }
 
+    /**
+     * Returns the grid geometry with missing properties defaulting to the 
properties of a grid <abbr>CRS</abbr>.
+     * This method usually returns {@link #getGridGeometry()} unchanged, 
except in the following rare circumstance:
+     * if the grid geometry has no resolution, no "grid to <abbr>CRS</abbr>" 
transform and no <abbr>CRS</abbr>,
+     * then this method returns a grid geometry with the resolution set to 1,
+     * <i>i.e.</i> the resolution is defined as one unit of grid cell.
+     *
+     * <p>This method can be invoked for computing the grid geometry of {@link 
TiledGridCoverage}.
+     * This is particularly important in the context of pyramids because the 
levels are selected
+     * on the basis of their resolution. Implementations of {@link 
Pyramid#forPyramidLevel(int)}
+     * are encouraged to use this method for the base level, and only that 
level.</p>
+     *
+     * @return grid geometry potentially completed with the addition of 
resolution and engineering <abbr>CRS</abbr>.
+     * @throws DataStoreException if an error occurred while reading 
definitions from the underlying data store.
+     */
+    protected GridGeometry getGridGeometryWithDefaults() throws 
DataStoreException {
+        synchronized (getSynchronizationLock()) {
+            GridGeometry gridGeometry = gridGeometryWithDefaults;
+            if (gridGeometry == null) {
+                gridGeometry = getGridGeometry();
+                if (!gridGeometry.isDefined(GridGeometry.GRID_TO_CRS)) {
+                    gridGeometry = 
gridGeometry.defaultToGridCRS(StoreUtilities.gridCrsName(this, gridGeometry));
+                }
+                gridGeometryWithDefaults = gridGeometry;
+            }
+            return gridGeometry;
+        }
+    }
+
     /**
      * Description of a {@code TileMatrixSet} implemented as an image pyramid.
      * This interface is used by the default implementation of {@link 
#getTileMatrixSets()}.
@@ -1286,6 +1338,7 @@ check:  if (dataType.isInteger()) {
          * @throws DataStoreException if an error occurred while creating the 
resource.
          *
          * @see #getAvailableResolutions()
+         * @see #getGridGeometryWithDefaults()
          */
         TiledGridCoverageResource forPyramidLevel(int level) throws 
DataStoreException;
 
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
index fb6c66cbed..2b15588fec 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.java
@@ -618,6 +618,11 @@ public class Vocabulary extends IndexedResourceBundle {
          */
         public static final short GridExtent = 97;
 
+        /**
+         * Grid of “{0}”
+         */
+        public static final short GridOf_1 = 290;
+
         /**
          * Height
          */
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
index 63f1c17305..867e72e9f4 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary.properties
@@ -125,6 +125,7 @@ Gray                    = Gray
 Grayscale               = Grayscale
 Green                   = Green
 GridExtent              = Grid extent
+GridOf_1                = Grid of \u201c{0}\u201d
 Height                  = Height
 Identifier              = Identifier
 Identifiers             = Identifiers
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
index acf2328f98..c5240d9ee1 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Vocabulary_fr.properties
@@ -132,6 +132,7 @@ Gray                    = Gris
 Grayscale               = Niveaux de gris
 Green                   = Vert
 GridExtent              = \u00c9tendue de la grille
+GridOf_1                = Grille de \u00ab\u202f{0}\u202f\u00bb
 Height                  = Hauteur
 Identifier              = Identifiant
 Identifiers             = Identifiants
diff --git 
a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java
 
b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java
index 70b2dea484..2334217b95 100644
--- 
a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java
+++ 
b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java
@@ -37,7 +37,6 @@ import org.opengis.metadata.Metadata;
 import org.opengis.util.GenericName;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
-import org.apache.sis.referencing.operation.transform.LinearTransform;
 import org.apache.sis.coverage.SampleDimension;
 import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridGeometry;
@@ -184,12 +183,17 @@ final class ImageResource extends 
TiledGridCoverageResource implements StoreReso
 
     /**
      * Declares that this image is the pyramid level of the given base grid.
+     * If the given {@code base} argument is null, then the base grid is this 
grid.
      * This method does nothing if this image already has its own "grid to 
<abbr>CRS</abbr>" transform.
      *
-     * @param  base  grid geometry of the pyramid level at the finest 
resolution.
+     * @param  base  grid geometry of the pyramid level at the finest 
resolution, or {@code null}.
+     * @return the base grid, which is {@code base} if that argument was 
non-null.
      * @throws TransformException if an error occurred while deriving the 
"grid to <abbr>CRS</abbr>" transform.
      */
-    final void setPyramidLevelOf(final GridGeometry base) throws 
TransformException {
+    final GridGeometry setPyramidLevelOf(GridGeometry base) throws 
DataStoreException, TransformException {
+        if (base == null) {
+            return gridGeometry = getGridGeometryWithDefaults();
+        }
         if (!gridGeometry.isDefined(GridGeometry.GRID_TO_CRS)) {
             final GridExtent levelExtent = gridGeometry.getExtent();
             final GridExtent baseExtent  = base.getExtent();
@@ -197,9 +201,9 @@ final class ImageResource extends TiledGridCoverageResource 
implements StoreReso
             for (int i = 0; i < factors.length; i++) {
                 factors[i] = Numerics.divide(baseExtent.getSize(i), 
levelExtent.getSize(i));
             }
-            final LinearTransform toLevel = MathTransforms.scale(factors);
-            gridGeometry = toLevel.isIdentity() ? base : new 
GridGeometry(base, levelExtent, toLevel);
+            gridGeometry = new GridGeometry(base, levelExtent, 
MathTransforms.scale(factors));
         }
+        return base;
     }
 
     /**
diff --git 
a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Pyramid.java
 
b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Pyramid.java
index 8596c14d7c..c94776a786 100644
--- 
a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Pyramid.java
+++ 
b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Pyramid.java
@@ -80,7 +80,7 @@ final class Pyramid extends TiledGridCoverageResource 
implements TiledGridCovera
      * @throws TransformException if an error occurred while deriving a "grid 
to <abbr>CRS</abbr>" transform.
      */
     Pyramid(final GeoHeifStore store, final GenericName name, final 
ImagePyramid pyramid, final ImageResource[] levels)
-            throws TransformException
+            throws DataStoreException, TransformException
     {
         super(store);
         this.name = name;
@@ -88,9 +88,9 @@ final class Pyramid extends TiledGridCoverageResource 
implements TiledGridCovera
         tileSizeY = pyramid.tileSizeY;
         this.levels = levels;
         Arrays.sort(levels, LEVEL_COMPARATOR);
-        final GridGeometry base = 
levels[0].getGridGeometry().defaultToGridCRS(null);
+        GridGeometry base = null;
         for (ImageResource level : levels) {
-            level.setPyramidLevelOf(base);
+            base = level.setPyramidLevelOf(base);
         }
     }
 
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
index 56bc9200e9..93a2e21a9a 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageCanvas.java
@@ -62,7 +62,6 @@ import org.opengis.metadata.Identifier;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.referencing.operation.transform.LinearTransform;
 import org.apache.sis.referencing.operation.matrix.AffineTransforms2D;
@@ -82,6 +81,7 @@ import org.apache.sis.image.processing.isoline.Isolines;
 import org.apache.sis.image.internal.shared.TileErrorHandler;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.GridCoverageResource;
+import org.apache.sis.storage.base.StoreUtilities;
 import org.apache.sis.storage.event.StoreListener;
 import org.apache.sis.storage.tiling.TileReadEvent;
 import org.apache.sis.gui.map.MapCanvas;
@@ -704,7 +704,7 @@ public class CoverageCanvas extends MapCanvasAWT {
                             ranges = resource.getSampleDimensions();
                             scales = 
Containers.peekFirst(resource.getAvailableResolutions());
                         }
-                        gridCrsName = ImageRequest.gridCrsName(resource, 
domain);
+                        gridCrsName = StoreUtilities.gridCrsName(resource, 
domain);
                         if (domain != null) {
                             /*
                              * The domain should never be null and should 
always be complete (including envelope).
@@ -715,8 +715,7 @@ public class CoverageCanvas extends MapCanvasAWT {
                             if (!domain.isDefined(GridGeometry.ENVELOPE) && 
domain.isDefined(GridGeometry.EXTENT)) {
                                 final GridExtent extent = domain.getExtent();
                                 final int dimension = extent.getDimension();
-                                domain = new GridGeometry(extent, 
PixelInCell.CELL_CORNER, MathTransforms.identity(dimension),
-                                                (dimension == BIDIMENSIONAL) ? 
CommonCRS.Engineering.DISPLAY.crs() : null);
+                                domain = new GridGeometry(extent, 
PixelInCell.CELL_CORNER, MathTransforms.identity(dimension), null);
                             }
                             /*
                              * Compute the maximum zoom out. Usually, we want 
to show the full image.
@@ -892,7 +891,7 @@ public class CoverageCanvas extends MapCanvasAWT {
      * If this method returns an artificial name, it would cause an unusable 
menu
      * item to appear in the menu that offers different <abbr>CRS</abbr>.</p>
      *
-     * @see ImageRequest#gridCrsName(GridCoverageResource, GridGeometry)
+     * @see StoreUtilities#gridCrsName(GridCoverageResource, GridGeometry)
      */
     final Identifier gridCrsName() {
         return data.gridCrsName;
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
index 755d734d0e..f473d80867 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/CoverageExplorer.java
@@ -37,6 +37,7 @@ import org.opengis.metadata.Identifier;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.GridCoverageResource;
+import org.apache.sis.storage.base.StoreUtilities;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.portrayal.RenderException;
@@ -622,7 +623,7 @@ public class CoverageExplorer extends Widget {
                 Identifier name = gridName;
                 if (name == null && resource != null) try {
                     // May happen if `CoverageCanvas.setNewSource(…)` did not 
had the time to be executed.
-                    name = ImageRequest.gridCrsName(resource, gg);
+                    name = StoreUtilities.gridCrsName(resource, gg);
                 } catch (DataStoreException e) {
                     // Declare `setResource` as the public method invoking 
(indirectly) this method.
                     Logging.recoverableException(LOGGER, 
CoverageExplorer.class, "setResource", e);
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
index 1898ed4929..319e5c6b6f 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
@@ -44,6 +44,7 @@ import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.GridCoverageResource;
+import org.apache.sis.storage.base.StoreUtilities;
 import org.apache.sis.gui.internal.BackgroundThreads;
 import org.apache.sis.gui.internal.LogHandler;
 import org.apache.sis.gui.internal.ExceptionReporter;
@@ -384,7 +385,7 @@ public class GridView extends Control {
                     return null;
                 }
                 final GridGeometry gg = coverage.getGridGeometry();
-                gridCrsName = ImageRequest.gridCrsName(request.resource, gg);
+                gridCrsName = StoreUtilities.gridCrsName(request.resource, gg);
                 GridExtent slice = request.slice;
                 final GridControls c = controls;
                 if (c != null) {
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java
index 29691a0d8e..f0bd415f54 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/ImageRequest.java
@@ -18,14 +18,9 @@ package org.apache.sis.gui.coverage;
 
 import java.util.Objects;
 import java.util.Optional;
-import org.opengis.util.NameSpace;
-import org.opengis.util.GenericName;
-import org.opengis.metadata.Identifier;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.coverage.grid.GridExtent;
-import org.apache.sis.referencing.CommonCRS;
-import org.apache.sis.referencing.ImmutableIdentifier;
 import org.apache.sis.storage.GridCoverageResource;
 import org.apache.sis.storage.DataStoreException;
 
@@ -169,44 +164,6 @@ public class ImageRequest {
         return Optional.ofNullable(coverage);
     }
 
-    /**
-     * Returns the name of the grid <abbr>CRS</abbr>, derived from the 
resource identifier.
-     *
-     * @param  resource  resource from which to get the identifier, or {@code 
null} if none.
-     * @param  domain    grid geometry of the resource or coverage loaded from 
the resource.
-     * @return name derived from the identifier which can be used for the grid 
<abbr>CRS</abbr>.
-     * @throws DataStoreException if an error occurred while fetching the 
identifier.
-     */
-    static Identifier gridCrsName(final GridCoverageResource resource, final 
GridGeometry domain)
-            throws DataStoreException
-    {
-        if (resource != null) {
-            final GenericName name = resource.getIdentifier().orElse(null);
-            if (name != null) {
-                if (name instanceof Identifier) {
-                    return (Identifier) name;
-                }
-                /*
-                 * Do not use `NamedIdentifier` because we want the full name 
as identifier code.
-                 * By contrast, `NamedIdentifier` takes only the tip (because 
it is better suited
-                 * to datum names or projection parameter names). In the 
context of resource, the
-                 * tip alone is not sufficient because it is often only an 
image number in a file
-                 * specified by the name component before the tip.
-                 */
-                String codeSpace = null;
-                final NameSpace scope = name.scope();
-                if (scope != null && !scope.isGlobal()) {
-                    codeSpace = scope.name().toString();
-                }
-                return new ImmutableIdentifier(null, codeSpace, 
name.toString());
-            }
-        }
-        return (domain.isDefined(GridGeometry.GRID_TO_CRS)
-                        ? CommonCRS.Engineering.GRID.datum()    // "Unknown 
grid"
-                        : CommonCRS.Engineering.GRID.crs())     // "Cell 
indices"
-                .getName();
-    }
-
     /**
      * Returns the desired grid extent and resolution, or an empty value for 
reading the full domain.
      * This is the {@code domain} argument specified to the following 
constructor:
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java
index 7f37fc85b8..70b6743946 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/StyledRenderingData.java
@@ -24,6 +24,7 @@ import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.GridCoverageResource;
+import org.apache.sis.storage.base.StoreUtilities;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.coverage.grid.PixelInCell;
 import org.apache.sis.image.ErrorHandler;
@@ -45,7 +46,7 @@ final class StyledRenderingData extends RenderingData {
     /**
      * Name of the grid <abbr>CRS</abbr>, derived from the resource identifier.
      *
-     * @see ImageRequest#gridCrsName(GridCoverageResource, GridGeometry)
+     * @see StoreUtilities#gridCrsName(GridCoverageResource, GridGeometry)
      */
     Identifier gridCrsName;
 
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/ValuesFormatter.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/ValuesFormatter.java
index bf1e702a10..fbab35500b 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/ValuesFormatter.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/ValuesFormatter.java
@@ -383,11 +383,6 @@ final class ValuesFormatter extends 
ValuesUnderCursor.Formatter {
         @Override public double getCoordinate(final int dimension) {
             return coordinates[dimension];
         }
-
-        /** Returns the CRS of this position, or {@code null} if unspecified. 
*/
-        @Override public CoordinateReferenceSystem 
getCoordinateReferenceSystem() {
-            return isIgnoreable(crs) ? null : crs;
-        }
     }
 
     /**
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/ValuesUnderCursor.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/ValuesUnderCursor.java
index d8dbd3d7da..c8e7493788 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/ValuesUnderCursor.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/ValuesUnderCursor.java
@@ -20,8 +20,6 @@ import java.util.concurrent.atomic.AtomicReference;
 import javafx.scene.control.Menu;
 import javafx.application.Platform;
 import org.opengis.geometry.DirectPosition;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.gui.coverage.CoverageCanvas;
 import org.apache.sis.coverage.grid.GridCoverage;
 import org.apache.sis.geometry.GeneralDirectPosition;
@@ -212,24 +210,7 @@ public abstract class ValuesUnderCursor {
          * @return a copy of the given position, or {@code null} if the 
position should be considered outside.
          */
         DirectPosition copy(final DirectPosition point) {
-            final var p = new GeneralDirectPosition(point);
-            if (isIgnoreable(point.getCoordinateReferenceSystem())) {
-                p.setCoordinateReferenceSystem(null);
-            }
-            return p;
-        }
-
-        /**
-         * Returns {@code true} if the given reference system should be 
ignored.
-         * We need to ignore "computer display" because this is a synthetic 
<abbr>CRS</abbr>
-         * added when the source coverage does not define its own 
<abbr>CRS</abbr>.
-         * If we do not remove that <abbr>CRS</abbr>, an exception will be 
thrown
-         * when the coverage will try to convert that <abbr>CRS</abbr>.
-         *
-         * @see org.apache.sis.gui.referencing.Utils#isIgnoreable
-         */
-        static boolean isIgnoreable(final CoordinateReferenceSystem system) {
-            return CommonCRS.Engineering.DISPLAY.datumUsedBy(system);
+            return new GeneralDirectPosition(point);
         }
 
         /**
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
index 700a1ba091..264615f9af 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/RecentReferenceSystems.java
@@ -652,7 +652,6 @@ public class RecentReferenceSystems {
             final var system = (ReferenceSystem) systemsOrCodes.get(i);
             if (system != OTHER && (filter == null || filter.test(system))) {
                 if (i < NUM_CORE_ITEMS || Utils.intersects(domain, system)) {
-                    if (Utils.isIgnoreable(system)) continue;   // Ignore 
"Computer display" CRS.
                     systems.add(system);
                     if (systems.size() >= NUM_SHOWN_ITEMS) break;
                 }
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/Utils.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/Utils.java
index e7bad96f34..8d1d70187c 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/Utils.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/Utils.java
@@ -20,7 +20,6 @@ import org.opengis.geometry.Envelope;
 import org.opengis.util.FactoryException;
 import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.referencing.ReferenceSystem;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.CRSAuthorityFactory;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
@@ -28,7 +27,6 @@ import org.apache.sis.metadata.iso.extent.Extents;
 import org.apache.sis.geometry.ImmutableEnvelope;
 import org.apache.sis.util.internal.shared.Constants;
 import org.apache.sis.util.logging.Logging;
-import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.referencing.CRS;
 import static org.apache.sis.gui.internal.LogHandler.LOGGER;
 
@@ -98,13 +96,4 @@ final class Utils {
         }
         return conservative;
     }
-
-    /**
-     * Returns {@code true} if the given reference system should be ignored.
-     *
-     * @see 
org.apache.sis.gui.map.ValuesUnderCursor.Formatter#isIgnoreable(CoordinateReferenceSystem)
-     */
-    static boolean isIgnoreable(final ReferenceSystem system) {
-        return (system instanceof CoordinateReferenceSystem c) && 
CommonCRS.Engineering.DISPLAY.datumUsedBy(c);
-    }
 }

Reply via email to