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 b4604cdd7df5c2f0bd88bddeaba476c63c108d9e Author: Martin Desruisseaux <[email protected]> AuthorDate: Sat Jun 13 13:18:46 2026 +0200 Anticipate for the reuse of `ImageModel` in a future version. --- .../sis/storage/geoheif/CoverageBuilder.java | 32 +++++++++++----- .../main/org/apache/sis/storage/geoheif/Image.java | 2 +- .../org/apache/sis/storage/geoheif/ImageModel.java | 44 ++++++++++++++-------- .../apache/sis/storage/geoheif/ImageResource.java | 6 +-- .../sis/storage/geoheif/ResourceBuilder.java | 4 +- 5 files changed, 57 insertions(+), 31 deletions(-) diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/CoverageBuilder.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/CoverageBuilder.java index 4f2c8033e6..1cbabfe5f5 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/CoverageBuilder.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/CoverageBuilder.java @@ -69,9 +69,13 @@ import org.apache.sis.pending.jdk.JDK18; */ final class CoverageBuilder implements Emptiable { /** - * The data store which is creating a grid coverage. + * The resource which is creating a grid coverage. + * + * @todo A future version could store a map of {@link ImageModel} in the resource builder + * for the case where an image is tiled and each tile has the same image description. + * It would avoid recreating the same color model and sample model many times. */ - final GeoHeifStore store; + private final ResourceBuilder owner; /** * An index of the image to build, for information purpose only. @@ -180,17 +184,17 @@ final class CoverageBuilder implements Emptiable { /** * Creates a new builder with the given properties. * - * @param store the data store which is creating a grid coverage. + * @param owner the resource which is creating a grid coverage. * @param imageIndex an index of the image, for information purpose only. * @param properties source of coverage properties for this coverage item. * @param duplicatedBoxes names of boxes that were duplicated. Used for logging a warning only once per type of box. */ - CoverageBuilder(final GeoHeifStore store, + CoverageBuilder(final ResourceBuilder owner, final int imageIndex, final ItemProperties.ForID properties, final Set<String> duplicatedBoxes) { - this.store = store; + this.owner = owner; this.imageIndex = imageIndex; unknownBoxes = new LinkedHashMap<>(); if (properties == null) { @@ -281,7 +285,7 @@ final class CoverageBuilder implements Emptiable { if (duplicated) { final String type = Box.formatFourCC(property.type()); if (duplicatedBoxes.add(type)) { - store.warning(Errors.Keys.DuplicatedElement_1, type); + store().warning(Errors.Keys.DuplicatedElement_1, type); } } } @@ -350,7 +354,7 @@ final class CoverageBuilder implements Emptiable { sj.add(id.toString()); } final var record = new LogRecord(level, message.append(sj).append('.').toString()); - store.warning(record); + store().warning(record); } return essential; } @@ -408,12 +412,21 @@ final class CoverageBuilder implements Emptiable { return new ImageResource(this, tiles.toArray(Image[]::new), null); } + /** + * Returns the data store which is creating a grid coverage. + * + * @return the data store which is creating a grid coverage. + */ + public final GeoHeifStore store() { + return owner.store; + } + /** * Returns a name for the resource to create and opportunistically adds it to the metadata. * This method should be invoked exactly once. */ public final GenericName name() { - GenericName gn = store.createComponentName(name); + GenericName gn = store().createComponentName(name); metadata().addIdentifier(gn, MetadataBuilder.Scope.RESOURCE); return gn; } @@ -487,7 +500,7 @@ final class CoverageBuilder implements Emptiable { */ final void setImageLayout(final Image image) throws DataStoreException, IOException { if (imageModel == null) { - imageModel = new ImageModel(image.getImageType(store)); + imageModel = new ImageModel(image.getImageType(store()), this); } } @@ -534,6 +547,7 @@ final class CoverageBuilder implements Emptiable { * @throws DataStoreException if the "grid to <abbr>CRS</abbr>" transform cannot be created. */ public final GridGeometry gridGeometry() throws DataStoreException { + final GeoHeifStore store = store(); final var extent = new GridExtent(width, height); MathTransform gridToCRS = null; if (affine != null) { diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Image.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Image.java index f662062f3c..cea5719bb0 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Image.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/Image.java @@ -79,7 +79,7 @@ abstract class Image { byteOrder = builder.byteOrder(); numXTiles = builder.numTiles(0); numYTiles = builder.numTiles(1); - listeners = builder.store.listeners(); + listeners = builder.store().listeners(); // Do NOT invoke `builder.sampleModel()`, because that information is not available for all types. } diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageModel.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageModel.java index c7fa5c9c51..9c285ab3d0 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageModel.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageModel.java @@ -76,17 +76,11 @@ final class ImageModel { private final SampleDimension[] sampleDimensions; /** - * Creates a new image model from the given Image I/O specifier. - * - * @param type the image specifier from the Image I/O <abbr>API</abbr>. + * index of the image which has been used for deriving the sample dimensions. + * This is used by {@link #sampleDimensions} for detecting if we can skip the + * reconstruction of sample dimensions. */ - ImageModel(final ImageTypeSpecifier type) { - colorModel = type.getColorModel(); - sampleModel = type.getSampleModel(); - dataType = DataType.forDataBufferType(sampleModel.getDataType()); - sampleDimensions = null; - defaultBandNames = null; - } + private final int imageIndex; /** * Computes date type, color model, sample model, and sample dimensions. @@ -168,8 +162,9 @@ final class ImageModel { sb.setName(band); } defaultBandNames[band] = sb.getName(); - var source = new CoverageModifier.BandSource(builder.store, builder.imageIndex, band, numBands, dataType); - builder.metadata().addNewBand(sampleDimensions[band] = builder.store.customizer.customize(source, sb)); + final GeoHeifStore store = builder.store(); + var source = new CoverageModifier.BandSource(store, builder.imageIndex, band, numBands, dataType); + builder.metadata().addNewBand(sampleDimensions[band] = store.customizer.customize(source, sb)); sb.clear(); if (bitDepth == 0) { bitDepth = Component.DEFAULT_BIT_DEPTH; @@ -253,27 +248,44 @@ final class ImageModel { colorModel = cb.createRGB(sampleModel); } this.colorModel = colorModel; + imageIndex = builder.imageIndex; + } + + /** + * Creates a new image model from the given Image I/O specifier. + * + * @param builder the builder which is creating a grid coverage. + * @param type the image specifier from the Image I/O <abbr>API</abbr>. + */ + ImageModel(final ImageTypeSpecifier type, final CoverageBuilder builder) { + colorModel = type.getColorModel(); + sampleModel = type.getSampleModel(); + dataType = DataType.forDataBufferType(sampleModel.getDataType()); + imageIndex = builder.imageIndex; + sampleDimensions = null; + defaultBandNames = null; } /** * Returns the sample dimensions. * If the {@code coverage} argument is null, it is assumed the same as at construction time. * - * @param builder builder of the coverage for which to create sample dimensions, or {@code null}. + * @param builder builder of the coverage for which to create sample dimensions. * @return the sample dimensions. * @throws DataStoreContentException if the sample dimensions cannot be created. */ final List<SampleDimension> sampleDimensions(final CoverageBuilder builder) throws DataStoreException { SampleDimension[] bands = sampleDimensions; boolean share = true; - if (builder != null) { + if (builder.imageIndex != imageIndex) { bands = bands.clone(); final int numBands = bands.length; + final GeoHeifStore store = builder.store(); final var sb = new SampleDimension.Builder(); for (int band = 0; band < numBands; band++) { sb.setName(defaultBandNames[band]); - var source = new CoverageModifier.BandSource(builder.store, builder.imageIndex, band, numBands, dataType); - final SampleDimension sd = builder.store.customizer.customize(source, sb); + var source = new CoverageModifier.BandSource(store, builder.imageIndex, band, numBands, dataType); + final SampleDimension sd = store.customizer.customize(source, sb); if (!sd.equals(bands[band])) { bands[band] = sd; share = false; 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 3686e778f6..274aa98072 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 @@ -129,10 +129,10 @@ final class ImageResource extends TiledGridCoverageResource implements StoreReso * @throws DataStoreException if the "grid to <abbr>CRS</abbr>" transform or the sample dimensions cannot be created. */ ImageResource(final CoverageBuilder builder, Image[] tiles, final Image image) throws DataStoreException { - super(builder.store); - this.store = builder.store; + super(builder.store()); + this.store = builder.store(); identifier = builder.name(); - sampleDimensions = builder.imageModel().sampleDimensions(null); + sampleDimensions = builder.imageModel().sampleDimensions(builder); gridGeometry = builder.gridGeometry(); if (tiles == null) { // Shall be after the call to `sampleDimensions()`. diff --git a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ResourceBuilder.java b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ResourceBuilder.java index 53cc82e09a..be195117b2 100644 --- a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ResourceBuilder.java +++ b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ResourceBuilder.java @@ -64,7 +64,7 @@ final class ResourceBuilder { /** * The data store for which the resources are built. */ - private final GeoHeifStore store; + final GeoHeifStore store; /** * Identifier of the primary item. Should contain at most one element, but we are paranoiac. @@ -323,7 +323,7 @@ final class ResourceBuilder { final int imageIndex = (addTo != null ? addTo : resources).size(); final ItemProperties.ForID itemProperties = properties.remove(itemID); final CoverageBuilder coverage = builders.computeIfAbsent(itemProperties, - (p) -> new CoverageBuilder(store, imageIndex, p, duplicatedBoxes)); + (p) -> new CoverageBuilder(this, imageIndex, p, duplicatedBoxes)); if (coverage.reportUnknownBoxes(name)) { // Warning already logged by `reportUnknownBoxes(…)`. continue;
