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 5364df70d4 Handle more divers structures in GIMI files 5364df70d4 is described below commit 5364df70d40967b0511184daed56b53f7be18a36 Author: jsorel <johann.so...@geomatys.com> AuthorDate: Tue Oct 1 16:50:40 2024 +0200 Handle more divers structures in GIMI files --- .../org/apache/sis/storage/gimi/GimiProvider.java | 2 +- .../org/apache/sis/storage/gimi/GimiStore.java | 17 ++- .../apache/sis/storage/gimi/GimiTileMatrix.java | 4 +- .../org/apache/sis/storage/gimi/ResourceGrid.java | 64 +++++++--- .../storage/gimi/ResourceImageUncompressed.java | 134 ++++++++++++++++----- .../apache/sis/storage/gimi/ResourcePyramid.java | 62 +++++++++- .../sis/storage/gimi/internal/ScaleSortedMap.java | 2 +- .../isobmff/gimi/ModelTransformationProperty.java | 9 ++ .../gimi/isobmff/gimi/WellKnownText2Property.java | 9 ++ .../gimi/isobmff/iso23001_17/TAIClockInfo.java | 4 +- 10 files changed, 250 insertions(+), 57 deletions(-) diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiProvider.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiProvider.java index 3ec75d1fe1..239e08d1e5 100644 --- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiProvider.java +++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiProvider.java @@ -90,7 +90,7 @@ public final class GimiProvider extends DataStoreProvider { final Path path = connector.getStorageAs(Path.class); if (path != null) { final String name = path.getFileName().toString().toLowerCase(); - if (name.endsWith(".heij") || name.endsWith(".heif")) { + if (name.endsWith(".heij") || name.endsWith(".heif") || name.endsWith(".heic") || name.endsWith(".avif")) { return new ProbeResult(true, MIME_TYPE, null); } } 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 74a6aa4039..5490c19cb4 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 @@ -27,12 +27,14 @@ import java.util.Optional; import org.opengis.metadata.Metadata; import org.opengis.parameter.ParameterValueGroup; import org.apache.sis.io.stream.ChannelDataInput; +import org.apache.sis.io.stream.IOUtilities; import org.apache.sis.parameter.Parameters; import org.apache.sis.storage.Aggregate; import org.apache.sis.storage.DataStore; import org.apache.sis.storage.DataStoreException; import org.apache.sis.storage.Resource; import org.apache.sis.storage.StorageConnector; +import org.apache.sis.storage.base.MetadataBuilder; import org.apache.sis.storage.gimi.isobmff.Box; import org.apache.sis.storage.gimi.isobmff.ISOBMFFReader; import org.apache.sis.storage.gimi.isobmff.iso14496_12.GroupList; @@ -40,6 +42,7 @@ import org.apache.sis.storage.gimi.isobmff.iso14496_12.ItemInfo; import org.apache.sis.storage.gimi.isobmff.iso14496_12.ItemInfoEntry; import org.apache.sis.storage.gimi.isobmff.iso14496_12.Meta; import org.apache.sis.storage.gimi.isobmff.iso23008_12.ImagePyramidEntityGroup; +import org.apache.sis.util.iso.Names; /** @@ -52,6 +55,7 @@ public final class GimiStore extends DataStore implements Aggregate { private List<Resource> components; private Map<Integer,Resource> componentIndex; + private Metadata metadata; //cache the reader private ISOBMFFReader reader; @@ -72,8 +76,13 @@ public final class GimiStore extends DataStore implements Aggregate { } @Override - public Metadata getMetadata() throws DataStoreException { - throw new UnsupportedOperationException("Not supported yet."); + public synchronized Metadata getMetadata() throws DataStoreException { + if (metadata == null) { + final MetadataBuilder builder = new MetadataBuilder(); + builder.addIdentifier(Names.createLocalName(null, null, IOUtilities.filenameWithoutExtension(gimiPath.getFileName().toString())), MetadataBuilder.Scope.ALL); + metadata = builder.buildAndFreeze(); + } + return metadata; } @Override @@ -154,6 +163,10 @@ public final class GimiStore extends DataStore implements Aggregate { final ResourcePyramid pyramid = new ResourcePyramid(this, img); components.add(pyramid); componentIndex.put(pyramid.group.groupId, pyramid); + + //force initialize now, pyramids may amend existing grids + pyramid.getGridGeometry(); + } } } diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiTileMatrix.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiTileMatrix.java index 3ba53d813c..c7e09cf8fd 100644 --- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiTileMatrix.java +++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/GimiTileMatrix.java @@ -40,9 +40,9 @@ final class GimiTileMatrix implements TileMatrix { private final ResourceGrid grid; private final GenericName identifier; private final GridGeometry tilingScheme; - private final int[] tileSize; + private final long[] tileSize; - public GimiTileMatrix(ResourceGrid grid, GridGeometry tilingScheme, int[] tileSize) { + public GimiTileMatrix(ResourceGrid grid, GridGeometry tilingScheme, long[] tileSize) { this.grid = grid; this.identifier = Names.createLocalName(null, null, grid.getIdentifier().get().tip().toString() + "_tm"); this.tilingScheme = tilingScheme; diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceGrid.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceGrid.java index 7853028cb5..e617a76823 100644 --- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceGrid.java +++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceGrid.java @@ -33,11 +33,14 @@ import org.apache.sis.storage.Resource; import org.apache.sis.storage.base.StoreResource; import org.apache.sis.storage.gimi.internal.MatrixGridRessource; import org.apache.sis.storage.gimi.isobmff.Box; +import org.apache.sis.storage.gimi.isobmff.gimi.ModelTransformationProperty; +import org.apache.sis.storage.gimi.isobmff.gimi.WellKnownText2Property; import org.apache.sis.storage.gimi.isobmff.iso23008_12.ImageSpatialExtents; import org.apache.sis.storage.tiling.TileMatrix; import org.apache.sis.storage.tiling.TileMatrixSet; import org.apache.sis.storage.tiling.TiledResource; import org.apache.sis.util.iso.Names; +import org.opengis.util.FactoryException; /** @@ -94,6 +97,8 @@ final class ResourceGrid extends MatrixGridRessource implements TiledResource, S } private synchronized void initialize() throws DataStoreException { + if (tileMatrix != null) return; + final Resource first = item.store.getComponent(item.references.get(0).toItemId[0]); if (first instanceof GridCoverageResource) { this.first = (GridCoverageResource) first; @@ -101,23 +106,54 @@ final class ResourceGrid extends MatrixGridRessource implements TiledResource, S 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); + final long[] tileSize = new long[]{tileExtent.getSize(0), tileExtent.getSize(1)}; + + ImageSpatialExtents imageExts = null; + ModelTransformationProperty modelTrs = null; + WellKnownText2Property modelWkt = null; + + for (Box box : item.properties) { + if (box instanceof ImageSpatialExtents) { + imageExts = (ImageSpatialExtents) box; + } else if (box instanceof ModelTransformationProperty) { + modelTrs = (ModelTransformationProperty) box; + } else if (box instanceof WellKnownText2Property) { + modelWkt = (WellKnownText2Property) box; + } + } + + if (modelWkt != null) { + try { + this.crs = modelWkt.toCRS(); + } catch (FactoryException ex) { + throw new DataStoreException(ex.getMessage(), ex); } + } else { + this.crs = null; + } + + MathTransform matrixGridToCrs; + if (modelTrs != null) { + matrixGridToCrs = modelTrs.toMathTransform(); + } else { + matrixGridToCrs = null; } + + //create tile matrix + GridGeometry tilingScheme = new GridGeometry(new GridExtent(imageExts.imageWidth, imageExts.imageHeight), PixelInCell.CELL_CENTER, matrixGridToCrs, crs); + tilingScheme = tilingScheme.derive().subgrid(null, tileSize).build(); //remove tile size from scheme + 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); + } + + void amendTilingScheme(GridGeometry tilingScheme, long[] tileSize) { + tileMatrix = new GimiTileMatrix(this, tilingScheme, tileSize); + tileMatrixSet = new GimiTileMatrixSet(Names.createLocalName(null, null, identifier.tip().toString() + "_tms"), crs); + tileMatrixSet.matrices.insertByScale(tileMatrix); } @Override diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageUncompressed.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageUncompressed.java index e1d66e52fb..bfd8883b51 100644 --- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageUncompressed.java +++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageUncompressed.java @@ -19,6 +19,7 @@ package org.apache.sis.storage.gimi; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Optional; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -30,7 +31,6 @@ import org.apache.sis.coverage.grid.GridCoverageBuilder; import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.GridGeometry; import org.apache.sis.coverage.grid.PixelInCell; -import org.apache.sis.referencing.CRS; import org.apache.sis.referencing.CommonCRS; import org.apache.sis.referencing.privy.AffineTransform2D; import org.apache.sis.storage.AbstractGridCoverageResource; @@ -44,7 +44,9 @@ import org.apache.sis.storage.gimi.isobmff.gimi.WellKnownText2Property; 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.gimi.isobmff.iso23008_12.PixelInformationProperty; import org.apache.sis.util.iso.Names; +import org.opengis.referencing.operation.MathTransform; /** @@ -58,8 +60,19 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements protected final GimiStore store; protected final Item item; private final GenericName identifier; - protected ComponentDefinition compDef; protected ImageSpatialExtents imageExt; + /** + * Can be null + */ + protected PixelInformationProperty pixelDef; + /** + /** + * Can be null + */ + protected ComponentDefinition compDef; + /** + * Can be null + */ protected UncompressedFrameConfig frameConf; /** * Can be null @@ -74,6 +87,12 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements */ protected WellKnownText2Property modelWkt; + + //computed values for decoding + private final int tileWidth; + private final int tileHeight; + private final int tileByteArrayLength; + public ResourceImageUncompressed(GimiStore store, Item item) throws DataStoreException { super(store); this.store = store; @@ -91,6 +110,8 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements modelTp = (ModelTiePointProperty) box; } else if (box instanceof WellKnownText2Property) { modelWkt = (WellKnownText2Property) box; + } else if (box instanceof PixelInformationProperty) { + pixelDef = (PixelInformationProperty) box; } } if (item.entry.itemName == null || item.entry.itemName.isBlank()) { @@ -98,6 +119,25 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements } else { this.identifier = Names.createLocalName(null, null, item.entry.itemName); } + + //pre-computed values + if (frameConf == null) { + //use a dumy one + frameConf = new UncompressedFrameConfig(); + frameConf.numTileColsMinusOne = 0; + frameConf.numTileRowsMinusOne = 0; + } + tileWidth = imageExt.imageWidth / (frameConf.numTileColsMinusOne+1); + tileHeight = imageExt.imageHeight / (frameConf.numTileRowsMinusOne+1); + + //TODO handle all kind of component length and subsampling + if (pixelDef != null) { + tileByteArrayLength = tileWidth * tileHeight * pixelDef.bitsPerChannel.length; + } else if (compDef != null) { + tileByteArrayLength = tileWidth * tileHeight * compDef.componentType.length; + } else { + throw new DataStoreException("Failed to compute tile sizein bytes"); + } } @Override @@ -114,21 +154,18 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements public GridGeometry getGridGeometry() throws DataStoreException { try { final GridExtent extent = new GridExtent(imageExt.imageWidth, imageExt.imageHeight); - final AffineTransform2D gridToCrs; + final MathTransform gridToCrs; if (modelTrs == null) { gridToCrs = new AffineTransform2D(1, 0, 0, 1, 0, 0); } else { - gridToCrs = new AffineTransform2D(modelTrs.transform[0], modelTrs.transform[3], modelTrs.transform[1], modelTrs.transform[4], modelTrs.transform[2], modelTrs.transform[5]); + gridToCrs = modelTrs.toMathTransform(); } final CoordinateReferenceSystem crs; if (modelWkt == null) { //TODO we should have an Image CRS - crs = CommonCRS.defaultGeographic(); + crs = CommonCRS.Engineering.GRID.crs(); } else { - String wkt = modelWkt.wkt2; - //TODO remove this hack when SIS support BASEGEOGCRS - wkt = wkt.replace("BASEGEOGCRS", "BASEGEODCRS"); - crs = CRS.fromWKT(wkt); + crs = modelWkt.toCRS(); } return new GridGeometry(extent, PixelInCell.CELL_CENTER, gridToCrs, crs); } catch (FactoryException ex) { @@ -139,20 +176,28 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements @Override public List<SampleDimension> getSampleDimensions() throws DataStoreException { final List<SampleDimension> sd = new ArrayList<>(); - for (int i = 0; i < compDef.componentType.length; i++) { - final SampleDimension.Builder sdb = new SampleDimension.Builder(); - switch (compDef.componentType[i]) { - case 4: - sdb.setName("Red"); - break; - case 5: - sdb.setName("Green"); - break; - case 6: - sdb.setName("Blue"); - break; + if (compDef != null) { + for (int i = 0; i < compDef.componentType.length; i++) { + final SampleDimension.Builder sdb = new SampleDimension.Builder(); + switch (compDef.componentType[i]) { + case 4: + sdb.setName("Red"); + break; + case 5: + sdb.setName("Green"); + break; + case 6: + sdb.setName("Blue"); + break; + } + sd.add(sdb.build()); + } + } else if (pixelDef != null) { + for (int i = 0; i < pixelDef.bitsPerChannel.length; i++) { + final SampleDimension.Builder sdb = new SampleDimension.Builder(); + sdb.setName(""+i); + sd.add(sdb.build()); } - sd.add(sdb.build()); } return sd; } @@ -160,15 +205,23 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements @Override public GridCoverage read(GridGeometry gg, int... ints) throws DataStoreException { final byte[] data = item.getData(); - final BufferedImage img = new BufferedImage(2048, 1024, BufferedImage.TYPE_3BYTE_BGR); - final WritableRaster raster = img.getRaster(); - for (int y = 0; y < 1024; y++) { - for (int x = 0; x < 2048; x++) { - int offset = y * 2048 + x; - 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); + + final BufferedImage img; + if ( (compDef != null && Arrays.equals(compDef.componentType, new int[]{4,5,6})) + || (pixelDef != null && pixelDef.bitsPerChannel.length == 3) + ) { + // RGB case + int width = imageExt.imageWidth; + int height = imageExt.imageHeight; + img = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); + final WritableRaster raster = img.getRaster(); + for (int y = 0; y <= frameConf.numTileRowsMinusOne; y++) { + for (int x = 0; x <= frameConf.numTileColsMinusOne; x++) { + readTile(data, x, y, raster, x*tileWidth, y*tileHeight); + } } + } else { + throw new DataStoreException("Unsupported component model"); } final GridGeometry gridGeometry = getGridGeometry(); GridCoverageBuilder gcb = new GridCoverageBuilder(); @@ -179,4 +232,25 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements return gcb.build(); } + /** + * + * @param data + * @param tileX starting from image left + * @param tileY starting from image top + */ + private void readTile(byte[] data, int tileX, int tileY, WritableRaster raster, int offsetX, int offsetY) { + final int tileOffset = (tileX + tileY * (frameConf.numTileColsMinusOne+1)) * tileByteArrayLength; + for (int y = 0; y < tileHeight; y++) { + for (int x = 0; x < tileWidth; x++) { + final int offset = y * tileWidth + x; + final int finalX = offsetX + x; + final int finalY = offsetY + y; + raster.setSample(finalX, finalY, 0, data[tileOffset + offset * 3] & 0xFF); + raster.setSample(finalX, finalY, 1, data[tileOffset + offset * 3 + 1] & 0xFF); + raster.setSample(finalX, finalY, 2, data[tileOffset + offset * 3 + 2] & 0xFF); + } + } + } + + } diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourcePyramid.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourcePyramid.java index 01529ac58c..ffef8b7d67 100644 --- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourcePyramid.java +++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourcePyramid.java @@ -17,7 +17,9 @@ package org.apache.sis.storage.gimi; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -27,6 +29,10 @@ import org.apache.sis.coverage.SampleDimension; import org.apache.sis.coverage.grid.GridCoverage; import org.apache.sis.coverage.grid.GridExtent; import org.apache.sis.coverage.grid.GridGeometry; +import org.apache.sis.coverage.grid.PixelInCell; +import org.apache.sis.referencing.CommonCRS; +import org.apache.sis.referencing.operation.transform.MathTransforms; +import org.apache.sis.referencing.privy.AffineTransform2D; import org.apache.sis.storage.AbstractGridCoverageResource; import org.apache.sis.storage.DataStore; import org.apache.sis.storage.DataStoreException; @@ -41,6 +47,8 @@ import org.apache.sis.storage.tiling.TileMatrix; import org.apache.sis.storage.tiling.TileMatrixSet; import org.apache.sis.storage.tiling.TiledResource; import org.apache.sis.util.iso.Names; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.MathTransform; /** @@ -74,8 +82,11 @@ final class ResourcePyramid extends AbstractGridCoverageResource implements Tile if (tileMatrixSet != null) { return; } - final GridCoverageResource first = (GridCoverageResource) store.getComponent(group.entitiesId[0]); - tileMatrixSet = new GimiTileMatrixSet(Names.createLocalName(null, null, getIdentifier().get().tip().toString() + "_tms"), first.getGridGeometry().getCoordinateReferenceSystem()); + + /* + * Find all resources of the pyramid + */ + final List<ResourceGrid> candidates = new ArrayList<>(); for (int i = 0; i < group.matrices.length; i++) { Resource res = store.getComponent(group.entitiesId[i]); if (res instanceof GridCoverageResource && !(res instanceof TiledResource)) { @@ -97,13 +108,54 @@ final class ResourcePyramid extends AbstractGridCoverageResource implements Tile } if (res instanceof ResourceGrid) { final ResourceGrid tr = (ResourceGrid) res; - final TileMatrix tm = tr.getTileMatrix(); - grids.put(tm.getIdentifier(), tr); - tileMatrixSet.matrices.insertByScale(tm); + candidates.add(tr); } else { throw new DataStoreException("A resource in the pyramid in not a coverage, itemId : " + group.entitiesId[i]); } } + + /* + * Sort by scale, lowest resolution at index 0. + * Only the most accurate matrix seems to contains georeferencing informations + */ + Collections.sort(candidates, (ResourceGrid o1, ResourceGrid o2) -> { + return Long.compare( + o2.getTileMatrix().getTilingScheme().getExtent().getSize(0), + o1.getTileMatrix().getTilingScheme().getExtent().getSize(0)); + }); + + /* + * Define each matrix CRS and transform based on the lowest one. + * each level is 2x resolution with the same tope left corner. + */ + final TileMatrix referenceMatrix = candidates.get(0).getTileMatrix(); + final GridGeometry reference = referenceMatrix.getTilingScheme(); + final MathTransform referenceTransform = reference.isDefined(GridGeometry.GRID_TO_CRS) ? reference.getGridToCRS(PixelInCell.CELL_CENTER) : new AffineTransform2D(1, 0, 0, 1, 0, 0); + final CoordinateReferenceSystem crs = reference.isDefined(GridGeometry.CRS) ? referenceMatrix.getTilingScheme().getCoordinateReferenceSystem() : CommonCRS.Engineering.GRID.crs(); + + tileMatrixSet = new GimiTileMatrixSet(Names.createLocalName(null, null, getIdentifier().get().tip().toString() + "_tms"), crs); + grids.put(referenceMatrix.getIdentifier(), candidates.get(0)); + tileMatrixSet.matrices.insertByScale(referenceMatrix); + final long[] tileSize = new long[]{group.tileSizeX, group.tileSizeY}; + + for (int i = 1, n = candidates.size(); i < n; i++) { + final ResourceGrid resource = candidates.get(i); + + final double scale = Math.pow(2, i); + final MathTransform scaleTrs = new AffineTransform2D(scale, 0, 0, scale, 0, 0); + + final GridGeometry fixed = new GridGeometry( + resource.getTileMatrix().getTilingScheme().getExtent(), + PixelInCell.CELL_CENTER, + MathTransforms.concatenate(scaleTrs, referenceTransform), + reference.getCoordinateReferenceSystem()); + + resource.amendTilingScheme(fixed, tileSize); + final TileMatrix matrix = resource.getTileMatrix(); + + grids.put(matrix.getIdentifier(), resource); + tileMatrixSet.matrices.insertByScale(matrix); + } } @Override 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 index e1892d9d24..cb02157a8d 100644 --- 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 @@ -42,7 +42,7 @@ public final class ScaleSortedMap<T extends TileMatrix> extends TreeMap<GenericN ArgumentChecks.ensureNonNull("identifier", id); final ScaleComparator comparator = (ScaleComparator) comparator(); if (comparator.matricesByScale.containsKey(id)) { - throw new IllegalArgumentException("Key " + id + "already exist"); + throw new IllegalArgumentException("Key already exist : " + id); } final double resolution = tileMatrix.getResolution()[0]; comparator.matricesByScale.put(id, resolution); diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/gimi/ModelTransformationProperty.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/gimi/ModelTransformationProperty.java index c6fc069376..d3f422c45a 100644 --- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/gimi/ModelTransformationProperty.java +++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/gimi/ModelTransformationProperty.java @@ -17,8 +17,10 @@ package org.apache.sis.storage.gimi.isobmff.gimi; import java.io.IOException; +import org.apache.sis.referencing.privy.AffineTransform2D; import org.apache.sis.storage.gimi.isobmff.ISOBMFFReader; import org.apache.sis.storage.gimi.isobmff.iso14496_12.ItemFullProperty; +import org.opengis.referencing.operation.MathTransform; /** @@ -42,5 +44,12 @@ public final class ModelTransformationProperty extends ItemFullProperty { } } + public MathTransform toMathTransform() { + if (transform.length == 6) { + return new AffineTransform2D(transform[0], transform[3], transform[1], transform[4], transform[2], transform[5]); + } else { + throw new UnsupportedOperationException("3D transform not supported yet"); + } + } } diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/gimi/WellKnownText2Property.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/gimi/WellKnownText2Property.java index e2c968b29d..2b5560e9fd 100644 --- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/gimi/WellKnownText2Property.java +++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/gimi/WellKnownText2Property.java @@ -17,8 +17,11 @@ package org.apache.sis.storage.gimi.isobmff.gimi; import java.io.IOException; +import org.apache.sis.referencing.CRS; import org.apache.sis.storage.gimi.isobmff.ISOBMFFReader; import org.apache.sis.storage.gimi.isobmff.iso14496_12.ItemFullProperty; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.util.FactoryException; /** @@ -36,4 +39,10 @@ public final class WellKnownText2Property extends ItemFullProperty { wkt2 = reader.readUtf8String(); } + public CoordinateReferenceSystem toCRS() throws FactoryException { + //TODO remove this hack when SIS support BASEGEOGCRS + String wkt = this.wkt2.replace("BASEGEOGCRS", "BASEGEODCRS"); + return CRS.fromWKT(wkt); + } + } diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso23001_17/TAIClockInfo.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso23001_17/TAIClockInfo.java index ac2254e2f1..0458e6bbce 100644 --- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso23001_17/TAIClockInfo.java +++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso23001_17/TAIClockInfo.java @@ -30,7 +30,7 @@ public final class TAIClockInfo extends FullBox { public static final String FCC = "taic"; - public long timeUncertainty; + public int timeUncertainty; public int clockResolution; public int clockDriftRate; public int unknown; @@ -38,7 +38,7 @@ public final class TAIClockInfo extends FullBox { @Override protected void readProperties(ISOBMFFReader reader) throws IOException { - timeUncertainty = reader.channel.readLong(); + timeUncertainty = reader.channel.readInt(); clockResolution = reader.channel.readInt(); clockDriftRate = reader.channel.readInt(); unknown = reader.channel.readInt();