This is an automated email from the ASF dual-hosted git repository.
desruisseaux 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 beda4a8939 Add a verification of the "untiled.tiff" image created for
testing purposes in the previous commit.
beda4a8939 is described below
commit beda4a89390fcf1003e2c07ef4aa1100c5d81fef
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Feb 20 18:36:03 2026 +0100
Add a verification of the "untiled.tiff" image created for testing purposes
in the previous commit.
---
.../sis/coverage/grid/GridCoverageBuilder.java | 68 ++++++++++++++++++++--
.../main/module-info.java | 2 +-
.../sis/storage/geotiff/GeoTiffStoreTest.java | 67 +++++++++++++++++++--
.../org/apache/sis/storage/geotiff/ReaderTest.java | 9 +--
.../org/apache/sis/storage/geotiff/WriterTest.java | 4 +-
5 files changed, 132 insertions(+), 18 deletions(-)
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverageBuilder.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverageBuilder.java
index be3de3d5bd..d1ccc8dd0d 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverageBuilder.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverageBuilder.java
@@ -21,7 +21,8 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Hashtable;
-import static java.util.Objects.requireNonNull;
+import java.util.Objects;
+import java.util.function.IntBinaryOperator;
import java.awt.Point;
import java.awt.Dimension;
import java.awt.Rectangle;
@@ -34,6 +35,7 @@ import java.awt.image.SampleModel;
import java.awt.image.WritableRaster;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.image.DataType;
import org.apache.sis.image.PlanarImage;
import org.apache.sis.coverage.SampleDimension;
import org.apache.sis.image.internal.shared.ColorScaleBuilder;
@@ -92,7 +94,7 @@ import org.apache.sis.util.resources.Errors;
*
* @author Johann Sorel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
- * @version 1.4
+ * @version 1.7
*
* @see GridCoverage2D
* @see SampleDimension.Builder
@@ -301,7 +303,7 @@ public class GridCoverageBuilder {
* @see SampleDimension.Builder
*/
public GridCoverageBuilder addRange(final SampleDimension band) {
- requireNonNull(band);
+ Objects.requireNonNull(band);
if (!(ranges instanceof ArrayList<?>)) {
ranges = (ranges != null) ? new ArrayList<>(ranges) : new
ArrayList<>();
}
@@ -325,7 +327,7 @@ public class GridCoverageBuilder {
* @see BufferedImage
*/
public GridCoverageBuilder setValues(final RenderedImage data) {
- image = requireNonNull(data);
+ image = Objects.requireNonNull(data);
raster = null;
buffer = null;
size = null;
@@ -348,7 +350,7 @@ public class GridCoverageBuilder {
* @see Raster#createBandedRaster(int, int, int, int, Point)
*/
public GridCoverageBuilder setValues(final Raster data) {
- raster = requireNonNull(data);
+ raster = Objects.requireNonNull(data);
image = null;
buffer = null;
size = null;
@@ -386,6 +388,60 @@ public class GridCoverageBuilder {
return this;
}
+ /**
+ * Sets a two-dimensional slice to the values computed by the given
functions.
+ * The number of bands is the number of functions and the color model
defaults to gray scale.
+ * The tiling is unspecified and may change in future versions of Apache
<abbr>SIS</abbr>.
+ *
+ * <p>Each functions will receive pixel coordinates (<var>x</var>,
<var>y</var>)
+ * and shall return the sample value to store in one band of the image at
that pixel position.
+ * The <var>x</var> values will be between 0 inclusive and {@link
Dimension#width} exclusive.
+ * The <var>y</var> values will be between 0 inclusive and {@link
Dimension#height} exclusive.
+ * The functions may be invoked with pixel coordinates in any order.</p>
+ *
+ * @param type the type of values to store in the image.
+ * @param size the image size in pixels.
+ * @param bands functions providing sample values in each band, in order.
+ * @return {@code this} for method invocation chaining.
+ * @throws IllegalArgumentException if {@code width} or {@code height} is
negative or equals to zero.
+ *
+ * @since 1.7
+ */
+ public GridCoverageBuilder setValues(final DataType type, final Dimension
size, IntBinaryOperator... bands) {
+ final int width, height;
+ ArgumentChecks.ensureStrictlyPositive("width", width = size.width);
+ ArgumentChecks.ensureStrictlyPositive("height", height = size.height);
+ ArgumentChecks.ensureNonEmpty("bands", bands);
+ bands = bands.clone();
+ for (int b=0; b<bands.length; b++) {
+ ArgumentChecks.ensureNonNullElement("bands", b, bands[b]);
+ }
+ final WritableRaster data =
Raster.createBandedRaster(type.toDataBufferType(), width, height, bands.length,
null);
+ if (bands.length == 1) {
+ /*
+ * This block is not strictly necessary, as the following block is
general.
+ * But it is a slight optimization for a common case.
+ */
+ final IntBinaryOperator band = bands[0];
+ for (int y=0; y<height; y++) {
+ for (int x=0; x<width; x++) {
+ data.setSample(x, y, 0, band.applyAsInt(x, y));
+ }
+ }
+ } else {
+ final int[] samples = new int[bands.length];
+ for (int y=0; y<height; y++) {
+ for (int x=0; x<width; x++) {
+ for (int b=0; b<bands.length; b++) {
+ samples[b] = bands[b].applyAsInt(x, y);
+ }
+ data.setPixel(x, y, samples);
+ }
+ }
+ }
+ return setValues(data);
+ }
+
/**
* Reverses axis direction in the specified grid dimension.
* For example if grid indices are (<var>column</var>, <var>row</var>),
@@ -426,7 +482,7 @@ public class GridCoverageBuilder {
*/
@SuppressWarnings("UseOfObsoleteCollectionType")
public GridCoverageBuilder addImageProperty(final String key, final Object
value) {
- if (properties.putIfAbsent(requireNonNull(key, "key"),
requireNonNull(value, "value")) != null) {
+ if (properties.putIfAbsent(Objects.requireNonNull(key, "key"),
Objects.requireNonNull(value, "value")) != null) {
throw new
IllegalArgumentException(Errors.format(Errors.Keys.ElementAlreadyPresent_1,
key));
}
return this;
diff --git a/endorsed/src/org.apache.sis.storage.geotiff/main/module-info.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/module-info.java
index 3e4d1b77c9..e6e3125b05 100644
--- a/endorsed/src/org.apache.sis.storage.geotiff/main/module-info.java
+++ b/endorsed/src/org.apache.sis.storage.geotiff/main/module-info.java
@@ -22,7 +22,7 @@
* @author Thi Phuong Hao Nguyen (VNSC)
* @author Minh Chinh Vu (VNSC)
* @author Martin Desruisseaux (Geomatys)
- * @version 1.6
+ * @version 1.7
* @since 0.8
*/
module org.apache.sis.storage.geotiff {
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/GeoTiffStoreTest.java
b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/GeoTiffStoreTest.java
index 842426f4b8..61c02871cf 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/GeoTiffStoreTest.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/GeoTiffStoreTest.java
@@ -16,14 +16,23 @@
*/
package org.apache.sis.storage.geotiff;
+import java.util.Arrays;
import java.nio.file.Path;
import java.nio.file.Files;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import org.opengis.referencing.cs.AxisDirection;
+import org.opengis.referencing.operation.TransformException;
+import org.apache.sis.geometry.Envelopes;
+import org.apache.sis.geometry.GeneralEnvelope;
+import org.apache.sis.image.DataType;
import org.apache.sis.storage.DataStore;
import org.apache.sis.storage.DataStores;
-import org.apache.sis.storage.StorageConnector;
+import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.GridCoverageResource;
import org.apache.sis.coverage.grid.GridExtent;
import org.apache.sis.coverage.grid.GridGeometry;
@@ -31,6 +40,7 @@ import org.apache.sis.coverage.grid.PixelInCell;
import org.apache.sis.coverage.grid.GridCoverage;
import org.apache.sis.coverage.grid.GridCoverageBuilder;
import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.operation.transform.MathTransforms;
import org.apache.sis.referencing.operation.matrix.Matrix4;
@@ -48,11 +58,17 @@ import static
org.opengis.test.Assertions.assertAxisDirectionsEqual;
/**
* integration tests for {@link GeoTiffStore}.
+ * This class tests indirectly (via {@link GeoTiffStore}) the {@link Reader}
and {@link Writer} classes.
*
* @author Martin Desruisseaux (Geomatys)
*/
@SuppressWarnings("exports")
public final class GeoTiffStoreTest extends TestCase {
+ /**
+ * Name of a test file for an untiled image with a single band in
gray-scale.
+ */
+ static final String UNTILED = "untiled.tiff";
+
/**
* Creates a new test case.
*/
@@ -62,7 +78,7 @@ public final class GeoTiffStoreTest extends TestCase {
/**
* Tests writing an image with a non-linear vertical component in the
"grid to CRS" transform.
* This method merely tests that no exception is thrown during the
execution, and that reading
- * the image back can give back the three-dimensional <abbr>CRS</abbr>.
+ * the image gives back the three-dimensional <abbr>CRS</abbr>.
*
* @throws Exception if an error occurred while preparing or running the
test.
*/
@@ -81,14 +97,14 @@ public final class GeoTiffStoreTest extends TestCase {
final GridCoverage coverage = builder.build();
final Path file = Files.createTempFile("sis-test-", ".tiff");
try {
- try (DataStore store = DataStores.openWritable(new
StorageConnector(file), "GeoTIFF")) {
+ try (DataStore store = DataStores.openWritable(file, "GeoTIFF")) {
assertInstanceOf(GeoTiffStore.class, store).append(coverage,
null);
}
/*
* Read the image that we wrote in above block. This block merely
tests that no exception is thrown,
* and that the result has the expected number of dimensions, axis
order and scale factors.
*/
- try (DataStore store = DataStores.open(new StorageConnector(file),
"GeoTIFF")) {
+ try (DataStore store = DataStores.open(file, "GeoTIFF")) {
GridCoverageResource r =
assertSingleton(assertInstanceOf(GeoTiffStore.class, store).components());
GridGeometry gg = r.getGridGeometry();
assertEquals(3, gg.getDimension());
@@ -109,4 +125,47 @@ public final class GeoTiffStoreTest extends TestCase {
Files.delete(file);
}
}
+
+ /**
+ * Writes an image and compare with the {@code "untiled.tiff"} file.
+ * This is an anti-regression test, as this test does not inspect the
+ * content of the file.
+ *
+ * @throws TransformException if an error occurred while computing the
domain of the image.
+ * @throws DataStoreException if an error occurred while writing the
GeoTIFF file.
+ * @throws IOException if an error occurred while reading the file of
expected content.
+ */
+ @Test
+ public void testWriteUntiled() throws TransformException,
DataStoreException, IOException {
+ var geographicArea = new GeneralEnvelope(CommonCRS.WGS84.geographic());
+ geographicArea.setRange(0, 32, 40); // Range of latitude values.
+ geographicArea.setRange(1, 137, 140); // Range of longitude values.
+ final GridCoverage coverage = new GridCoverageBuilder()
+ .setDomain(Envelopes.transform(geographicArea,
CommonCRS.WGS84.universal(35, 139)))
+ .setValues(DataType.BYTE, new Dimension(32, 16), (x, y) -> 100
* y + x)
+ .flipGridAxis(1)
+ .build();
+
+ final var buffer = new ByteArrayOutputStream(2284);
+ try (DataStore ds = DataStores.openWritable(buffer, "geotiff")) {
+ assertInstanceOf(GeoTiffStore.class, ds).append(coverage, null);
+ }
+ final byte[] actual = buffer.toByteArray();
+ final byte[] expected;
+ try (InputStream in =
GeoTiffStoreTest.class.getResourceAsStream(UNTILED)) {
+ assertNotNull(in, UNTILED);
+ expected = in.readAllBytes();
+ }
+ /*
+ * We tolerance mismatch far enough in the file, because they may be
caused
+ * by differences in the way that the CRS is encoded. So we verify
that at
+ * least the beginning of the header matches.
+ */
+ final int i = Arrays.mismatch(expected, actual);
+ if (i >= 0 && i < 1000) {
+ assertArrayEquals(expected, actual);
+ } else {
+ assertEquals(expected.length, actual.length);
+ }
+ }
}
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/ReaderTest.java
b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/ReaderTest.java
index 360d928fa8..fd9afada3a 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/ReaderTest.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/ReaderTest.java
@@ -41,6 +41,8 @@ import org.apache.sis.test.TestCase;
/**
* Tests a few read operations.
+ * Despite the name of this test class, the {@link Reader} class is not tested
directly
+ * but indirectly via {@link GeoTiffStore}.
*
* @author Martin Desruisseaux (Geomatys)
*
@@ -48,11 +50,6 @@ import org.apache.sis.test.TestCase;
*/
@SuppressWarnings("exports")
public class ReaderTest extends TestCase {
- /**
- * Name of the test file.
- */
- private static final String FILENAME = "untiled.tiff";
-
/**
* Creates a new test case.
*/
@@ -66,7 +63,7 @@ public class ReaderTest extends TestCase {
* @throws DataStoreException if an error occurred while creating the data
store.
*/
private static GeoTiffStore createStore() throws DataStoreException {
- return new GeoTiffStore(null, new
StorageConnector(ReaderTest.class.getResource(FILENAME)));
+ return new GeoTiffStore(null, new
StorageConnector(ReaderTest.class.getResource(GeoTiffStoreTest.UNTILED)));
}
/**
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/WriterTest.java
b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/WriterTest.java
index 71f318e57c..2c11154faa 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/WriterTest.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/WriterTest.java
@@ -57,6 +57,8 @@ import
org.apache.sis.referencing.operation.HardCodedConversions;
/**
* Tests {@link Writer}.
+ * Despite the name of this test class, the {@link Writer} class is not tested
directly
+ * but indirectly via {@link GeoTiffStore}.
*
* @author Erwan Roussel (Geomatys)
* @author Martin Desruisseaux (Geomatys)
@@ -88,7 +90,7 @@ public final class WriterTest extends TestCase {
/**
* The channel where the image is written.
- * The data can be obtained by a call to {@link
ByteArrayChannel#toBuffer()}.
+ * The data can be obtained by a call to {@lingk
ByteArrayChannel#toBuffer()}.
*/
private ByteArrayChannel output;