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

commit b9a0ead72af5293156e1f0f07b277b22d431a8fb
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Mar 14 21:11:31 2019 +0100

    Move the calculation of sample range into getSampleRange() method since 
this information is expected to be requested only one or none at all.
    Take in account the number of bits per pixel. Reorder a few methods for 
keeping related methods together. Minor formatting.
---
 .../java/org/apache/sis/image/PixelIterator.java   | 95 ++++++++++++++--------
 .../org/apache/sis/image/LinearIteratorTest.java   | 14 ++--
 2 files changed, 68 insertions(+), 41 deletions(-)

diff --git 
a/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java 
b/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java
index ec36654..36861d7 100644
--- a/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java
+++ b/core/sis-raster/src/main/java/org/apache/sis/image/PixelIterator.java
@@ -25,14 +25,17 @@ import java.awt.image.Raster;
 import java.awt.image.RenderedImage;
 import java.awt.image.WritableRaster;
 import java.awt.image.WritableRenderedImage;
+import java.awt.image.SampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.awt.image.MultiPixelPackedSampleModel;
 import java.util.NoSuchElementException;
 import org.opengis.coverage.grid.SequenceType;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.measure.NumberRange;
 
 import static java.lang.Math.floorDiv;
 import static org.apache.sis.internal.util.Numerics.ceilDiv;
-import org.apache.sis.measure.NumberRange;
 
 
 /**
@@ -56,6 +59,7 @@ import org.apache.sis.measure.NumberRange;
  *
  * @author  Rémi Maréchal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
+ * @author  Johann Sorel (Geomatys)
  * @version 1.0
  * @since   1.0
  * @module
@@ -82,11 +86,6 @@ public abstract class PixelIterator {
     final int numBands;
 
     /**
-     * Value range supported by storage.
-     */
-    final NumberRange sampleRange;
-
-    /**
      * The domain, in pixel coordinates, of the region traversed by this pixel 
iterator.
      * This may be smaller than the image or raster bounds, but not greater.
      * The lower values are inclusive and the upper values exclusive.
@@ -131,7 +130,6 @@ public abstract class PixelIterator {
         image           = null;
         currentRaster   = data;
         numBands        = data.getNumBands();
-        sampleRange     = 
rangeForDataType(data.getSampleModel().getDataType());
         tileWidth       = data.getWidth();
         tileHeight      = data.getHeight();
         tileGridXOffset = data.getMinX();
@@ -161,7 +159,6 @@ public abstract class PixelIterator {
         final Rectangle bounds;
         image           = data;
         numBands        = data.getSampleModel().getNumBands();
-        sampleRange     = 
rangeForDataType(data.getSampleModel().getDataType());
         tileWidth       = data.getTileWidth();
         tileHeight      = data.getTileHeight();
         tileGridXOffset = data.getTileGridXOffset();
@@ -179,16 +176,6 @@ public abstract class PixelIterator {
         windowHeight    = (window != null) ? window.height : 0;
     }
 
-    private static NumberRange<?> rangeForDataType(int dataType) {
-        switch (dataType) {
-            case DataBuffer.TYPE_BYTE : return NumberRange.create(0, true, 
255, true);
-            case DataBuffer.TYPE_SHORT : return 
NumberRange.create(Short.MIN_VALUE, true, Short.MAX_VALUE, true);
-            case DataBuffer.TYPE_USHORT : return NumberRange.create(0, true, 
65535, true);
-            case DataBuffer.TYPE_INT : return 
NumberRange.create(Integer.MIN_VALUE, true, Integer.MAX_VALUE, true);
-            default : return NumberRange.create(Double.NEGATIVE_INFINITY, 
true, Double.POSITIVE_INFINITY, true);
-        }
-    }
-
     /**
      * Computes the intersection between the given bounds and and {@code 
subArea} if {@code subArea} is non-null.
      * If the result is empty, then the width and/or height are set to zero 
(not negative).
@@ -420,6 +407,57 @@ public abstract class PixelIterator {
     }
 
     /**
+     * Returns the range of sample values that can be stored in each band of 
the rendered image or raster.
+     * The range depends on the data type (byte, integer, <i>etc.</i>) and the 
number of bits per sample.
+     * If the samples are stored as floating point values, then the range is 
infinite (unbounded).
+     *
+     * <p>{@linkplain SinglePixelPackedSampleModel Some models} do not allow 
the same range of values for all bands.
+     * In such case, this method returns the largest range allowed by the 
model.</p>
+     *
+     * @return the range of valid sample values. May be unbounded.
+     */
+    public NumberRange<?> getSampleRange() {
+        final SampleModel model = (currentRaster != null) ? 
currentRaster.getSampleModel() : image.getSampleModel();
+        int numBits;
+        if (model instanceof MultiPixelPackedSampleModel) {
+            /*
+             * This model supports only unsigned integer types: 
DataBuffer.TYPE_BYTE, DataBuffer.TYPE_USHORT
+             * or DataBuffer.TYPE_INT (considered unsigned in the context of 
this sample model).  The number
+             * of bits per sample is defined by the "pixel bit stride".
+             */
+            numBits = ((MultiPixelPackedSampleModel) 
model).getPixelBitStride();
+        } else if (model instanceof SinglePixelPackedSampleModel) {
+            /*
+             * This model supports only unsigned integer types: TYPE_BYTE, 
TYPE_USHORT, TYPE_INT (considered
+             * unsigned in the context of this sample model). The number of 
bits may vary for each band.
+             */
+            numBits = 0;
+            for (int mask : ((SinglePixelPackedSampleModel) 
model).getBitMasks()) {
+                final int n = Integer.bitCount(mask);
+                if (n > numBits) numBits = n;
+            }
+        } else {
+            /*
+             * For all other sample models, the range is determined by the 
data type.
+             * The following cases invoke the NumberRange constructor which 
best fit the data type.
+             */
+            int type = DataBuffer.TYPE_UNDEFINED;
+            if (model != null) {
+                switch (type = model.getDataType()) {
+                    case DataBuffer.TYPE_BYTE:   return 
NumberRange.create((short) 0,                 true,  (short)   0xFF,            
true);
+                    case DataBuffer.TYPE_USHORT: return NumberRange.create(    
    0,                 true,          0xFFFF,            true);
+                    case DataBuffer.TYPE_SHORT:  return 
NumberRange.create(Short.  MIN_VALUE,         true,  Short.  MAX_VALUE,         
true);
+                    case DataBuffer.TYPE_INT:    return 
NumberRange.create(Integer.MIN_VALUE,         true,  Integer.MAX_VALUE,         
true);
+                    case DataBuffer.TYPE_FLOAT:  return 
NumberRange.create(Float.  NEGATIVE_INFINITY, false, Float.  POSITIVE_INFINITY, 
false);
+                    case DataBuffer.TYPE_DOUBLE: return 
NumberRange.create(Double. NEGATIVE_INFINITY, false, Double. POSITIVE_INFINITY, 
false);
+                }
+            }
+            throw new 
IllegalStateException(Errors.format(Errors.Keys.UnknownType_1, type));
+        }
+        return NumberRange.create(0, true, (1 << numBits) - 1, true);
+    }
+
+    /**
      * Returns the order in which pixels are traversed. {@link 
SequenceType#LINEAR} means that pixels on the first
      * row are traversed from left to right, then pixels on the second row 
from left to right, <i>etc.</i>
      * A {@code null} value means that the iteration order is unspecified.
@@ -429,17 +467,7 @@ public abstract class PixelIterator {
     public abstract SequenceType getIterationOrder();
 
     /**
-     * Returns the pixel coordinates of the region where this iterator is 
doing the iteration.
-     * If no region was specified at construction time, then this method 
returns the image or raster bounds.
-     *
-     * @return pixel coordinates of the iteration region.
-     */
-    public Rectangle getDomain() {
-        return new Rectangle(lowerX, lowerY, upperX - lowerX, upperY - lowerY);
-    }
-
-    /**
-     * Returns the number of bands (samples per pixel) from Image or Raster 
within this Iterator.
+     * Returns the number of bands (samples per pixel) in the image or raster.
      *
      * @return number of bands.
      */
@@ -448,12 +476,13 @@ public abstract class PixelIterator {
     }
 
     /**
-     * Returns the numeric range supported by datas from Image or Raster 
within this Iterator.
+     * Returns the pixel coordinates of the region where this iterator is 
doing the iteration.
+     * If no region was specified at construction time, then this method 
returns the image or raster bounds.
      *
-     * @return primitive samples range.
+     * @return pixel coordinates of the iteration region.
      */
-    public NumberRange<?> getSampleRange() {
-        return sampleRange;
+    public Rectangle getDomain() {
+        return new Rectangle(lowerX, lowerY, upperX - lowerX, upperY - lowerY);
     }
 
     /**
diff --git 
a/core/sis-raster/src/test/java/org/apache/sis/image/LinearIteratorTest.java 
b/core/sis-raster/src/test/java/org/apache/sis/image/LinearIteratorTest.java
index 3cb6835..aa86d81 100644
--- a/core/sis-raster/src/test/java/org/apache/sis/image/LinearIteratorTest.java
+++ b/core/sis-raster/src/test/java/org/apache/sis/image/LinearIteratorTest.java
@@ -25,18 +25,16 @@ import java.awt.image.Raster;
 import java.awt.image.WritableRaster;
 import java.awt.image.WritableRenderedImage;
 import java.nio.FloatBuffer;
+import org.opengis.coverage.grid.SequenceType;
 import org.apache.sis.test.DependsOnMethod;
 import org.apache.sis.test.TestCase;
 import org.apache.sis.util.ArraysExt;
 import org.junit.After;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 import org.junit.Ignore;
 import org.junit.Test;
-import org.opengis.coverage.grid.SequenceType;
+
+import static org.junit.Assert.*;
+
 
 /**
  * This base class tests the linear read-write iterator
@@ -47,7 +45,7 @@ import org.opengis.coverage.grid.SequenceType;
  * @version 1.0
  * @since   1.0
  */
-public class LinearIteratorTest extends TestCase {
+public final strictfp class LinearIteratorTest extends TestCase {
     /**
      * The pixel iterator being tested.
      * This field is initialized by a call to one of the {@code 
createPixelIterator(…)} methods.
@@ -230,7 +228,7 @@ public class LinearIteratorTest extends TestCase {
             }
             value += 7;             // Arbitrary offset.
         }
-        
+
         assertEquals("Number of expected values", expected.length, n);
         return image;
     }

Reply via email to