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
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new c13530cdad Try harder to build a sample model when there is
insuffisient information.
c13530cdad is described below
commit c13530cdad217d0fdcf85c75598c219b8bfe424b
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Jun 19 19:18:15 2026 +0200
Try harder to build a sample model when there is insuffisient information.
---
.../org/apache/sis/storage/geoheif/ImageModel.java | 26 +++++++++++++++++-----
.../sis/storage/geoheif/UncompressedImage.java | 4 ++--
2 files changed, 23 insertions(+), 7 deletions(-)
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 a8d64494bd..d623266779 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
@@ -37,6 +37,7 @@ import org.apache.sis.storage.isobmff.mpeg.ComponentType;
import org.apache.sis.storage.isobmff.mpeg.ComponentPalette;
import org.apache.sis.storage.isobmff.mpeg.InterleavingMode;
import org.apache.sis.storage.isobmff.mpeg.UncompressedFrameConfig;
+import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.internal.shared.Numerics;
@@ -113,7 +114,7 @@ final class ImageModel {
final int nc = (model == null) ? 0 : model.components.length;
final int nt = (componentTypes == null) ? 0 : componentTypes.length;
final int ns = (bitsPerChannel == null) ? 0 : bitsPerChannel.length;
- final int numBands = Math.max(nc, nt); // Ignore `ns` as it is
sometime too large (for an unknown reason).
+ final int numBands = (nc|nt) != 0 ? Math.max(nc, nt) : ns; // For an
unknown reason `ns` is sometime larger.
final var bitsPerSample = new int[numBands];
final var sb = new SampleDimension.Builder();
sampleDimensions = new SampleDimension[numBands];
@@ -121,7 +122,7 @@ final class ImageModel {
@SuppressWarnings("LocalVariableHidesMemberVariable")
DataType dataType = null;
- int numBits=0, redMask=0, greenMask=0, blueMask=0, alphaMask=0;
+ int numBits=0, maxBits=0, redMask=0, greenMask=0, blueMask=0,
alphaMask=0;
int grayBand = -1, indexBand = -1, alphaBand = -1; // Negative
value means none.
for (int band = 0; band < numBands; band++) {
/*
@@ -181,6 +182,7 @@ final class ImageModel {
*/
bitsPerSample[band] = bitDepth;
numBits += bitDepth;
+ maxBits = Math.max(maxBits, bitDepth);
if (colorType instanceof ComponentType ct) {
int mask = 0;
if (numBits < Integer.SIZE) {
@@ -196,7 +198,7 @@ final class ImageModel {
}
}
}
- final boolean isRGB = (redMask | greenMask | blueMask) != 0;
+ boolean isRGB = (redMask | greenMask | blueMask) != 0;
if (isRGB && numBits < Integer.SIZE) {
final int n = Integer.SIZE - numBits; // Number of unused bits.
redMask >>>= n;
@@ -205,12 +207,26 @@ final class ImageModel {
alphaMask >>>= n;
}
/*
- * Build a sample model. The `InterleavingMode.COMPONENT` default
value is arbitrary,
+ * If there is no information about sample model except the number of
bits per channel,
+ * default to component sample model with the smallest type capable to
store the number
+ * of bits. Note: missing `UncompressedFrameConfig` box is illegal. We
try to be robust,
+ * but we should also be a little bit conservative.
+ */
+ if (dataType == null && maxBits != 0) {
+ final var type = DataType.forNumberOfBits(maxBits, false, false);
+ if (ArraysExt.allEquals(bitsPerSample, type.size())) {
+ dataType = type;
+ isRGB = (numBands >= 3);
+ }
+ }
+ /*
+ * Build a sample model. The `InterleavingMode.PIXEL` default value is
arbitrary,
* as the `UncompressedFrameConfig` box is mandatory according ISO/IEC
23001-17:2024.
+ * However, it matches the behavior that we observed with some OGC
Testbed-20 data.
*/
this.dataType = dataType;
if (dataType != null) {
- final InterleavingMode interleaveType = (model != null) ?
model.interleaveType : InterleavingMode.COMPONENT;
+ final InterleavingMode interleaveType = (model != null) ?
model.interleaveType : InterleavingMode.PIXEL;
if (tileSize == null) {
tileSize = new Dimension(width, height);
if (model != null) {
diff --git
a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java
b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java
index db2fc606a3..070f6161a5 100644
---
a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java
+++
b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java
@@ -202,8 +202,8 @@ class UncompressedImage extends Image {
}
/*
* Now read all banks and store the values in the image buffer.
- * If there is many banks (`InterleavingMode.COMPONENT`), these
- * banks are assumed consecutive.
+ * If there are many banks (`InterleavingMode.COMPONENT`),
+ * these banks are assumed consecutive.
*/
input.buffer.order(byteOrder);
final var hr = new
HyperRectangleReader(ImageUtilities.toNumberEnum(dataType), input);