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 35d0e9d06ea9996369c5b449ef4063d8c61ad679
Author: jsorel <[email protected]>
AuthorDate: Wed Jun 3 15:27:39 2026 +0200

    feat(GeoHeif): support auxilary prj and hfw files
---
 .../sis/storage/geoheif/CoverageBuilder.java       | 74 ++++++++++++++++++++++
 1 file changed, 74 insertions(+)

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 ab53ba7e16..46c18e7320 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
@@ -32,6 +32,12 @@ import java.awt.Dimension;
 import java.awt.image.ColorModel;
 import java.awt.image.SampleModel;
 import java.awt.image.RasterFormatException;
+import java.io.EOFException;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
 import javax.imageio.ImageTypeSpecifier;
 import org.opengis.util.GenericName;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
@@ -44,6 +50,7 @@ import org.apache.sis.coverage.SampleDimension;
 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.io.stream.IOUtilities;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.metadata.MetadataBuilder;
 import org.apache.sis.storage.modifier.CoverageModifier;
@@ -66,8 +73,14 @@ import org.apache.sis.util.collection.Containers;
 import org.apache.sis.util.internal.shared.Numerics;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.pending.jdk.JDK18;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.internal.shared.AffineTransform2D;
+import org.apache.sis.storage.*;
+import org.apache.sis.storage.base.AuxiliaryContent;
 import org.apache.sis.storage.isobmff.mpeg.CompressedUnitsItemInfo;
 import org.apache.sis.storage.isobmff.mpeg.CompressionConfiguration;
+import org.apache.sis.util.CharSequences;
+import org.opengis.util.FactoryException;
 
 
 /**
@@ -713,10 +726,25 @@ final class CoverageBuilder implements Emptiable {
         MathTransform gridToCRS = null;
         if (affine != null) {
             gridToCRS = affine.toMathTransform();
+        } else {
+            try {
+                gridToCRS = readWorldFile("hfw");
+            } catch (URISyntaxException | IOException ex) {
+                throw new DataStoreException(ex);
+            }
         }
         CoordinateReferenceSystem crs = null;
         if (crsDefinition != null) {
             crs = crsDefinition.toCRS(store.listeners());     // May stil be 
null.
+        } else {
+            try {
+                AuxiliaryContent aux = store.readAuxiliaryPath("prj");
+                crs = CRS.fromWKT(aux.toString());
+            } catch (NoSuchFileException e)  {
+                //no file
+            } catch (URISyntaxException | IOException | FactoryException ex) {
+                throw new DataStoreException(ex);
+            }
         }
         var gridGeometry = new GridGeometry(extent, PixelInCell.CELL_CORNER, 
gridToCRS, crs);
         metadata().addSpatialRepresentation(null, gridGeometry, false);
@@ -726,4 +754,50 @@ final class CoverageBuilder implements Emptiable {
         var source = new CoverageModifier.Source(store, imageIndex, dataType);
         return store.customizer.customize(source, gridGeometry);
     }
+
+    /**
+     * Reads the "World file" by parsing an auxiliary file with the given 
suffix.
+     *
+     * @param  wld  suffix of the auxiliary file.
+     * @return the "World file" content as an affine transform, or {@code 
null} if none was found.
+     * @throws URISyntaxException if an error occurred while normalizing the 
URI.
+     * @throws IOException if an I/O error occurred.
+     * @throws DataStoreException if the file content cannot be parsed.
+     */
+    private AffineTransform2D readWorldFile(final String wld)
+            throws URISyntaxException, IOException, DataStoreException
+    {
+        final AuxiliaryContent content;
+        try {
+            content = store.readAuxiliaryPath(wld);
+        } catch (NoSuchFileException e) {
+            return null;
+        }
+        if (content == null) {
+            return null;
+        }
+        final String         filename = content.getFilename();
+        final CharSequence[] lines    = CharSequences.splitOnEOL(content);
+        final int            expected = 6;        // Expected number of 
elements.
+        int                  count    = 0;        // Actual number of elements.
+        final double[]       elements = new double[expected];
+        for (int i=0; i<expected; i++) {
+            final String line = lines[i].toString().trim();
+            if (!line.isEmpty() && line.charAt(0) != '#') {
+                if (count >= expected) {
+                    throw new 
DataStoreContentException(Errors.forLocale(store.getLocale()).getString(Errors.Keys.TooManyOccurrences_2,
 expected, "coefficient"));
+                }
+                try {
+                    elements[count++] = Double.parseDouble(line);
+                } catch (NumberFormatException e) {
+                    throw new 
DataStoreContentException(Errors.forLocale(store.getLocale()).getString(Errors.Keys.ErrorInFileAtLine_2,
 filename, i), e);
+                }
+            }
+        }
+        if (count != expected) {
+            throw new 
EOFException(Errors.forLocale(store.getLocale()).getString(Errors.Keys.UnexpectedEndOfFile_1,
 filename));
+        }
+        return new AffineTransform2D(elements);
+    }
+
 }

Reply via email to