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 750eb6c19c World File reader/writer should accepts Image I/O 
reader/writer directly. Move package documentation to the data store classes.
750eb6c19c is described below

commit 750eb6c19cf6af33de2e09f16fe112d101cd7656
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Apr 21 00:48:18 2022 +0200

    World File reader/writer should accepts Image I/O reader/writer directly.
    Move package documentation to the data store classes.
---
 .../apache/sis/internal/storage/URIDataStore.java  | 14 ++++--
 .../apache/sis/internal/storage/image/Store.java   | 54 +++++++++++++++++++++-
 .../sis/internal/storage/image/StoreProvider.java  | 17 ++++++-
 .../sis/internal/storage/image/WritableStore.java  | 22 ++++++++-
 .../sis/internal/storage/image/package-info.java   | 37 +++------------
 5 files changed, 106 insertions(+), 38 deletions(-)

diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java
index 32b1b139cc..62bb5e09e9 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/URIDataStore.java
@@ -16,9 +16,11 @@
  */
 package org.apache.sis.internal.storage;
 
+import java.util.Optional;
+import java.io.DataOutput;
+import java.io.OutputStream;
 import java.io.File;
 import java.net.URI;
-import java.util.Optional;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
@@ -316,12 +318,18 @@ public abstract class URIDataStore extends DataStore 
implements StoreResource, R
         }
 
         /**
-         * Returns {@code true} if the open options contains {@link 
StandardOpenOption#WRITE}.
+         * Returns {@code true} if the open options contains {@link 
StandardOpenOption#WRITE}
+         * or if the storage type is some kind of output stream.
          *
          * @param  connector  the connector to use for opening a file.
          * @return whether the specified connector should open a writable data 
store.
+         * @throws DataStoreException if the storage object has already been 
used and can not be reused.
          */
-        public static boolean isWritable(final StorageConnector connector) {
+        public static boolean isWritable(final StorageConnector connector) 
throws DataStoreException {
+            final Object storage = connector.getStorage();
+            if (storage instanceof OutputStream || storage instanceof 
DataOutput) {
+                return true;
+            }
             return 
ArraysExt.contains(connector.getOption(OptionKey.OPEN_OPTIONS), 
StandardOpenOption.WRITE);
         }
     }
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java
index 9b4846d6d8..d129a7513b 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/Store.java
@@ -31,6 +31,7 @@ import java.nio.file.NoSuchFileException;
 import java.nio.file.StandardOpenOption;
 import javax.imageio.ImageIO;
 import javax.imageio.ImageReader;
+import javax.imageio.ImageWriter;
 import javax.imageio.spi.ImageReaderSpi;
 import javax.imageio.stream.ImageInputStream;
 import org.opengis.metadata.Metadata;
@@ -64,8 +65,47 @@ import org.apache.sis.setup.OptionKey;
 
 
 /**
- * A data store which creates grid coverages from Image I/O.
- * The store is considered as an aggregate, with one resource per image.
+ * A data store which creates grid coverages from Image I/O readers using 
<cite>World File</cite> convention.
+ * Georeferencing is defined by two auxiliary files having the same name than 
the image file but different suffixes:
+ *
+ * <ul class="verbose">
+ *   <li>A text file containing the coefficients of the affine transform 
mapping pixel coordinates to geodesic coordinates.
+ *     The reader expects one coefficient per line, in the same order than the 
order expected by the
+ *     {@link java.awt.geom.AffineTransform#AffineTransform(double[]) 
AffineTransform(double[])} constructor, which is
+ *     <var>scaleX</var>, <var>shearY</var>, <var>shearX</var>, 
<var>scaleY</var>, <var>translateX</var>, <var>translateY</var>.
+ *     The reader looks for a file having the following suffixes, in 
preference order:
+ *     <ol>
+ *       <li>The first letter of the image file extension, followed by the 
last letter of
+ *         the image file extension, followed by {@code 'w'}. Example: {@code 
"tfw"} for
+ *         {@code "tiff"} images, and {@code "jgw"} for {@code "jpeg"} 
images.</li>
+ *       <li>The extension of the image file with a {@code 'w'} appended.</li>
+ *       <li>The {@code "wld"} extension.</li>
+ *     </ol>
+ *   </li>
+ *   <li>A text file containing the <cite>Coordinate Reference System</cite> 
(CRS) definition
+ *     in <cite>Well Known Text</cite> (WKT) syntax.
+ *     The reader looks for a file having the {@code ".prj"} extension.</li>
+ * </ul>
+ *
+ * Every auxiliary text file are expected to be encoded in UTF-8
+ * and every numbers are expected to be formatted in US locale.
+ *
+ * <h2>Type of input objects</h2>
+ * The {@link StorageConnector} input should be an instance of the following 
types:
+ * {@link java.nio.file.Path}, {@link java.io.File}, {@link java.net.URL} or 
{@link java.net.URI}.
+ * Other types such as {@link ImageInputStream} are also accepted but in those 
cases the auxiliary files can not be read.
+ * For any input of unknown type, this data store first checks if an {@link 
ImageReader} accepts the input type directly.
+ * If none is found, this data store tries to {@linkplain 
ImageIO#createImageInputStream(Object) create an input stream}
+ * from the input object.
+ *
+ * <p>The storage input object may also be an {@link ImageReader} instance 
ready for use
+ * (i.e. with its {@linkplain ImageReader#setInput(Object) input set} to a 
non-null value).
+ * In that case, this data store will use the given image reader as-is.</p>
+ *
+ * <h2>Handling of multi-image files</h2>
+ * Because some image formats can store an arbitrary amount of images,
+ * this data store is considered as an aggregate with one resource per image.
+ * All image should have the same size and all resources will share the same 
{@link GridGeometry}.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 1.2
@@ -173,6 +213,16 @@ class Store extends PRJDataStore implements Aggregate {
     {
         super(provider, connector);
         final Object storage = connector.getStorage();
+        if (storage instanceof ImageReader) {
+            reader = (ImageReader) storage;
+            suffix = IOUtilities.extension(reader.getInput());
+            configureReader();
+            return;
+        }
+        if (storage instanceof ImageWriter) {
+            suffix = IOUtilities.extension(((ImageWriter) 
storage).getOutput());
+            return;
+        }
         suffix = IOUtilities.extension(storage);
         if (!(readOnly || fileExists(connector))) {
             /*
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/StoreProvider.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/StoreProvider.java
index d987c2ca45..563dafcd46 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/StoreProvider.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/StoreProvider.java
@@ -18,7 +18,10 @@ package org.apache.sis.internal.storage.image;
 
 import java.util.Set;
 import java.util.HashSet;
+import java.io.DataOutput;
 import java.io.IOException;
+import javax.imageio.ImageReader;
+import javax.imageio.ImageWriter;
 import javax.imageio.spi.ImageReaderSpi;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
@@ -67,6 +70,8 @@ public final class StoreProvider extends 
PRJDataStore.Provider {
 
     /**
      * Returns a {@link Store} implementation associated with this provider.
+     * The data store will be writable if {@link 
java.nio.file.StandardOpenOption#WRITE} is provided,
+     * or if the storage is a writable object such as {@link 
javax.imageio.stream.ImageOutputStream}.
      *
      * @param  connector  information about the storage (URL, stream, 
<i>etc</i>).
      * @return a data store implementation associated with this provider for 
the given storage.
@@ -74,8 +79,18 @@ public final class StoreProvider extends 
PRJDataStore.Provider {
      */
     @Override
     public DataStore open(final StorageConnector connector) throws 
DataStoreException {
+        final Object storage = connector.getStorage();
+        boolean isWritable = (storage instanceof ImageWriter);
+        if (!isWritable) {
+            if (storage instanceof ImageReader) {
+                Object input = ((ImageReader) storage).getInput();
+                isWritable = (input instanceof DataOutput);         // Parent 
of ImageOutputStream.
+            } else {
+                isWritable = isWritable(connector);
+            }
+        }
         try {
-            if (isWritable(connector)) {
+            if (isWritable) {
                 return new WritableStore(this, connector);
             } else {
                 return new Store(this, connector, true);
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/WritableStore.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/WritableStore.java
index 986105f849..e20c3c7263 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/WritableStore.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/WritableStore.java
@@ -52,7 +52,20 @@ import org.apache.sis.setup.OptionKey;
 
 
 /**
- * A data store with writing capabilities.
+ * A data store which writes grid coverages using Image I/O writers completed 
by the <cite>World File</cite> convention.
+ * Georeferencing is defined by two auxiliary files described in the {@link 
Store} parent class.
+ *
+ * <h2>Type of output objects</h2>
+ * The {@link StorageConnector} output should be an instance of the following 
types:
+ * {@link java.nio.file.Path}, {@link java.io.File}, {@link java.net.URL} or 
{@link java.net.URI}.
+ * Other types such as {@link ImageOutputStream} are also accepted but in 
those cases the auxiliary files can not be written.
+ * For any output of unknown type, this data store first checks if an {@link 
ImageWriter} accepts the output type directly.
+ * If none is found, this data store tries to {@linkplain 
ImageIO#createImageOutputStream(Object) create an output stream}
+ * from the output object.
+ *
+ * <p>The storage input object may also be an {@link ImageWriter} instance 
ready for use
+ * (i.e. with its {@linkplain ImageWriter#setOutput(Object) output set} to a 
non-null value).
+ * In that case, this data store will use the given image writer as-is.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 1.2
@@ -95,11 +108,17 @@ final class WritableStore extends Store implements 
WritableAggregate {
             throws DataStoreException, IOException
     {
         super(provider, connector, false);
+        final Object storage = connector.getStorage();
         final ImageReader reader = getCurrentReader();
         final Object inout;
         if (reader != null) {
             inout = reader.getInput();
             numImages = -1;
+        } else if (storage instanceof ImageWriter) {
+            writer = (ImageWriter) storage;
+            inout  = writer.getOutput();
+            configureWriter();
+            numImages = -1;
         } else {
             /*
              * If it was possible to initialize an image reader, wait to see 
if an image writer is needed.
@@ -115,7 +134,6 @@ final class WritableStore extends Store implements 
WritableAggregate {
                 writer = FormatFilter.SUFFIX.createWriter(null, connector, 
null, deferred);
 fallback:       if (writer == null) {
                     ImageOutputStream stream = null;
-                    final Object storage = connector.getStorage();
                     for (final Map.Entry<ImageWriterSpi,Boolean> entry : 
deferred.entrySet()) {
                         if (entry.getValue()) {
                             if (stream == null) {
diff --git 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/package-info.java
 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/package-info.java
index 2912efae95..60397f5937 100644
--- 
a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/package-info.java
+++ 
b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/image/package-info.java
@@ -16,40 +16,17 @@
  */
 
 /**
- * {@link org.apache.sis.storage.DataStore} implementation for Image I/O.
- * This data store wraps Image I/O reader and wrapper for image format such as 
TIFF, PNG or JPEG.
- * The data store delegates the reading and writing of pixel values to the 
wrapped reader or writer,
- * and additionally looks for two small text files in the same directory than 
the image file
- * with the same filename but a different extension:
- *
- * <ul class="verbose">
- *   <li>A text file containing the coefficients of the affine transform 
mapping pixel
- *       coordinates to geodesic coordinates. The reader expects one 
coefficient per line,
- *       in the same order than the one expected by the
- *       {@link java.awt.geom.AffineTransform#AffineTransform(double[]) 
AffineTransform(double[])}
- *       constructor, which is <var>scaleX</var>, <var>shearY</var>, 
<var>shearX</var>,
- *       <var>scaleY</var>, <var>translateX</var>, <var>translateY</var>.
- *       The reader looks for a file having the following extensions, in 
preference order:
- *       <ol>
- *         <li>The first letter of the image file extension, followed by the 
last letter of
- *             the image file extension, followed by {@code 'w'}. Example: 
{@code "tfw"} for
- *             {@code "tiff"} images, and {@code "jgw"} for {@code "jpeg"} 
images.</li>
- *         <li>The extension of the image file with a {@code 'w'} 
appended.</li>
- *         <li>The {@code "wld"} extension.</li>
- *       </ol>
- *   </li>
- *   <li>A text file containing the <cite>Coordinate Reference System</cite> 
(CRS)
- *       definition in <cite>Well Known Text</cite> (WKT) syntax. The reader 
looks
- *       for a file having the {@code ".prj"} extension.</li>
- * </ul>
- *
- * Every text file are expected to be encoded in ISO-8859-1 (a.k.a. 
ISO-LATIN-1)
- * and every numbers are expected to be formatted in US locale.
+ * Bridges between Apache SIS data stores and Java Image I/O.
+ * This package provides {@link org.apache.sis.storage.DataStore} 
implementations wrapping
+ * {@link javax.imageio.ImageReader} and {@link javax.imageio.ImageWriter} 
instances.
+ * The data stores delegate the reading and writing of pixel values to the 
wrapped reader or writer,
+ * completed with an additional source of information for georeferencing the 
image.
+ * A commonly-used convention is the <cite>World File</cite> format.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 1.2
  *
- * @see <a href="https://en.wikipedia.org/wiki/World_file";>World File Format 
Description</a>
+ * @see <a href="https://en.wikipedia.org/wiki/World_file";>World File format 
description on Wikipedia</a>
  *
  * @since 1.2
  * @module

Reply via email to