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 8b4bd320fc Provide more metadata and better names for bands.
8b4bd320fc is described below

commit 8b4bd320fc7016b122d7a2ff98b0d789a8200b61
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Mon Apr 18 21:12:39 2022 +0200

    Provide more metadata and better names for bands.
---
 .../apache/sis/coverage/grid/GridCoverage2D.java   |  7 ++++-
 .../sis/internal/coverage/j2d/ImageUtilities.java  | 17 ++++-------
 .../internal/coverage/j2d/ImageUtilitiesTest.java  |  8 +++---
 .../apache/sis/internal/storage/image/Image.java   | 13 ++++++++-
 .../apache/sis/internal/storage/image/Store.java   |  7 +++++
 .../sis/internal/storage/image/StoreTest.java      | 33 +++++++++++++++++++++-
 6 files changed, 66 insertions(+), 19 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 3eaf6856b5..aa80d6a0e8 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
@@ -395,7 +395,12 @@ public class GridCoverage2D extends GridCoverage {
                                                            final RenderedImage 
data, final int numBands)
     {
         if (range == null) {
-            final short[] names = (data != null) ? 
ImageUtilities.bandNames(data) : ArraysExt.EMPTY_SHORT;
+            final short[] names;
+            if (data != null) {
+                names = ImageUtilities.bandNames(data.getColorModel(), 
data.getSampleModel());
+            } else {
+                names = ArraysExt.EMPTY_SHORT;
+            }
             final SampleDimension[] sd = new SampleDimension[numBands];
             final NameFactory factory = 
DefaultFactories.forBuildin(NameFactory.class);
             for (int i=0; i<numBands; i++) {
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 200d66ae5f..e95631f54c 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
@@ -264,26 +264,19 @@ public final class ImageUtilities extends Static {
     }
 
     /**
-     * Returns names of bands based on inspection of the color model.
+     * Returns names of bands based on inspection of the sample model and 
color model.
      * The bands are identified by {@link Vocabulary.Keys} values for
      * red, green, blue, cyan, magenta, yellow, black, gray, <i>etc</i>.
      * If a band can not be identified, then its corresponding value is 0.
      *
-     * @param  image  the image for which to get band names (can not be null).
+     * @param  cm  the color model for which to get band names, or {@code 
null} if unknown.
+     * @param  sm  the image sample model (can not be null).
      * @return {@link Vocabulary.Keys} identifying the bands.
      */
     @SuppressWarnings("fallthrough")
-    public static short[] bandNames(final RenderedImage image) {
-        final SampleModel sm = image.getSampleModel();
-        final int n;
-        if (sm != null) {
-            n = sm.getNumBands();
-        } else {
-            // Should not happen since SampleModel is essential, but we try to 
be robust.
-            n = image.getTile(image.getMinTileX(), 
image.getMinTileY()).getNumBands();
-        }
+    public static short[] bandNames(final ColorModel cm, final SampleModel sm) 
{
+        final int n = sm.getNumBands();
         final short[] keys = new short[n];
-        final ColorModel cm = image.getColorModel();
         if (cm instanceof IndexColorModel) {
             /*
              * IndexColorModel normally uses exactly one band. But SIS has a 
custom subtype which
diff --git 
a/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/ImageUtilitiesTest.java
 
b/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/ImageUtilitiesTest.java
index 458903b19f..eaa094f507 100644
--- 
a/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/ImageUtilitiesTest.java
+++ 
b/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/ImageUtilitiesTest.java
@@ -38,7 +38,7 @@ import static 
org.apache.sis.internal.util.Numerics.COMPARISON_THRESHOLD;
  * Tests {@link ImageUtilities}.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.2
  * @since   1.1
  * @module
  */
@@ -103,7 +103,7 @@ public final strictfp class ImageUtilitiesTest extends 
TestCase {
     }
 
     /**
-     * Verifies that {@link ImageUtilities#bandNames(RenderedImage)} returns 
expected band names.
+     * Verifies that {@link ImageUtilities#bandNames(ColorModel, SampleModel)} 
returns expected band names.
      *
      * @param  nde    expected number of data elements. This number 
categorizes the tests in this class.
      * @param  type   one of the {@link BufferedImage} {@code TYPE_*} 
constants.
@@ -111,8 +111,9 @@ public final strictfp class ImageUtilitiesTest extends 
TestCase {
      */
     private static void assertBandNamesEqual(final int nde, final int type, 
final short... names) {
         final BufferedImage image = new BufferedImage(1, 1, type);
+        final ColorModel cm = image.getColorModel();
         assertEquals("numDataElements", nde, 
image.getSampleModel().getNumDataElements());
-        assertArrayEquals("bandNames", names, ImageUtilities.bandNames(image));
+        assertArrayEquals("bandNames", names, ImageUtilities.bandNames(cm, 
image.getSampleModel()));
         /*
          * The following is more for testing our understanding of the way 
BufferedImage works.
          * We want to verify that no matter which BufferedImage.TYPE_* 
constant we used, values
@@ -120,7 +121,6 @@ public final strictfp class ImageUtilitiesTest extends 
TestCase {
          */
         image.getRaster().setPixel(0, 0, new int[] {10, 20, 30, 40});       // 
Always RGBA order for this test.
         final Object data = image.getRaster().getDataElements(0, 0, null);
-        final ColorModel cm = image.getColorModel();
         for (final short k : names) {
             final int expected, actual;
             switch (k) {
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Image.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Image.java
index c803dee70b..a212a1fe9e 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Image.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Image.java
@@ -26,6 +26,7 @@ import javax.imageio.ImageReader;
 import javax.imageio.ImageReadParam;
 import javax.imageio.ImageTypeSpecifier;
 import org.opengis.util.GenericName;
+import org.opengis.util.InternationalString;
 import org.apache.sis.image.ImageProcessor;
 import org.apache.sis.coverage.SampleDimension;
 import org.apache.sis.coverage.grid.GridCoverage;
@@ -40,7 +41,9 @@ import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.event.StoreListeners;
 import org.apache.sis.internal.storage.StoreResource;
 import org.apache.sis.internal.storage.RangeArgument;
+import org.apache.sis.internal.coverage.j2d.ImageUtilities;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
+import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.iso.Names;
 
@@ -150,13 +153,21 @@ class Image extends AbstractGridCoverageResource 
implements StoreResource {
                 final ImageTypeSpecifier type   = 
reader.getRawImageType(imageIndex);
                 final SampleDimension[]  bands  = new 
SampleDimension[type.getNumBands()];
                 final SampleDimension.Builder b = new 
SampleDimension.Builder();
+                final short[] names = 
ImageUtilities.bandNames(type.getColorModel(), type.getSampleModel());
                 for (int i=0; i<bands.length; i++) {
                     /*
                      * TODO: we could consider a mechanism similar to 
org.apache.sis.internal.geotiff.SchemaModifier
                      * if there is a need to customize the sample dimensions. 
`SchemaModifier` could become a shared
                      * public interface.
                      */
-                    bands[i] = b.setName(i + 1).build();
+                    final InternationalString name;
+                    final short k;
+                    if (i < names.length && (k = names[i]) != 0) {
+                        name = Vocabulary.formatInternational(k);
+                    } else {
+                        name = 
Vocabulary.formatInternational(Vocabulary.Keys.Band_1, i+1);
+                    }
+                    bands[i] = b.setName(name).build();
                     b.clear();
                 }
                 sampleDimensions = UnmodifiableArrayList.wrap(bands);
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java
index a19b90927b..a3ff6092b8 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java
@@ -35,6 +35,7 @@ import javax.imageio.stream.ImageInputStream;
 import org.opengis.metadata.Metadata;
 import org.opengis.metadata.maintenance.ScopeCode;
 import org.opengis.referencing.datum.PixelInCell;
+import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.coverage.grid.GridExtent;
 import org.apache.sis.coverage.grid.GridGeometry;
 import org.apache.sis.storage.Aggregate;
@@ -43,6 +44,7 @@ import org.apache.sis.storage.GridCoverageResource;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.DataStoreClosedException;
 import org.apache.sis.storage.DataStoreContentException;
+import org.apache.sis.storage.DataStoreReferencingException;
 import org.apache.sis.storage.UnsupportedStorageException;
 import org.apache.sis.internal.storage.Resources;
 import org.apache.sis.internal.storage.PRJDataStore;
@@ -364,11 +366,16 @@ loop:   for (int convention=0;; convention++) {
             builder.addFormatName(format);                          // Does 
nothing if `format` is null.
             builder.addResourceScope(ScopeCode.COVERAGE, null);
             builder.addSpatialRepresentation(null, 
getGridGeometry(MAIN_IMAGE), true);
+            if (gridGeometry.isDefined(GridGeometry.ENVELOPE)) {
+                builder.addExtent(gridGeometry.getEnvelope());
+            }
             addTitleOrIdentifier(builder);
             builder.setISOStandards(false);
             metadata = builder.buildAndFreeze();
         } catch (IOException e) {
             throw new DataStoreException(e);
+        } catch (TransformException e) {
+            throw new DataStoreReferencingException(e);
         }
         return metadata;
     }
diff --git 
a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/image/StoreTest.java
 
b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/image/StoreTest.java
index c23bfca33b..42feef4317 100644
--- 
a/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/image/StoreTest.java
+++ 
b/storage/sis-storage/src/test/java/org/apache/sis/internal/storage/image/StoreTest.java
@@ -16,6 +16,10 @@
  */
 package org.apache.sis.internal.storage.image;
 
+import java.io.IOException;
+import org.opengis.metadata.Metadata;
+import org.opengis.metadata.extent.GeographicBoundingBox;
+import org.opengis.metadata.identification.Identification;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.storage.ProbeResult;
@@ -23,6 +27,7 @@ import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
 import static org.junit.Assert.*;
+import static org.apache.sis.test.TestUtilities.getSingleton;
 
 
 /**
@@ -54,5 +59,31 @@ public final strictfp class StoreTest extends TestCase {
         assertEquals("image/png", r.getMimeType());
     }
 
-
+    /**
+     * Tests the metadata of the {@code "gradient.png"} file.
+     *
+     * @throws DataStoreException if an error occurred while reading the file.
+     * @throws IOException if an error occurred while creating the image 
reader instance.
+     */
+    @Test
+    public void testMetadata() throws DataStoreException, IOException {
+        try (Store store = new Store(null, testData())) {
+            assertEquals("gradient", store.getIdentifier().get().toString());
+            final Metadata metadata = store.getMetadata();
+            final Identification id = 
getSingleton(metadata.getIdentificationInfo());
+            final String format = 
getSingleton(id.getResourceFormats()).getFormatSpecificationCitation().getTitle().toString();
+            assertTrue(format, format.contains("PNG"));
+            assertEquals("WGS 84", 
getSingleton(metadata.getReferenceSystemInfo()).getName().getCode());
+            final GeographicBoundingBox bbox = (GeographicBoundingBox)
+                    
getSingleton(getSingleton(id.getExtents()).getGeographicElements());
+            assertEquals( -90, bbox.getSouthBoundLatitude(), STRICT);
+            assertEquals( +90, bbox.getNorthBoundLatitude(), STRICT);
+            assertEquals(-180, bbox.getWestBoundLongitude(), STRICT);
+            assertEquals(+180, bbox.getEastBoundLongitude(), STRICT);
+            /*
+             * Verify that the metadata is cached.
+             */
+            assertSame(metadata, store.getMetadata());
+        }
+    }
 }

Reply via email to