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

commit 3f1071a42afa76a5efb0616a22c72ff7f9f2f929
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Oct 8 14:29:18 2026 +0200

    Show also TIFF color map as tabular data.
---
 SECURITY.md                                        |   5 +-
 .../sis/storage/geotiff/ImageFileDirectory.java    |   6 +-
 .../apache/sis/storage/geotiff/NativeMetadata.java |   5 +
 .../sis/storage/geotiff/reader/ColorMap.java       | 110 +++++++++++++++++++++
 .../sis/storage/geotiff/reader/ModelTiePoints.java |   4 +-
 .../sis/util/internal/shared/TableRowList.java     |   5 +-
 .../org/apache/sis/gui/internal/PropertyView.java  |   3 +-
 7 files changed, 129 insertions(+), 9 deletions(-)

diff --git a/SECURITY.md b/SECURITY.md
index 8c0b34aaed..af25017911 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,7 +1,8 @@
 # Security Policy
 
 Apache SIS does not store credentials (user logins or passwords).
-Logging may contain URLs used for connection to databases and paths to data 
files.
+JDBC URLs for connecting to databases or paths to opened data files
+may appear in log records or (only if the JavaFX application is used) in Java 
preferences.
 Prerequisites for running Apache SIS safely are listed below.
 
 
@@ -24,7 +25,7 @@ Some file formats can contain references (usually as URLs) to 
auxiliary files:
 * `PARAMETERFILE` elements in Well Known Text (WKT),
 * `xlink:href` attributes in Geographic Markup Language (GML),
 * Any coordinate operation working with a datum shift grid such as NADCON or 
NTv2,
-* Landsat scenes with bands in separated TIFF images.
+* Landsat scenes with bands stored in separate TIFF images.
 
 By default, Apache SIS opens referenced files only if they are on the same host
 and in the same directory as, or in a sub-directory of, the referencing file.
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 a49ab90763..e3a3b82c9e 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
@@ -338,10 +338,10 @@ final class ImageFileDirectory extends DataCube {
      * <p>In a TIFF ColorMap, all the Red values come first, followed by all 
Green values, then all Blue values.
      * The number of values for each color is 1 {@literal <<} {@link 
#bitsPerSample}. Therefore, the {@code ColorMap}
      * vector for an 8-bit palette-color image would have 3 * 256 values. 0 
represents the minimum intensity and 65535
-     * represents the maximum intensity. Black is represented by 0,0,0 and 
white by 65535, 65535, 65535.</p>
+     * represents the maximum intensity. Black is represented by {0, 0, 0} and 
white by {65535, 65535, 65535}.</p>
      *
      * <p>{@code ColorMap} must be included in all palette-color images.
-     * In Specification Supplement 1, support was added for color maps 
containing other then RGB values.
+     * In Specification Supplement 1, support was added for color maps 
containing other than RGB values.
      * This scheme includes the {@code Indexed} tag, with value 1, and a 
{@link #photometricInterpretation}
      * different from {@code PaletteColor}.</p>
      */
@@ -1289,7 +1289,7 @@ final class ImageFileDirectory extends DataCube {
             missingTag((short) TAG_BITS_PER_SAMPLE, 1, false, false);
         }
         if (colorMap != null) {
-            ensureSameLength((short) TAG_COLOR_MAP, (short) 
TAG_BITS_PER_SAMPLE, colorMap.size(),  3 * (1 << bitsPerSample));
+            ensureSameLength((short) TAG_COLOR_MAP, (short) 
TAG_BITS_PER_SAMPLE, colorMap.size(), 3 * (1 << bitsPerSample));
         }
         if (sampleFormat != FLOAT) {
             long minValue, maxValue;
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/NativeMetadata.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/NativeMetadata.java
index 6f7abffbfc..a42a499957 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/NativeMetadata.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/NativeMetadata.java
@@ -39,6 +39,7 @@ import org.apache.sis.storage.geotiff.base.Predictor;
 import org.apache.sis.storage.geotiff.base.GeoKeys;
 import org.apache.sis.storage.geotiff.base.Tags;
 import org.apache.sis.storage.geotiff.reader.Type;
+import org.apache.sis.storage.geotiff.reader.ColorMap;
 import org.apache.sis.storage.geotiff.reader.GeoKeysLoader;
 import org.apache.sis.storage.geotiff.reader.ModelTiePoints;
 import org.apache.sis.storage.geotiff.reader.XMLMetadata;
@@ -191,6 +192,10 @@ final class NativeMetadata extends GeoKeysLoader {
                                 value = new 
ModelTiePoints(type.readAsVector(input, count));
                                 break;
                             }
+                            case TAG_COLOR_MAP: {
+                                value = new ColorMap(type.readAsVector(input, 
count));
+                                break;
+                            }
                             default: {
                                 value = type.readAsObject(input, count);
                                 if (value instanceof Vector) {
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/ColorMap.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/ColorMap.java
new file mode 100644
index 0000000000..0e12e942e8
--- /dev/null
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/ColorMap.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.storage.geotiff.reader;
+
+import java.util.Objects;
+import java.util.Locale;
+import java.text.Format;
+import java.text.NumberFormat;
+import org.apache.sis.math.Vector;
+import org.apache.sis.util.resources.Vocabulary;
+import org.apache.sis.util.internal.shared.TableRowList;
+
+
+/**
+ * The color map represented as a table. Used only for native metadata 
representation.
+ * In a TIFF color map, all the Red values come first, followed by all Green 
values, then all Blue values.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @author  Jonatas Fischer
+ */
+public final class ColorMap extends TableRowList<Vector, Integer> {
+    /**
+     * Number of values per color.
+     */
+    private static final int RECORD_LENGTH = 3;
+    /**
+     * Values of colors read from GeoTIFF file.
+     */
+    private final Vector values;
+
+    /**
+     * Number of colors, saved because frequently used.
+     */
+    private final int size;
+
+    /**
+     * Creates a new color map.
+     *
+     * @param  values  values of colors read from GeoTIFF file.
+     */
+    public ColorMap(final Vector values) {
+        this.values = values;
+        size = values.size() / RECORD_LENGTH;
+    }
+
+    /**
+     * Returns the number of colors.
+     *
+     * @return number of colors.
+     */
+    @Override
+    public int size() {
+        return size;
+    }
+
+    /**
+     * Returns the column headers.
+     * The returned array length is {@link #RECORD_LENGTH}.
+     */
+    @Override
+    public String[] columns(final Locale locale) {
+        final Vocabulary vocabulary = Vocabulary.forLocale(locale);
+        return new String[] {
+            vocabulary.getString(Vocabulary.Keys.Red),
+            vocabulary.getString(Vocabulary.Keys.Green),
+            vocabulary.getString(Vocabulary.Keys.Blue)
+        };
+    }
+
+    /**
+     * Returns the value in the specified row and column.
+     */
+    @Override
+    public Integer get(final int row, final int column) {
+        return values.intValue(size * Objects.checkIndex(column, 
RECORD_LENGTH) + Objects.checkIndex(row, size));
+    }
+
+    /**
+     * Returns the colors in the given row.
+     */
+    @Override
+    public Vector get(final int row) {
+        return values.subSampling(Objects.checkIndex(row, size), size, 
RECORD_LENGTH);
+    }
+
+    /**
+     * Returns the format to use for the given column.
+     *
+     * @param  locale  the locale of the format to create.
+     * @param  column  the column for which to get a format.
+     */
+    @Override
+    public Format createFormat(final Locale locale, final int column) {
+        return NumberFormat.getIntegerInstance(locale);
+    }
+}
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/ModelTiePoints.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/ModelTiePoints.java
index c65aaa000b..39495ae965 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/ModelTiePoints.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/ModelTiePoints.java
@@ -85,9 +85,11 @@ public final class ModelTiePoints extends 
TableRowList<Vector, Double> {
     /**
      * Returns the column headers.
      * The returned array length is {@link #RECORD_LENGTH}.
+     *
+     * @param  locale  ignored.
      */
     @Override
-    public String[] columns() {
+    public String[] columns(final Locale locale) {
         return new String[] {"i", "j", "k", "x", "y", "z"};
     }
 
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/TableRowList.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/TableRowList.java
index e39df92d94..4323fa458b 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/TableRowList.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/internal/shared/TableRowList.java
@@ -43,9 +43,10 @@ public abstract class TableRowList<E, V> extends 
AbstractList<E> {
      * Returns the title of each column, in order.
      * The length of this array is the number of columns.
      *
+     * @param  locale  desired locale, or {@code null} for the default locale.
      * @return the column titles.
      */
-    public abstract String[] columns();
+    public abstract String[] columns(Locale locale);
 
     /**
      * Returns the value in the given column of the given row.
@@ -77,7 +78,7 @@ public abstract class TableRowList<E, V> extends 
AbstractList<E> {
     public String toString() {
         final var locale = Locale.getDefault();
         final var table = new TableAppender();
-        final String[] columns = columns();
+        final String[] columns = columns(locale);
         final Format[] formats = new Format[columns.length];
         table.setCellAlignment(TableAppender.ALIGN_RIGHT);
         table.setMultiLinesCells(true);
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/PropertyView.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/PropertyView.java
index 48af6a092e..a7651c42dc 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/PropertyView.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/internal/PropertyView.java
@@ -256,7 +256,8 @@ public final class PropertyView implements Localized, 
ChangeListener<Number> {
             node = new TableView<>();
             tableView = node;
         }
-        
node.getColumns().setAll(FormatTableCellFactory.createColumns(table.columns(), 
(i) -> table.createFormat(getLocale(), i)));
+        final Locale locale = getLocale();
+        
node.getColumns().setAll(FormatTableCellFactory.createColumns(table.columns(locale),
 (i) -> table.createFormat(locale, i)));
         node.getItems().setAll(table);
         return node;
     }

Reply via email to