jiayuasu commented on code in PR #3114:
URL: https://github.com/apache/sedona/pull/3114#discussion_r3633904128
##########
common/src/main/java/org/apache/sedona/common/utils/RasterUtils.java:
##########
@@ -647,6 +647,75 @@ public static boolean isDataTypeIntegral(int dataTypeCode)
{
}
}
+ /**
+ * Verifies that {@code noDataValue} can be stored in the pixel type named
by {@code pixelType}
+ * without silent coercion, returning it unchanged when it can. Writing a
value that is out of the
+ * pixel type's range, or fractional for an integer pixel type, coerces the
stored sample to a
+ * different number than the value recorded as the band's nodata metadata
(for example -1.0 or
+ * 300.0 wraps to 255 or 44 in an unsigned 8-bit band), so the background
would then read back as
+ * data rather than nodata. Such a value is a correctness violation, not a
per-row data condition,
+ * so this rejects it with an {@link IllegalArgumentException} instead of
coercing.
+ *
+ * @param noDataValue the candidate nodata / background value
+ * @param pixelType a Sedona pixel type string accepted by {@link
#getDataTypeCode(String)} (for
+ * example {@code "B"}, {@code "I"}, {@code "D"})
+ * @return {@code noDataValue}, unchanged, when it is representable in the
pixel type
+ * @throws IllegalArgumentException when {@code noDataValue} cannot be
represented in the pixel
+ * type
+ */
+ public static double assertNoDataValueRepresentable(double noDataValue,
String pixelType) {
+ int dataTypeCode = getDataTypeCode(pixelType);
+ long min;
+ long max;
+ String description;
+ switch (dataTypeCode) {
+ case DataBuffer.TYPE_BYTE:
+ min = 0;
+ max = 255;
+ description = "unsigned 8-bit";
+ break;
+ case DataBuffer.TYPE_USHORT:
+ min = 0;
+ max = 65535;
+ description = "unsigned 16-bit";
+ break;
+ case DataBuffer.TYPE_SHORT:
+ min = Short.MIN_VALUE;
+ max = Short.MAX_VALUE;
+ description = "signed 16-bit";
+ break;
+ case DataBuffer.TYPE_INT:
+ min = Integer.MIN_VALUE;
+ max = Integer.MAX_VALUE;
+ description = "signed 32-bit";
+ break;
+ case DataBuffer.TYPE_FLOAT:
+ // 32-bit float represents NaN and the infinities; reject only a
finite value whose
+ // magnitude overflows the float range (it would silently become an
infinity). Rounding a
+ // value to the nearest float is the inherent, expected behavior of a
float band.
+ if (Double.isFinite(noDataValue) && Math.abs(noDataValue) >
Float.MAX_VALUE) {
+ throw new IllegalArgumentException(
+ String.format(
+ "noDataValue %s is not representable in pixel type '%s'
(32-bit float, valid range %s..%s)",
+ noDataValue, pixelType, -Float.MAX_VALUE, Float.MAX_VALUE));
+ }
+ return noDataValue;
Review Comment:
Could we round-trip this through `float` before returning it? This passes
validation:
`RasterConstructors.asRaster(geom, ref, "F", false, 1d, 0.1d, false)`
but then fails while constructing the nodata metadata with `Range [0.1 ..
0.1] is not valid`. Returning `(double) (float) noDataValue` makes the stored
pixel and metadata agree. A test with `0.1` should catch it.
##########
common/src/main/java/org/apache/sedona/common/raster/Rasterization.java:
##########
@@ -85,6 +99,23 @@ protected static List<Object> rasterize(
return objects;
}
+ /**
+ * Fills every pixel of the freshly-allocated raster with the background
value, so pixels never
+ * covered by the geometry read back as that value instead of the allocation
default of 0. A null
+ * or zero background keeps the zero-initialized allocation as-is.
+ */
+ private static void fillBackground(WritableRaster writableRaster, Double
backgroundValue) {
+ if (backgroundValue == null || backgroundValue == 0) {
Review Comment:
`backgroundValue == 0` also matches `-0.0`. For `F`/`D`, that leaves the
zero-initialized pixels as `+0.0` while the nodata metadata remains `-0.0`.
`RS_Count(..., true)` uses `Double.compare`, so the hole is counted as data (9
instead of 8 in the 3x3 polygon-with-hole repro). Could we either normalize
signed zero before both uses, or skip only positive zero here?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]