Avoid range collision if the minimum or maximum value in a netCDF file is equals to a pad/fill value.
diff --git a/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_C.java b/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_C.java
index b74c9c4..bd14569 100644
--- a/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_C.java
+++ b/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/GCOM_C.java
@@ -110,7 +110,7 @@
  *
  * @author  Alexis Manin (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
  *
  * @see <a href="http://global.jaxa.jp/projects/sat/gcom_c/">SHIKISAI (GCOM-C) on JAXA</a>
  * @see <a href="https://en.wikipedia.org/wiki/Global_Change_Observation_Mission">GCOM on Wikipedia</a>
@@ -430,11 +430,12 @@
      * Returns the range of valid values, or {@code null} if unknown.
      *
      * @param  data  the variable to get valid range of values for.
+     * @param  nodataValues  the fill values and padding values.
      * @return the range of valid values, or {@code null} if unknown.
      */
     @Override
-    public NumberRange<?> validRange(final Variable data) {
-        NumberRange<?> range = super.validRange(data);
+    public NumberRange<?> validRange(final Variable data, final Set<Number> nodataValues) {
+        NumberRange<?> range = super.validRange(data, nodataValues);
         if (range == null) {
             final double min = data.getAttributeAsNumber("Minimum_valid_DN");
             final double max = data.getAttributeAsNumber("Maximum_valid_DN");
@@ -470,7 +471,7 @@
 
     /**
      * Builds the function converting values from their packed formats in the variable to "real" values.
-     * This method is invoked only if {@link #validRange(Variable)} returned a non-null value.
+     * This method is invoked only if {@link #validRange(Variable, Set)} returned a non-null value.
      *
      * @param  data  the variable from which to determine the transfer function.
      * @return a transfer function built from the attributes defined in the given variable.
diff --git a/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/package-info.java b/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/package-info.java
index f353184..1381a2a 100644
--- a/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/package-info.java
+++ b/profiles/sis-japan-profile/src/main/java/org/apache/sis/internal/earth/netcdf/package-info.java
@@ -21,7 +21,7 @@
  *
  * @author  Alexis Manin (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
  * @since   1.0
  * @module
  */
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
index 6310d20..03c3666 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Convention.java
@@ -63,7 +63,7 @@
  * @author  Johann Sorel (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Alexis Manin (Geomatys)
- * @version 1.0
+ * @version 1.1
  *
  * @see <a href="https://issues.apache.org/jira/browse/SIS-315">SIS-315</a>
  *
@@ -92,7 +92,7 @@
     /**
      * Names of attributes where to fetch minimum and maximum sample values, in preference order.
      *
-     * @see #validRange(Variable)
+     * @see #validRange(Variable, Set)
      */
     private static final String[] RANGE_ATTRIBUTES = {
         "valid_range",      // Expected "reasonable" range for variable.
@@ -555,13 +555,13 @@
      * Otherwise if this method returns the range of real values, then that range shall be an instance
      * of {@link MeasurementRange} for allowing the caller to distinguish the two cases.
      *
-     * @param  data  the variable to get valid range of values for.
-     *               This is usually a variable containing raster data.
+     * @param  data  the variable to get valid range of values for (usually a variable containing raster data).
+     * @param  nodataValues  the fill values and padding values.
      * @return the range of valid values, or {@code null} if unknown.
      *
      * @see Variable#getRangeFallback()
      */
-    public NumberRange<?> validRange(final Variable data) {
+    public NumberRange<?> validRange(final Variable data, final Set<Number> nodataValues) {
         Number minimum = null;
         Number maximum = null;
         Class<? extends Number> type = null;
@@ -590,23 +590,47 @@
                     data.decoder.illegalAttributeValue(attribute, values.stringValue(i), e);
                 }
             }
+            /*
+             * Stop the loop and return a range as soon as we have enough information.
+             * Note that we may loop over many attributes before to complete information.
+             */
             if (minimum != null && maximum != null) {
                 /*
                  * Heuristic rule defined in UCAR documentation (see EnhanceScaleMissing interface):
                  * if the type of the range is equal to the type of the scale, and the type of the
                  * data is not wider, then assume that the minimum and maximum are real values.
                  */
+                final Class<?> scaleType  = data.getAttributeType(CDM.SCALE_FACTOR);
+                final Class<?> offsetType = data.getAttributeType(CDM.ADD_OFFSET);
                 final int rangeType = Numbers.getEnumConstant(type);
-                if (rangeType >= data.getDataType().number &&
-                    rangeType >= Math.max(Numbers.getEnumConstant(data.getAttributeType(CDM.SCALE_FACTOR)),
-                                          Numbers.getEnumConstant(data.getAttributeType(CDM.ADD_OFFSET))))
+                if ((scaleType != null || offsetType != null)
+                        && rangeType >= data.getDataType().number
+                        && rangeType >= Math.max(Numbers.getEnumConstant(scaleType),
+                                                 Numbers.getEnumConstant(offsetType)))
                 {
                     @SuppressWarnings({"unchecked", "rawtypes"})
                     final NumberRange<?> range = new MeasurementRange(type, minimum, true, maximum, true, data.getUnit());
                     return range;
                 } else {
+                    /*
+                     * The range use sample values (before conversion to the unit of measurement).
+                     * Before to return that range, check if the minimum or maximum overlaps with
+                     * a pad value. If this is the case, resolve the overlapping by making that
+                     * value exclusive instead than inclusive.
+                     */
+                    boolean isMinIncluded = true;
+                    boolean isMaxIncluded = true;
+                    if (!nodataValues.isEmpty()) {
+                        final double minValue = minimum.doubleValue();
+                        final double maxValue = maximum.doubleValue();
+                        for (final Number pad : nodataValues) {
+                            final double value = pad.doubleValue();
+                            isMinIncluded &= (minValue != value);
+                            isMaxIncluded &= (maxValue != value);
+                        }
+                    }
                     @SuppressWarnings({"unchecked", "rawtypes"})
-                    final NumberRange<?> range = new NumberRange(type, minimum, true, maximum, true);
+                    final NumberRange<?> range = new NumberRange(type, minimum, isMinIncluded, maximum, isMaxIncluded);
                     return range;
                 }
             }
@@ -616,7 +640,7 @@
 
     /**
      * Compares two numbers which shall be of the same class.
-     * This is a helper method for {@link #validRange(Variable)}.
+     * This is a helper method for {@link #validRange(Variable, Set)}.
      */
     @SuppressWarnings("unchecked")
     private static int compare(final Number n1, final Number n2) {
@@ -669,8 +693,8 @@
      * to be created for each variable.
      *
      * <p>This method is invoked in contexts where a transfer function is assumed to exist, for example
-     * because {@link #validRange(Variable)} returned a non-null value. Consequently this method shall
-     * never return {@code null}, but can return the identity function.</p>
+     * because {@link #validRange(Variable, Set)} returned a non-null value. Consequently this method
+     * shall never return {@code null}, but can return the identity function.</p>
      *
      * @param  data  the variable from which to determine the transfer function.
      *               This is usually a variable containing raster data.
diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
index 308f47d..8860b1b 100644
--- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
+++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java
@@ -787,14 +787,14 @@
 
     /**
      * Returns the range of valid values, or {@code null} if unknown. This is a shortcut for
-     * {@link Convention#validRange(Variable)} with a fallback on {@link #getRangeFallback()}.
+     * {@link Convention#validRange(Variable, Set)} with a fallback on {@link #getRangeFallback()}.
      *
      * @return the range of valid values, or {@code null} if unknown.
      *
-     * @see Convention#validRange(Variable)
+     * @see Convention#validRange(Variable, Set)
      */
     final NumberRange<?> getValidRange() {
-        NumberRange<?> range = decoder.convention().validRange(this);
+        NumberRange<?> range = decoder.convention().validRange(this, getNodataValues().keySet());
         if (range == null) {
             range = getRangeFallback();
         }
@@ -803,8 +803,8 @@
 
     /**
      * Returns the range of values as determined by the data type or other means, or {@code null} if unknown.
-     * This method is invoked only as a fallback if {@link Convention#validRange(Variable)} did not found a
-     * range of values by application of CF conventions. The returned range may be a range of packed values
+     * This method is invoked only as a fallback if {@link Convention#validRange(Variable, Set)} did not found
+     * a range of values by application of CF conventions. The returned range may be a range of packed values
      * or a range of real values. In the later case, the range shall be an instance of
      * {@link org.apache.sis.measure.MeasurementRange}.
      *
@@ -814,7 +814,7 @@
      *
      * @return the range of valid values, or {@code null} if unknown.
      *
-     * @see Convention#validRange(Variable)
+     * @see Convention#validRange(Variable, Set)
      */
     protected NumberRange<?> getRangeFallback() {
         final DataType dataType = getDataType();