This is an automated email from the ASF dual-hosted git repository.
jsorel 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 36af97c7b8 Improve support of tilematrix and jpef items in GIMI
36af97c7b8 is described below
commit 36af97c7b8e208a2482dd2aee65c00a400ecafb7
Author: jsorel <[email protected]>
AuthorDate: Fri Jul 26 17:19:00 2024 +0200
Improve support of tilematrix and jpef items in GIMI
---
.../org/apache/sis/storage/gimi/GimiStore.java | 328 +++++++++++++++++++--
.../sis/storage/gimi/internal/ScaleSortedMap.java | 104 +++++++
.../sis/storage/gimi/internal/TileMatrices.java | 60 ++++
.../org/apache/sis/storage/gimi/isobmff/Box.java | 4 +-
.../sis/storage/gimi/isobmff/ISOBMFFReader.java | 10 +
.../gimi/isobmff/iso14496_10/ContentDescribes.java | 19 +-
.../EntityToGroup.java} | 20 +-
.../gimi/isobmff/iso14496_12/ItemReference.java | 7 +-
.../gimi/isobmff/iso23008_12/ISO23008_12.java | 2 +
.../ImagePyramidEntityGroup.java} | 39 ++-
10 files changed, 518 insertions(+), 75 deletions(-)
diff --git
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiStore.java
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiStore.java
index 0387851d39..c7f505d10e 100644
---
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiStore.java
+++
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiStore.java
@@ -18,13 +18,22 @@ package org.apache.sis.storage.gimi;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
+import java.util.SortedMap;
+import java.util.function.Function;
import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import javax.imageio.ImageIO;
+import javax.imageio.stream.ImageInputStream;
import org.apache.sis.coverage.SampleDimension;
import org.apache.sis.coverage.grid.GridCoverage;
import org.apache.sis.coverage.grid.GridCoverageBuilder;
@@ -36,12 +45,17 @@ import org.apache.sis.parameter.Parameters;
import org.apache.sis.referencing.CRS;
import org.apache.sis.referencing.privy.AffineTransform2D;
import org.apache.sis.storage.AbstractGridCoverageResource;
+import org.apache.sis.storage.AbstractResource;
import org.apache.sis.storage.Aggregate;
import org.apache.sis.storage.DataStore;
+import org.apache.sis.storage.DataStoreContentException;
import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.storage.GridCoverageResource;
import org.apache.sis.storage.Resource;
import org.apache.sis.storage.StorageConnector;
import org.apache.sis.storage.base.StoreResource;
+import org.apache.sis.storage.gimi.internal.ScaleSortedMap;
+import org.apache.sis.storage.gimi.internal.TileMatrices;
import org.apache.sis.storage.gimi.isobmff.Box;
import org.apache.sis.storage.gimi.isobmff.ISOBMFFReader;
import org.apache.sis.storage.gimi.isobmff.gimi.ModelTiePointProperty;
@@ -61,12 +75,19 @@ import
org.apache.sis.storage.gimi.isobmff.iso14496_12.SingleItemTypeReference;
import org.apache.sis.storage.gimi.isobmff.iso23001_17.ComponentDefinition;
import org.apache.sis.storage.gimi.isobmff.iso23001_17.UncompressedFrameConfig;
import org.apache.sis.storage.gimi.isobmff.iso23008_12.ImageSpatialExtents;
+import org.apache.sis.storage.tiling.Tile;
+import org.apache.sis.storage.tiling.TileMatrix;
import org.apache.sis.storage.tiling.TileMatrixSet;
+import org.apache.sis.storage.tiling.TileStatus;
import org.apache.sis.storage.tiling.TiledResource;
+import org.apache.sis.util.iso.Names;
+import org.opengis.geometry.Envelope;
import org.opengis.metadata.Metadata;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.MathTransform;
import org.opengis.util.FactoryException;
+import org.opengis.util.GenericName;
/**
*
@@ -77,6 +98,7 @@ public final class GimiStore extends DataStore implements
Aggregate {
private final Path gimiPath;
private List<Resource> components;
+ private Map<Integer,Resource> componentIndex;
//cache the reader
private ISOBMFFReader reader;
@@ -125,6 +147,7 @@ public final class GimiStore extends DataStore implements
Aggregate {
if (components != null) return components;
components = new ArrayList<>();
+ componentIndex = new HashMap<>();
try {
final ISOBMFFReader reader = getReader();
@@ -141,16 +164,22 @@ public final class GimiStore extends DataStore implements
Aggregate {
iinf.readPayload(reader.channel);
for (ItemInfoEntry iie : iinf.entries) {
final Item item = new Item(iie);
- if (UncompressedImage.TYPE.equals(iie.itemType)) {
+ Resource resource;
+ if (UncompressedImage.TYPE_UNCOMPRESSED.equals(iie.itemType)) {
//uncompressed image
- components.add(new UncompressedImage(item));
- } else if (Grid.TYPE.equals(iie.itemType)) {
+ resource = new UncompressedImage(item);
+ } else if (Jpeg.TYPE_JPEG.equals(iie.itemType)) {
//tiled image
- components.add(new Grid(item));
+ resource = new Jpeg(item);
+ } else if (Grid.TYPE.equals(iie.itemType)) {
+ //tiled image
+ resource = new Grid(item);
} else {
//TODO
- //ignore all others for now
+ resource = new UnknownResource(item);
}
+ components.add(resource);
+ componentIndex.put(iie.itemId, resource);
}
} catch (Exception ex) {
@@ -160,21 +189,36 @@ public final class GimiStore extends DataStore implements
Aggregate {
return components;
}
+ private final class UnknownResource extends AbstractResource implements
StoreResource{
+
+ private final Item item;
+
+ public UnknownResource(Item item) throws DataStoreException {
+ super(GimiStore.this);
+ this.item = item;
+
+ }
+
+ @Override
+ public DataStore getOriginator() {
+ return GimiStore.this;
+ }
+ }
+
/**
* A single uncompressed image.
*/
- private final class UncompressedImage extends AbstractGridCoverageResource
implements StoreResource {
+ private class UncompressedImage extends AbstractGridCoverageResource
implements StoreResource {
- public static final String TYPE = "unci";
+ public static final String TYPE_UNCOMPRESSED = "unci";
- private final Item item;
- private ComponentDefinition compDef;
- private ImageSpatialExtents imageExt;
- private UncompressedFrameConfig frameConf;
- private ModelTransformationProperty modelTrs;
- private ModelTiePointProperty modelTp;
- private WellKnownText2Property modelWkt;
- private MediaData mediaData;
+ protected final Item item;
+ protected ComponentDefinition compDef;
+ protected ImageSpatialExtents imageExt;
+ protected UncompressedFrameConfig frameConf;
+ protected ModelTransformationProperty modelTrs;
+ protected ModelTiePointProperty modelTp;
+ protected WellKnownText2Property modelWkt;
public UncompressedImage(Item item) throws DataStoreException {
super(GimiStore.this);
@@ -238,9 +282,9 @@ public final class GimiStore extends DataStore implements
Aggregate {
for (int y = 0; y < 1024; y++) {
for (int x = 0; x < 2048; x++) {
int offset = y*2048 + x;
- raster.setSample(x, y, 0, mediaData.data[offset*3] & 0xFF);
- raster.setSample(x, y, 1, mediaData.data[offset*3+1] &
0xFF);
- raster.setSample(x, y, 2, mediaData.data[offset*3+2] &
0xFF);
+ raster.setSample(x, y, 0, data[offset*3] & 0xFF);
+ raster.setSample(x, y, 1, data[offset*3+1] & 0xFF);
+ raster.setSample(x, y, 2, data[offset*3+2] & 0xFF);
}
}
@@ -256,40 +300,261 @@ public final class GimiStore extends DataStore
implements Aggregate {
}
+ private final class Jpeg extends UncompressedImage {
+
+ public static final String TYPE_JPEG = "jpeg";
+
+ public Jpeg(Item item) throws DataStoreException {
+ super(item);
+ }
+
+ @Override
+ public GridCoverage read(GridGeometry gg, int... ints) throws
DataStoreException {
+ final byte[] data = item.getData();
+
+ ImageInputStream iis;
+ BufferedImage img;
+ try {
+ iis = ImageIO.createImageInputStream(new
ByteArrayInputStream(data));
+ img = ImageIO.read(iis);
+ } catch (IOException ex) {
+ throw new DataStoreException(ex);
+ }
+
+ final GridGeometry gridGeometry = getGridGeometry();
+ GridCoverageBuilder gcb = new GridCoverageBuilder();
+ gcb.setDomain(gridGeometry);
+ //gcb.setRanges(getSampleDimensions());
+ //gcb.setValues(db, new
Dimension((int)gridGeometry.getExtent().getSize(0),
(int)gridGeometry.getExtent().getSize(1)));
+ gcb.setValues(img);
+ return gcb.build();
+ }
+
+ }
+
+
private final class Grid extends AbstractGridCoverageResource implements
TiledResource, StoreResource {
public static final String TYPE = "grid";
private final Item item;
+ private final GenericName identifier;
+
+ //filled after initialize
+ private GridCoverageResource first;
+ private CoordinateReferenceSystem crs;
+ private TileMatrix tileMatrix;
+ private GimiTileMatrixSet tileMatrixSet;
public Grid(Item item) throws DataStoreException {
super(GimiStore.this);
this.item = item;
+ if (item.entry.itemName == null || item.entry.itemName.isBlank()) {
+ this.identifier = Names.createLocalName(null, null,
Integer.toString(item.entry.itemId));
+ } else {
+ this.identifier = Names.createLocalName(null, null,
item.entry.itemName);
+ }
}
@Override
- public GridGeometry getGridGeometry() throws DataStoreException {
- throw new UnsupportedOperationException("Not supported yet."); //
Generated from
nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
+ public Optional<GenericName> getIdentifier() {
+ return Optional.of(identifier);
+ }
+
+ @Override
+ public DataStore getOriginator() {
+ return GimiStore.this;
+ }
+
+ private synchronized void initialize() throws DataStoreException {
+ final Resource first =
componentIndex.get(item.references.get(0).toItemId[0]);
+ if (first instanceof GridCoverageResource) {
+ this.first = (GridCoverageResource) first;
+ } else {
+ throw new DataStoreException("Expecting a GridCoverageResource
tile but was a " + first.getClass().getName());
+ }
+
+ final GridGeometry firstTileGridGeom =
this.first.getGridGeometry();
+ this.crs = firstTileGridGeom.getCoordinateReferenceSystem();
+ final GridExtent tileExtent = firstTileGridGeom.getExtent();
+ final int[] tileSize = new
int[]{Math.toIntExact(tileExtent.getSize(0)),
Math.toIntExact(tileExtent.getSize(1))};
+ final MathTransform matrixGridToCrs =
firstTileGridGeom.derive().subgrid(null,
tileSize).build().getGridToCRS(PixelInCell.CELL_CENTER);
+
+ for (Box b : item.properties) {
+ if (b instanceof ImageSpatialExtents) {
+ final ImageSpatialExtents ext = (ImageSpatialExtents) b;
+ final long matrixWidth = ext.imageWidth /
tileExtent.getSize(0);
+ final long matrixHeight = ext.imageHeight /
tileExtent.getSize(1);
+
+ //create tile matrix
+ final GridGeometry tilingScheme = new GridGeometry(new
GridExtent(matrixWidth, matrixHeight), PixelInCell.CELL_CENTER,
matrixGridToCrs, crs);
+ tileMatrix = new GimiTileMatrix(this, tilingScheme,
tileSize);
+
+ //create tile matrix set
+ tileMatrixSet = new
GimiTileMatrixSet(Names.createLocalName(null, null, identifier.tip().toString()
+ "_tms"), crs);
+ tileMatrixSet.matrices.insertByScale(tileMatrix);
+ }
+ }
}
@Override
public List<SampleDimension> getSampleDimensions() throws
DataStoreException {
- throw new UnsupportedOperationException("Not supported yet."); //
Generated from
nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
+ initialize();
+ return first.getSampleDimensions();
+ }
+
+ @Override
+ public Collection<? extends TileMatrixSet> getTileMatrixSets() throws
DataStoreException {
+ initialize();
+ return List.of(tileMatrixSet);
+ }
+
+ @Override
+ public GridGeometry getGridGeometry() throws DataStoreException {
+ throw new UnsupportedOperationException("Not supported yet.");
}
+
@Override
public GridCoverage read(GridGeometry domain, int... ranges) throws
DataStoreException {
- throw new UnsupportedOperationException("Not supported yet."); //
Generated from
nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+ }
+
+ private final class GimiTile implements Tile {
+
+ private final long[] indices;
+ private final int itemId;
+
+ public GimiTile(long[] indices, int itemId) {
+ this.indices = indices;
+ this.itemId = itemId;
}
@Override
- public Collection<? extends TileMatrixSet> getTileMatrixSets() throws
DataStoreException {
- throw new UnsupportedOperationException("Not supported yet."); //
Generated from
nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
+ public long[] getIndices() {
+ return indices.clone();
}
@Override
- public DataStore getOriginator() {
- return GimiStore.this;
+ public TileStatus getStatus() {
+ return componentIndex.containsKey(itemId) ? TileStatus.EXISTS :
TileStatus.MISSING;
+ }
+
+ @Override
+ public Resource getResource() throws DataStoreException {
+ final Resource res = componentIndex.get(itemId);
+ if (res == null) throw new DataStoreContentException("Missing tile
at " + Arrays.toString(indices) + ", it should not be possible with GIMI
model");
+ return res;
+ }
+ }
+
+ private final class GimiTileMatrix implements TileMatrix {
+
+ private final Grid grid;
+ private final GenericName identifier;
+ private final GridGeometry tilingScheme;
+ private final int[] tileSize;
+
+ public GimiTileMatrix(Grid grid, GridGeometry tilingScheme, int[]
tileSize) {
+ this.grid = grid;
+ this.identifier = Names.createLocalName(null, null,
grid.getIdentifier().get().tip().toString()+"_tm");
+ this.tilingScheme = tilingScheme;
+ this.tileSize = tileSize;
+ }
+
+ @Override
+ public GenericName getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public double[] getResolution() {
+ double[] resolution = tilingScheme.getResolution(true);
+ resolution[0] /= tileSize[0];
+ resolution[1] /= tileSize[1];
+ return resolution;
+ }
+
+ @Override
+ public GridGeometry getTilingScheme() {
+ return tilingScheme;
+ }
+
+ @Override
+ public TileStatus getTileStatus(long... indices) throws
DataStoreException {
+ return tilingScheme.getExtent().contains(indices) ?
TileStatus.EXISTS : TileStatus.OUTSIDE_EXTENT;
+ }
+
+ @Override
+ public Optional<Tile> getTile(long... indices) throws
DataStoreException {
+ final int itemIdx = Math.toIntExact(indices[0] + indices[1] *
tilingScheme.getExtent().getSize(0));
+ return Optional.of(new GimiTile(indices,
grid.item.references.get(0).toItemId[itemIdx]));
+ }
+
+ @Override
+ public Stream<Tile> getTiles(GridExtent indicesRanges, boolean
parallel) throws DataStoreException {
+ Stream<long[]> stream = TileMatrices.pointStream(indicesRanges);
+ stream = parallel ? stream.parallel() : stream.sequential();
+ return stream.map(new Function<long[], Tile>(){
+ @Override
+ public Tile apply(final long[] indices) {
+ try {
+ return getTile(indices).orElse(null);
+ } catch (DataStoreException ex) {
+ return new Tile() {
+ @Override
+ public long[] getIndices() {
+ return indices;
+ }
+
+ @Override
+ public TileStatus getStatus() {
+ return TileStatus.IN_ERROR;
+ }
+
+ @Override
+ public Resource getResource() throws
DataStoreException {
+ throw ex;
+ }
+ };
+ }
+ }
+ });
+ }
+ }
+
+ private final class GimiTileMatrixSet implements TileMatrixSet {
+
+ private final GenericName identifier;
+ private final CoordinateReferenceSystem crs;
+ private final ScaleSortedMap<TileMatrix> matrices = new
ScaleSortedMap<>();
+
+ public GimiTileMatrixSet(GenericName identifier,
CoordinateReferenceSystem crs) {
+ this.identifier = identifier;
+ this.crs = crs;
+ }
+
+ @Override
+ public GenericName getIdentifier() {
+ return identifier;
+ }
+
+ @Override
+ public CoordinateReferenceSystem getCoordinateReferenceSystem() {
+ return crs;
+ }
+
+ @Override
+ public Optional<Envelope> getEnvelope() {
+ if (matrices.isEmpty()) return Optional.empty();
+ return
Optional.of(matrices.lastEntry().getValue().getTilingScheme().getEnvelope());
+ }
+
+ @Override
+ public SortedMap<GenericName, ? extends TileMatrix> getTileMatrices() {
+ return matrices;
}
}
@@ -310,11 +575,11 @@ public final class GimiStore extends DataStore implements
Aggregate {
final ISOBMFFReader reader = getReader();
final Box meta = root.getChild(Meta.FCC, null, reader.channel);
+ ISOBMFFReader.load(meta, reader.channel);
//is item primary
final PrimaryItem primaryItem = (PrimaryItem)
meta.getChild(PrimaryItem.FCC, null, reader.channel);
if (primaryItem != null) {
- primaryItem.readPayload(reader.channel);
isPrimary = primaryItem.itemId == entry.itemId;
} else {
isPrimary = true;
@@ -323,12 +588,9 @@ public final class GimiStore extends DataStore implements
Aggregate {
//extract properties
final Box itemProperties = meta.getChild(ItemProperties.FCC, null,
reader.channel);
if (itemProperties != null) {
- itemProperties.readPayload(reader.channel);
final ItemPropertyContainer itemPropertiesContainer =
(ItemPropertyContainer) itemProperties.getChild(ItemPropertyContainer.FCC,
null, reader.channel);
- itemPropertiesContainer.readPayload(reader.channel);
final List<Box> allProperties =
itemPropertiesContainer.getChildren(reader.channel);
final ItemPropertyAssociation itemPropertiesAssociations =
(ItemPropertyAssociation) itemProperties.getChild(ItemPropertyAssociation.FCC,
null, reader.channel);
- itemPropertiesAssociations.readPayload(reader.channel);
for (ItemPropertyAssociation.Entry en :
itemPropertiesAssociations.entries) {
if (en.itemId == entry.itemId) {
@@ -343,7 +605,11 @@ public final class GimiStore extends DataStore implements
Aggregate {
//extract outter references
final ItemReference itemReferences = (ItemReference)
meta.getChild(ItemReference.FCC, null, reader.channel);
if (itemReferences != null) {
-
+ for (SingleItemTypeReference sitr : itemReferences.references)
{
+ if (sitr.fromItemId == entry.itemId) {
+ references.add(sitr);
+ }
+ }
}
diff --git
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/internal/ScaleSortedMap.java
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/internal/ScaleSortedMap.java
new file mode 100644
index 0000000000..6b88d6d537
--- /dev/null
+++
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/internal/ScaleSortedMap.java
@@ -0,0 +1,104 @@
+/*
+ * 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.gimi.internal;
+
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.storage.tiling.TileMatrix;
+import org.opengis.util.GenericName;
+
+/**
+ * SortedMap of TileMatrix sorted by first axe resolution.
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+public final class ScaleSortedMap<T extends TileMatrix> extends
TreeMap<GenericName, T>{
+
+ public ScaleSortedMap() {
+ super(new ScaleComparator());
+ comparator();
+ }
+
+ public void insertByScale(T tileMatrix) {
+ final GenericName id = tileMatrix.getIdentifier();
+ ArgumentChecks.ensureNonNull("identifier", id);
+ final ScaleComparator comparator = (ScaleComparator) comparator();
+ if (comparator.matricesByScale.containsKey(id)) {
+ throw new IllegalArgumentException("Key " + id + "already exist");
+ }
+ final double resolution = tileMatrix.getResolution()[0];
+ comparator.matricesByScale.put(id, resolution);
+ super.put(id, tileMatrix);
+ }
+
+ public void removeByScale(T tileMatrix) {
+ final GenericName id = tileMatrix.getIdentifier();
+ ArgumentChecks.ensureNonNull("identifier", id);
+ final ScaleComparator comparator = (ScaleComparator) comparator();
+ if (comparator.matricesByScale.remove(id) != null) {
+ super.remove(id);
+ }
+ }
+
+ @Override
+ public T put(GenericName key, T value) {
+ throw new IllegalArgumentException("Should not be used");
+ }
+
+ @Override
+ public void putAll(Map<? extends GenericName, ? extends T> map) {
+ throw new IllegalArgumentException("Should not be used");
+ }
+
+ @Override
+ public T putIfAbsent(GenericName key, T value) {
+ throw new IllegalArgumentException("Should not be used");
+ }
+
+ @Override
+ public T remove(Object key) {
+ throw new IllegalArgumentException("Should not be used");
+ }
+
+ @Override
+ public boolean remove(Object key, Object value) {
+ throw new IllegalArgumentException("Should not be used");
+ }
+
+ /**
+ * Compare TileMatrix by scale.
+ * Entries are sorted from coarser resolution (highest scale denominator)
to most detailed resolution (lowest scale denominator).
+ */
+ private static class ScaleComparator implements Comparator<GenericName> {
+ private final Map<GenericName,Double> matricesByScale = new
HashMap<>();
+
+ @Override
+ public int compare(GenericName o1, GenericName o2) {
+ Double d1 = matricesByScale.get(o1);
+ Double d2 = matricesByScale.get(o2);
+ if (d1 == null) d1 = Double.NaN;
+ if (d2 == null) d2 = Double.NaN;
+ int v = Double.compare(d2, d1);
+ if (v != 0) return v;
+ //we NEED ordering, otherwise entry will be replaced.
+ return o1.toString().compareTo(o2.toString());
+ }
+ }
+}
diff --git
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/internal/TileMatrices.java
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/internal/TileMatrices.java
new file mode 100644
index 0000000000..ab1b01b566
--- /dev/null
+++
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/internal/TileMatrices.java
@@ -0,0 +1,60 @@
+/*
+ * 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.gimi.internal;
+
+import java.util.stream.LongStream;
+import java.util.stream.Stream;
+import org.apache.sis.coverage.grid.GridExtent;
+
+/**
+ *
+ * @author Johann Sorel (Geomatys)
+ */
+public class TileMatrices {
+
+ private TileMatrices(){}
+
+
+ /**
+ * Create a stream of point in the GridExtent.
+ *
+ * TODO : make a more efficient implementation.
+ */
+ public static Stream<long[]> pointStream(GridExtent extent) {
+ final int dimension = extent.getDimension();
+ final long[] low = extent.getLow().getCoordinateValues();
+ final long[] high = extent.getHigh().getCoordinateValues();
+
+ Stream<long[]> stream = LongStream.range(low[0], high[0]+1)
+ .mapToObj((long value) -> {
+ final long[] array = new long[dimension];
+ array[0] = value;
+ return array;
+ });
+ for (int i = 1; i <dimension; i++) {
+ final int idx = i;
+ stream = stream.flatMap((long[] t) -> LongStream.range(low[idx],
high[idx]+1)
+ .mapToObj((long value) -> {
+ final long[] array = t.clone();
+ array[idx] = value;
+ return array;
+ }));
+ }
+ return stream;
+ }
+
+}
diff --git
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/Box.java
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/Box.java
index 37318ac1a4..14733fd16e 100644
---
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/Box.java
+++
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/Box.java
@@ -117,6 +117,7 @@ public class Box {
final Box box = ISOBMFFReader.readBox(cdi);
cdi.seek(box.boxOffset + box.size);
children.add(box);
+ if (box.size == 0) break; //last box
}
} catch (EOFException ex) {
//expected
@@ -126,6 +127,7 @@ public class Box {
final Box box = ISOBMFFReader.readBox(cdi);
cdi.seek(box.boxOffset + box.size);
children.add(box);
+ if (box.size == 0) break; //last box
}
}
@@ -243,7 +245,7 @@ public class Box {
final List<Field> fields = new ArrayList<>();
while (!(clazz == Box.class || clazz == FullBox.class) && clazz !=
null) {
- fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
+ fields.addAll(0, Arrays.asList(clazz.getDeclaredFields()));
clazz = clazz.getSuperclass();
}
diff --git
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/ISOBMFFReader.java
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/ISOBMFFReader.java
index 46cb4155ac..fab59b5555 100644
---
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/ISOBMFFReader.java
+++
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/ISOBMFFReader.java
@@ -149,4 +149,14 @@ public final class ISOBMFFReader {
cdi.readByte(); //skip string 0/null terminal marker
return str;
}
+
+ /**
+ * Load box payload and all children payload recursively.
+ */
+ public static void load(Box box, ChannelDataInput cdi) throws IOException {
+ box.readPayload(cdi);
+ for (Box b : box.getChildren(cdi)) {
+ load(b, cdi);
+ }
+ }
}
diff --git
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_10/ContentDescribes.java
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_10/ContentDescribes.java
index bda82d3f11..c057a52cf0 100644
---
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_10/ContentDescribes.java
+++
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_10/ContentDescribes.java
@@ -16,30 +16,15 @@
*/
package org.apache.sis.storage.gimi.isobmff.iso14496_10;
-import java.io.IOException;
-import org.apache.sis.io.stream.ChannelDataInput;
-import org.apache.sis.storage.gimi.isobmff.Box;
+import org.apache.sis.storage.gimi.isobmff.iso14496_12.SingleItemTypeReference;
/**
*
* @author Johann Sorel (Geomatys)
*/
-public class ContentDescribes extends Box{
+public class ContentDescribes extends SingleItemTypeReference{
public static final String FCC = "cdsc";
- public int fromId;
- public int[] toId;
-
- @Override
- protected void readProperties(ChannelDataInput cdi) throws IOException {
- fromId = cdi.readUnsignedShort();
- toId = new int[cdi.readUnsignedShort()];
- for (int i = 0; i < toId.length ; i++) {
- toId[i] = cdi.readUnsignedShort();
- }
- }
-
-
}
diff --git
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_10/ContentDescribes.java
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_12/EntityToGroup.java
similarity index 70%
copy from
incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_10/ContentDescribes.java
copy to
incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_12/EntityToGroup.java
index bda82d3f11..f927a670f0 100644
---
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_10/ContentDescribes.java
+++
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_12/EntityToGroup.java
@@ -14,32 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sis.storage.gimi.isobmff.iso14496_10;
+package org.apache.sis.storage.gimi.isobmff.iso14496_12;
import java.io.IOException;
import org.apache.sis.io.stream.ChannelDataInput;
-import org.apache.sis.storage.gimi.isobmff.Box;
+import org.apache.sis.storage.gimi.isobmff.FullBox;
/**
*
* @author Johann Sorel (Geomatys)
*/
-public class ContentDescribes extends Box{
+public class EntityToGroup extends FullBox {
- public static final String FCC = "cdsc";
-
- public int fromId;
- public int[] toId;
+ public int groupId;
+ public int[] entitiesId;
@Override
protected void readProperties(ChannelDataInput cdi) throws IOException {
- fromId = cdi.readUnsignedShort();
- toId = new int[cdi.readUnsignedShort()];
- for (int i = 0; i < toId.length ; i++) {
- toId[i] = cdi.readUnsignedShort();
- }
+ groupId = cdi.readInt();
+ entitiesId = cdi.readInts(cdi.readInt());
}
-
}
diff --git
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_12/ItemReference.java
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_12/ItemReference.java
index 405e7bf6d2..a553f10590 100644
---
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_12/ItemReference.java
+++
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_12/ItemReference.java
@@ -32,7 +32,7 @@ public class ItemReference extends FullBox {
public static final String FCC = "iref";
- public List<Box> references;
+ public List<SingleItemTypeReference> references;
@Override
public void readProperties(ChannelDataInput cdi) throws IOException {
@@ -40,9 +40,12 @@ public class ItemReference extends FullBox {
while (cdi.getStreamPosition() < boxOffset+size) {
final Box box = ISOBMFFReader.readBox(cdi);
+ if (!(box instanceof SingleItemTypeReference)) {
+ throw new IOException("Expected only SingleItemTypeReference
boxes in ItemReference but encounter a " + box.getClass().getSimpleName());
+ }
box.readPayload(cdi);
cdi.seek(box.boxOffset + box.size);
- references.add(box);
+ references.add((SingleItemTypeReference) box);
}
}
}
diff --git
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso23008_12/ISO23008_12.java
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso23008_12/ISO23008_12.java
index fca0498f3e..ea4ef9a216 100644
---
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso23008_12/ISO23008_12.java
+++
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso23008_12/ISO23008_12.java
@@ -29,6 +29,7 @@ public final class ISO23008_12 implements BoxRegistry {
private static final Set<String> BOXES = Set.of(
DerivedImageReference.FCC,
+ ImagePyramidEntityGroup.FCC,
ImageSpatialExtents.FCC,
PixelInformationProperty.FCC,
UserDescriptionProperty.FCC
@@ -54,6 +55,7 @@ public final class ISO23008_12 implements BoxRegistry {
public Box create(String fourCC) throws IllegalNameException {
//TODO replace by String switch when SIS minimum java is updated
if (DerivedImageReference.FCC.equals(fourCC)) return new
DerivedImageReference();
+ else if (ImagePyramidEntityGroup.FCC.equals(fourCC)) return new
ImagePyramidEntityGroup();
else if (ImageSpatialExtents.FCC.equals(fourCC)) return new
ImageSpatialExtents();
else if (PixelInformationProperty.FCC.equals(fourCC)) return new
PixelInformationProperty();
else if (UserDescriptionProperty.FCC.equals(fourCC)) return new
UserDescriptionProperty();
diff --git
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_10/ContentDescribes.java
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso23008_12/ImagePyramidEntityGroup.java
similarity index 50%
copy from
incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_10/ContentDescribes.java
copy to
incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso23008_12/ImagePyramidEntityGroup.java
index bda82d3f11..e6b2d11f83 100644
---
a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_10/ContentDescribes.java
+++
b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso23008_12/ImagePyramidEntityGroup.java
@@ -14,32 +14,49 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sis.storage.gimi.isobmff.iso14496_10;
+package org.apache.sis.storage.gimi.isobmff.iso23008_12;
import java.io.IOException;
import org.apache.sis.io.stream.ChannelDataInput;
import org.apache.sis.storage.gimi.isobmff.Box;
+import org.apache.sis.storage.gimi.isobmff.iso14496_12.EntityToGroup;
/**
*
* @author Johann Sorel (Geomatys)
*/
-public class ContentDescribes extends Box{
+public final class ImagePyramidEntityGroup extends EntityToGroup{
- public static final String FCC = "cdsc";
+ public static final String FCC = "pymd";
- public int fromId;
- public int[] toId;
+ public static final class Matrix {
+ public int layerBinning;
+ public int tilesInLayerRowMinus1;
+ public int tilesInLayerColumnMinus1;
- @Override
- protected void readProperties(ChannelDataInput cdi) throws IOException {
- fromId = cdi.readUnsignedShort();
- toId = new int[cdi.readUnsignedShort()];
- for (int i = 0; i < toId.length ; i++) {
- toId[i] = cdi.readUnsignedShort();
+ @Override
+ public String toString() {
+ return Box.beanToString(this);
}
}
+ public int tileSizeX;
+ public int tileSizeY;
+ public Matrix[] matrices;
+ @Override
+ protected void readProperties(ChannelDataInput cdi) throws IOException {
+ super.readProperties(cdi);
+ tileSizeX = cdi.readUnsignedShort();
+ tileSizeY = cdi.readUnsignedShort();
+
+ matrices = new Matrix[entitiesId.length];
+ for (int i = 0; i < matrices.length; i++) {
+ matrices[i] = new Matrix();
+ matrices[i].layerBinning = cdi.readUnsignedShort();
+ matrices[i].tilesInLayerRowMinus1 = cdi.readUnsignedShort();
+ matrices[i].tilesInLayerColumnMinus1 = cdi.readUnsignedShort();
+ }
+ }
}