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; }
