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 4049ee5d82 Add a DataType.UINT type for distinguishing whether Java2D
`DataBuffer.TYPE_INT` should be interpreted as signed or unsigned. The sign of
the integer type is ambiguous in Java2D, as it depends on the context. Methods
were added in `DataType` for handling this ambiguity.
4049ee5d82 is described below
commit 4049ee5d8216fac74b93cd1ff7a2b71ac7404d99
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Dec 27 16:57:55 2024 +0100
Add a DataType.UINT type for distinguishing whether Java2D
`DataBuffer.TYPE_INT` should be interpreted as signed or unsigned.
The sign of the integer type is ambiguous in Java2D, as it depends on the
context.
Methods were added in `DataType` for handling this ambiguity.
---
.../org/apache/sis/image/BandAggregateLayout.java | 8 +-
.../apache/sis/image/BandedSampleConverter.java | 2 +-
.../main/org/apache/sis/image/DataType.java | 217 ++++++++++++++++-----
.../main/org/apache/sis/image/PixelIterator.java | 12 +-
.../main/org/apache/sis/image/ResampledImage.java | 2 +-
.../main/org/apache/sis/image/Transferer.java | 6 +-
.../apache/sis/image/privy/ColorModelBuilder.java | 3 +-
.../apache/sis/image/privy/ColorModelFactory.java | 6 +-
.../apache/sis/image/privy/ColorScaleBuilder.java | 8 +-
.../org/apache/sis/image/privy/ImageUtilities.java | 84 +-------
.../org/apache/sis/image/privy/RasterFactory.java | 7 +-
.../apache/sis/image/privy/TilePlaceholder.java | 5 +-
.../test/org/apache/sis/image/DataTypeTest.java | 28 ++-
.../apache/sis/image/privy/ImageUtilitiesTest.java | 16 --
.../org/apache/sis/storage/geotiff/DataSubset.java | 2 +-
.../sis/storage/geotiff/ImageFileDirectory.java | 2 +-
.../org/apache/sis/storage/geotiff/Writer.java | 4 +-
.../storage/geotiff/inflater/CopyFromBytes.java | 3 +-
.../geotiff/inflater/HorizontalPredictor.java | 5 +-
.../geotiff/writer/HorizontalPredictor.java | 5 +-
.../storage/geotiff/writer/ReformattedImage.java | 5 +-
.../sis/storage/geotiff/writer/TileMatrix.java | 1 +
.../apache/sis/storage/netcdf/base/DataType.java | 2 +-
.../apache/sis/storage/base/TiledGridResource.java | 2 +-
.../org/apache/sis/storage/esri/RasterStore.java | 8 +-
.../main/org/apache/sis/gui/coverage/GridView.java | 4 +-
26 files changed, 247 insertions(+), 200 deletions(-)
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateLayout.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateLayout.java
index 4d700e5aba..fdadc5e8cf 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateLayout.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateLayout.java
@@ -22,7 +22,6 @@ import java.awt.Point;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.image.ColorModel;
-import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.awt.image.BandedSampleModel;
@@ -154,7 +153,7 @@ final class BandAggregateLayout {
int tileHeight = 0;
int tileAlignX = 0;
int tileAlignY = 0;
- int commonDataType = DataBuffer.TYPE_UNDEFINED;
+ DataType commonDataType = null;
for (final RenderedImage source : sources) {
/*
* Ensure that all images use the same data type. This is
mandatory.
@@ -173,7 +172,7 @@ final class BandAggregateLayout {
allowSharing |= (domain == null);
}
}
- final int dataType = sm.getDataType();
+ final var dataType = DataType.forBands(sm);
if (domain == null) {
domain = ImageUtilities.getBounds(source);
commonDataType = dataType;
@@ -234,9 +233,8 @@ final class BandAggregateLayout {
final boolean exactTileSize = ((cx | cy) >>> Integer.SIZE) == 0;
allowSharing &= exactTileSize;
if (!allowSharing) scanlineStride = 0; // Means to force the
use of tile width.
- final var dataType = DataType.forDataBufferType(commonDataType);
final var layout = new ImageLayout(null, preferredTileSize,
!exactTileSize, false, false, minTile);
- sampleModel = layout.createBandedSampleModel(null, domain,
dataType, numBands, scanlineStride);
+ sampleModel = layout.createBandedSampleModel(null, domain,
commonDataType, numBands, scanlineStride);
}
this.bandsPerSource = bandsPerSource;
this.sources = sources;
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java
index 25d5ae161c..348e3f4a27 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java
@@ -148,7 +148,7 @@ class BandedSampleConverter extends WritableComputedImage {
}
if (!Double.isFinite(middle)) {
final SampleModel sm = source.getSampleModel();
- if (ImageUtilities.isUnsignedType(sm)) {
+ if (DataType.isUnsigned(sm)) {
middle = Math.scalb(0.5, sm.getSampleSize(i));
} else {
middle = 0;
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/DataType.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/DataType.java
index 0bb49fc4bb..caea60edb2 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/DataType.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/DataType.java
@@ -16,62 +16,84 @@
*/
package org.apache.sis.image;
+import java.awt.image.Raster;
import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.awt.image.RasterFormatException;
+import java.awt.image.SampleModel;
+import java.awt.image.MultiPixelPackedSampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
import org.apache.sis.util.Numbers;
+import org.apache.sis.util.ArraysExt;
+import org.apache.sis.util.resources.Errors;
import org.apache.sis.measure.NumberRange;
import org.apache.sis.image.privy.ImageUtilities;
import org.apache.sis.feature.internal.Resources;
-import org.apache.sis.util.resources.Errors;
import static
org.apache.sis.util.privy.Numerics.MAX_INTEGER_CONVERTIBLE_TO_FLOAT;
/**
* Identification of the primitive type used for storing sample values in an
image.
- * This is a type-safe version of the {@code TYPE_*} constants defined in
{@link DataBuffer}.
+ * This is a type-safe version of the {@code TYPE_*} constants defined in
{@link DataBuffer},
+ * except that this enumeration distinguishes signed and unsigned 32 bits
integers.
*
* @author Martin Desruisseaux (Geomatys)
* @version 1.5
* @since 1.1
*/
public enum DataType {
- /*
- * Enumeration values must be declared in order of increasing
`DataBuffer.TYPE_*` constant values,
- * without skiping values. This requirement allow us to get `FOO.ordinal()
== DataBuffer.TYPE_FOO`.
- * This matching is verified by DataTypeTest.verifyOrdinalValues().
- */
-
/**
* Unsigned 8-bits data.
+ * Mapped to {@link DataBuffer#TYPE_BYTE} in Java2D <abbr>API</abbr>.
*/
- BYTE((byte) 0),
+ BYTE(DataBuffer.TYPE_BYTE, (byte) 0),
/**
* Unsigned 16-bits data.
+ * Mapped to {@link DataBuffer#TYPE_USHORT} in Java2D <abbr>API</abbr>.
*/
- USHORT((short) 0),
+ USHORT(DataBuffer.TYPE_USHORT, (short) 0),
/**
* Signed 16-bits data.
+ * Mapped to {@link DataBuffer#TYPE_SHORT} in Java2D <abbr>API</abbr>.
+ */
+ SHORT(DataBuffer.TYPE_SHORT, (short) 0),
+
+ /**
+ * Signed 32-bits data.
+ * Mapped to {@link DataBuffer#TYPE_INT} in Java2D <abbr>API</abbr>.
+ * Note that the sign of the latter Java2D type is ambiguous.
+ * See {@link #forDataBufferType(int)} for more information.
*/
- SHORT((short) 0),
+ INT(DataBuffer.TYPE_INT, 0),
/**
- * Signed 32-bits data. Also used for storing unsigned data; the Java2D
API such as
- * {@link java.awt.image.Raster#getSample(int, int, int)} cannot
distinguish the two cases.
+ * Unsigned 32-bits data.
+ * Mapped to {@link DataBuffer#TYPE_INT} in Java2D <abbr>API</abbr>.
+ * Note that the sign of the latter Java2D type is ambiguous.
+ * See {@link #forDataBufferType(int)} for more information.
+ *
+ * @since 1.5
*/
- INT(0),
+ UINT(DataBuffer.TYPE_INT, 0),
/**
* Single precision (32-bits) floating point data.
+ * Mapped to {@link DataBuffer#TYPE_FLOAT} in Java2D <abbr>API</abbr>.
*/
- FLOAT(Float.NaN),
+ FLOAT(DataBuffer.TYPE_FLOAT, Float.NaN),
/**
* Double precision (64-bits) floating point data.
+ * Mapped to {@link DataBuffer#TYPE_DOUBLE} in Java2D <abbr>API</abbr>.
+ */
+ DOUBLE(DataBuffer.TYPE_DOUBLE, Double.NaN);
+
+ /**
+ * The data buffer type as one of the {@code DataBuffer.TYPE_*} constants.
*/
- DOUBLE(Double.NaN);
+ private final int dataType;
/**
* The default fill value, which is 0 for integer types and NaN for
floating point types.
@@ -82,32 +104,63 @@ public enum DataType {
private final Number fillValue;
/**
- * All enumeration values, cached for avoiding to recreate this array
- * on every {@link #forDataBufferType(int)} call.
+ * Enumeration values for {@code DataBuffer.TYPE_*} constants.
+ * The unsigned variant of {@code TYPE_INT} is discarded, keeping the
signed variant.
+ *
+ * @see #forDataBufferType(int)
*/
- private static final DataType[] VALUES = values();
+ private static final DataType[] VALUES = ArraysExt.remove(values(),
DataBuffer.TYPE_INT + 1, 1);
/**
- * Creates a new enumeration.
+ * Creates a new enumeration value.
*/
- private DataType(final Number fillValue) {
+ private DataType(final int dataType, final Number fillValue) {
+ this.dataType = dataType;
this.fillValue = fillValue;
}
/**
- * Returns the data type of the bands in the given image. This is often the
- * {@linkplain java.awt.image.SampleModel#getDataType() storage data
type}, but not necessarily.
- * For example if an ARGB image uses a storage mode where the sample
values in the 4 bands are
- * {@linkplain java.awt.image.SinglePixelPackedSampleModel packed in a
single 32-bits integer},
- * then this method returns {@link #BYTE} (the type of a single band), not
{@link #INT}
- * (the type of a whole pixel).
+ * Returns the data type of the bands in the given image.
+ * This is often the {@linkplain SampleModel#getDataType() storage data
type}, but not necessarily.
+ * See {@link #forBands(SampleModel)} for more information.
*
- * @param image the image for which to get the type.
- * @return type of the given image (never {@code null}).
+ * @param image the image for which to get the band data type.
+ * @return type of sample values in the given image (never {@code null}).
* @throws RasterFormatException if the image does not use a recognized
data type.
*/
public static DataType forBands(final RenderedImage image) {
- return
forDataBufferType(ImageUtilities.getBandType(image.getSampleModel()));
+ return forBands(image.getSampleModel());
+ }
+
+ /**
+ * Returns the data type of the bands managed by the given the sample
model.
+ * This is often the {@linkplain SampleModel#getDataType() storage data
type}, but not necessarily.
+ * For example, if an <abbr>ARGB</abbr> image uses a storage mode where
the sample values in the
+ * four bands are {@linkplain SinglePixelPackedSampleModel packed in a
single 32-bits integer},
+ * then this method returns {@link #BYTE} (the type of a single band)
rather than {@link #INT}
+ * (the type of a whole pixel).
+ *
+ * @param sm the sample model for which to get the band data type.
+ * @return type of sample values in the bands managed by the given sample
model (never {@code null}).
+ * @throws RasterFormatException if the sample model does not use a
recognized data type.
+ *
+ * @since 1.5
+ */
+ public static DataType forBands(final SampleModel sm) {
+ final int type = sm.getDataType();
+ if (type > DataBuffer.TYPE_BYTE && type <= DataBuffer.TYPE_INT) {
+ int numBits = 0;
+ for (int i=sm.getNumBands(); --i >= 0;) {
+ numBits = Math.max(numBits, sm.getSampleSize(i));
+ }
+ if (isUnsigned(sm)) {
+ return (numBits <= Byte.SIZE) ? BYTE :
+ (numBits <= Short.SIZE) ? USHORT : UINT;
+ } else {
+ return (numBits <= Short.SIZE) ? SHORT : INT;
+ }
+ }
+ return forDataBufferType(type);
}
/**
@@ -117,7 +170,7 @@ public enum DataType {
* <ul>
* <li>If {@code asInteger} is {@code false}, then this method returns
* {@link #FLOAT} or {@link #DOUBLE} depending on the range
type.</li>
- * <li>Otherwise this method treats the floating point values as if they
+ * <li>Otherwise, this method treats the floating point values as if they
* were integers, with minimum value rounded toward negative infinity
* and maximum value rounded toward positive infinity.</li>
* </ul>
@@ -147,13 +200,13 @@ public enum DataType {
}
}
/*
- * Check most common types first. If the range could be both signed
and unsigned short,
- * give precedence to unsigned short because it works better with
IndexColorModel.
+ * Check most common types first. If the range could be both signed
and unsigned,
+ * give precedence to unsigned types because it works better with
IndexColorModel.
* If a bounds is NaN, fallback on TYPE_FLOAT.
*/
final DataType type;
- if (min >= -0.5 && max < 0xFFFF + 0.5) {
- type = (max < 0xFF + 0.5) ? BYTE : USHORT;
+ if (min >= -0.5 && max < 0xFFFFFFFF + 0.5) {
+ type = (max < 0xFF + 0.5) ? BYTE : (max < 0xFFFF + 0.5) ? USHORT :
UINT;
} else if (min >= Short.MIN_VALUE - 0.5 && max < Short.MAX_VALUE +
0.5) {
type = SHORT;
} else if (min >= Integer.MIN_VALUE - 0.5 && max < Integer.MAX_VALUE +
0.5) {
@@ -177,7 +230,7 @@ public enum DataType {
switch (Numbers.getEnumConstant(type)) {
case Numbers.BYTE: return unsigned ? BYTE : SHORT;
case Numbers.SHORT: return unsigned ? USHORT : SHORT;
- case Numbers.INTEGER: if (unsigned) break; else return INT;
+ case Numbers.INTEGER: return unsigned ? UINT : INT;
case Numbers.FLOAT: return FLOAT;
case Numbers.DOUBLE: return DOUBLE;
}
@@ -189,6 +242,24 @@ public enum DataType {
* This method is the converse of {@link #toDataBufferType()}.
* It is provided for interoperability with Java2D.
*
+ * <h4>32 bit integers</h4>
+ * The case of {@link DataBuffer#TYPE_INT} is ambiguous.
+ * Whether this type is considered as signed or unsigned depends on the
context:
+ * <ul>
+ * <li>The sign is indistinguishable when using Java2D <abbr>API</abbr>
working on integer values
+ * such as the {@link Raster#getSample(int, int, int)
Raster.getSample(…)} method.</li>
+ * <li>When converted to floating point values by Java2D
<abbr>API</abbr> such as
+ * {@link Raster#getSampleFloat(int, int, int)
Raster.getSampleFloat(…)}, sample values are:
+ * <ul>
+ * <li>Unsigned when the raster uses {@link
SinglePixelPackedSampleModel} or {@link MultiPixelPackedSampleModel}.</li>
+ * <li>Signed when the raster uses any other type of sample
model.</li>
+ * </ul>
+ * </li>
+ * <li>The type is <em>unsigned</em> when converted to a color by {@link
java.awt.image.ComponentColorModel}.</li>
+ * </ul>
+ *
+ * For resolving above ambiguities, consider using {@link
#forBands(SampleModel)} instead of this method.
+ *
* @param type one of {@code DataBuffer.TYPE_*} constants.
* @return the data type (never {@code null}) for the given data buffer
type.
* @throws RasterFormatException if the given type is not a recognized
{@code DataBuffer.TYPE_*} constant.
@@ -213,7 +284,7 @@ public enum DataType {
* <tr><td>4</td> <td>{@code false}</td> <td>{@code
false}</td></tr>
* <tr><td>{@value Byte#SIZE}</td> <td>{@code false}</td> <td>{@code
false}</td></tr>
* <tr><td>{@value Short#SIZE}</td> <td>{@code false}</td> <td>{@code
false} or {@code true}</td></tr>
- * <tr><td>{@value Integer#SIZE}</td> <td>{@code false}</td> <td>{@code
true}</td></tr>
+ * <tr><td>{@value Integer#SIZE}</td> <td>{@code false}</td> <td>{@code
false} or {@code true}</td></tr>
* <tr><td>{@value Float#SIZE}</td> <td>{@code true}</td>
<td>ignored</td></tr>
* <tr><td>{@value Double#SIZE}</td> <td>{@code true}</td>
<td>ignored</td></tr>
* </table>
@@ -238,14 +309,12 @@ public enum DataType {
case Double.SIZE: return DOUBLE;
}
} else {
- if (size == Short.SIZE) {
- return signed ? SHORT : USHORT;
+ switch (size) {
+ case Short.SIZE: return signed ? SHORT : USHORT;
+ case Integer.SIZE: return signed ? INT : UINT;
}
- final boolean isInt = (size == Integer.SIZE);
- if (isInt || size <= Byte.SIZE) {
- if (isInt == signed) {
- return isInt ? INT : BYTE;
- }
+ if (size <= Byte.SIZE) {
+ if (!signed) return BYTE;
argument = "signed";
value = signed;
}
@@ -259,7 +328,7 @@ public enum DataType {
* @return size in bits of this data type.
*/
public final int size() {
- return DataBuffer.getDataTypeSize(ordinal());
+ return DataBuffer.getDataTypeSize(dataType);
}
/**
@@ -276,22 +345,65 @@ public enum DataType {
/**
* Returns whether this type is an unsigned integer type.
- * Unsigned types are {@link #BYTE} and {@link #USHORT}.
+ * Unsigned types are {@link #BYTE}, {@link #USHORT} and {@link #UINT}.
*
* @return {@code true} if this type is an unsigned integer type.
*/
public final boolean isUnsigned() {
- return ordinal() <= DataBuffer.TYPE_USHORT;
+ return dataType <= DataBuffer.TYPE_USHORT || this == UINT;
+ }
+
+ /**
+ * Returns {@code true} if the type of sample values is an unsigned
integer type.
+ * Returns {@code false} if the type is a floating point type or in case
of doubt
+ * (e.g. for {@link DataBuffer#TYPE_UNDEFINED}).
+ *
+ * @param sm the sample model, or {@code null}.
+ * @return whether the given sample model provides unsigned sample values.
+ *
+ * @since 1.5
+ */
+ public static boolean isUnsigned(final SampleModel sm) {
+ if (sm != null) {
+ final int dataType = sm.getDataType();
+ if (dataType >= DataBuffer.TYPE_BYTE) {
+ if (dataType <= DataBuffer.TYPE_USHORT) return true;
+ if (dataType <= DataBuffer.TYPE_INT) {
+ /*
+ * Typical case: 4 bands (ARGB) stored in a single data
element of type `int`.
+ * The javadoc of those classes explain how to unpack the
sample values,
+ * and the result is always unsigned.
+ */
+ return (sm instanceof SinglePixelPackedSampleModel) ||
+ (sm instanceof MultiPixelPackedSampleModel);
+ }
+ }
+ }
+ return false;
}
/**
* Returns whether this type is an integer type, signed or not.
- * Integer types are {@link #BYTE}, {@link #USHORT}, {@link #SHORT} and
{@link #INT}.
+ * Integer types are {@link #BYTE}, {@link #USHORT}, {@link #SHORT},
{@link #INT} and {@link #UINT}.
*
* @return {@code true} if this type is an integer type.
*/
public final boolean isInteger() {
- return ordinal() <= DataBuffer.TYPE_INT;
+ return dataType <= DataBuffer.TYPE_INT;
+ }
+
+ /**
+ * Returns {@code true} if the given sample model uses an integer type.
+ * Returns {@code false} if the type is a floating point type or in case
+ * of doubt (e.g. for {@link DataBuffer#TYPE_UNDEFINED}).
+ *
+ * @param sm the sample model, or {@code null}.
+ * @return whether the given sample model works on integer values.
+ *
+ * @since 1.5
+ */
+ public static boolean isInteger(final SampleModel sm) {
+ return (sm != null) && ImageUtilities.isIntegerType(sm.getDataType());
}
/**
@@ -299,7 +411,7 @@ public enum DataType {
* without precision lost. This method returns:
*
* <ul>
- * <li>{@link #DOUBLE} if this data type is {@link #DOUBLE} or {@link
#INT}.</li>
+ * <li>{@link #DOUBLE} if this data type is {@link #DOUBLE}, {@link
#INT} or {@link #UINT}.</li>
* <li>{@link #FLOAT} for all other types.</li>
* </ul>
*
@@ -310,8 +422,7 @@ public enum DataType {
* which can store all values of this type without any lost.
*/
public final DataType toFloat() {
- final int type = ordinal();
- return (type < DataBuffer.TYPE_INT || type == DataBuffer.TYPE_FLOAT) ?
FLOAT : DOUBLE;
+ return (dataType < DataBuffer.TYPE_INT || dataType ==
DataBuffer.TYPE_FLOAT) ? FLOAT : DOUBLE;
}
/**
@@ -322,7 +433,7 @@ public enum DataType {
* @return one of the {@link DataBuffer} constants.
*/
public final int toDataBufferType() {
- return ordinal();
+ return dataType;
}
/**
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PixelIterator.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PixelIterator.java
index cb5bd3c4cd..4155780ff0 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PixelIterator.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PixelIterator.java
@@ -551,17 +551,17 @@ public class PixelIterator {
}
/**
- * Returns the type used for storing data in the raster buffer.
- * The data type identifies the {@link DataBuffer} subclass used for
storage.
+ * Returns the type of sample values. This is usually the {@link
DataBuffer} type,
+ * but may be a smaller type if many values are packed in each data buffer
element.
*
- * @return the type used for storing data in the raster buffer.
+ * @return the type of sample values.
*
- * @see SampleModel#getDataType()
+ * @see DataType#forBands(SampleModel)
*
* @since 1.2
*/
public DataType getDataType() {
- return DataType.forDataBufferType(getSampleModel().getDataType());
+ return DataType.forBands(getSampleModel());
}
/**
@@ -618,7 +618,7 @@ public class PixelIterator {
final int size = model.getSampleSize(bandToDefine);
long minimum = 0;
long maximum = Numerics.bitmask(size) - 1;
- if (!ImageUtilities.isUnsignedType(model)) {
+ if (!DataType.isUnsigned(model)) {
maximum >>>= 1; //
Convert unsigned range to signed range.
minimum = ~maximum;
}
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ResampledImage.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ResampledImage.java
index 2ecc0bb5dd..8d0b9d4624 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ResampledImage.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ResampledImage.java
@@ -754,7 +754,7 @@ public class ResampledImage extends ComputedImage {
for (int b=0; b<numBands; b++) {
maxValues[b] = Numerics.bitmask(sm.getSampleSize(b)) - 1;
}
- if (!ImageUtilities.isUnsignedType(sm)) {
+ if (!DataType.isUnsigned(sm)) {
for (int b=0; b<numBands; b++) {
minValues[b] = ~(maxValues[b] >>>= 1); // Convert
unsigned type to signed type range.
}
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Transferer.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Transferer.java
index 6c953309cb..fc6a002d5a 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Transferer.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Transferer.java
@@ -562,7 +562,7 @@ abstract class Transferer {
* @return object to use for applying the operation.
*/
static Transferer create(final Raster source, final WritableRaster target,
final Rectangle aoi) {
- switch (ImageUtilities.getBandType(target.getSampleModel())) {
+ switch (DataType.forBands(target.getSampleModel()).toDataBufferType())
{
case DataBuffer.TYPE_DOUBLE: {
if (isDirect(target, aoi)) {
return new DoubleToDirect(source, target, aoi);
@@ -570,7 +570,7 @@ abstract class Transferer {
break;
}
case DataBuffer.TYPE_FLOAT: {
- switch (ImageUtilities.getBandType(source.getSampleModel())) {
+ switch
(DataType.forBands(source.getSampleModel()).toDataBufferType()) {
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_SHORT:
case DataBuffer.TYPE_USHORT: // TODO: consider
using IntegerToDirect here.
@@ -606,7 +606,7 @@ abstract class Transferer {
* to the {@code float} type may lost precision digits.
*/
private static boolean singlePrecision(final Raster source) {
- switch (ImageUtilities.getBandType(source.getSampleModel())) {
+ switch (DataType.forBands(source.getSampleModel()).toDataBufferType())
{
case DataBuffer.TYPE_BYTE:
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT:
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorModelBuilder.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorModelBuilder.java
index e970e8780a..89988e5d4d 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorModelBuilder.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorModelBuilder.java
@@ -28,6 +28,7 @@ import java.awt.image.DataBuffer;
import java.awt.image.SampleModel;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.ArraysExt;
+import org.apache.sis.image.DataType;
/**
@@ -279,7 +280,7 @@ public final class ColorModelBuilder {
* @throws IllegalArgumentException if any argument specified to the
builder is invalid.
*/
public ColorModel createRGB(final SampleModel targetModel) {
-check: if (ImageUtilities.isIntegerType(targetModel)) {
+check: if (DataType.isInteger(targetModel)) {
final int numBands = targetModel.getNumBands();
switch (numBands) {
case 3: alphaBand = -1; break;
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorModelFactory.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorModelFactory.java
index e497dc2482..0e4322ef10 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorModelFactory.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorModelFactory.java
@@ -579,9 +579,9 @@ public final class ColorModelFactory {
} else {
minimum = 0;
maximum = 1;
- if (ImageUtilities.isIntegerType(model)) {
+ if (DataType.isInteger(model)) {
long max = Numerics.bitmask(model.getSampleSize(visibleBand))
- 1;
- if (!ImageUtilities.isUnsignedType(model)) {
+ if (!DataType.isUnsigned(model)) {
max >>>= 1;
minimum = ~max; // Tild operator, not minus.
}
@@ -792,7 +792,7 @@ public final class ColorModelFactory {
*/
@Override
public String toString() {
- final StringBuilder buffer = new
StringBuilder(Strings.toString(getClass(),
+ final var buffer = new StringBuilder(Strings.toString(getClass(),
"dataType", DataType.forDataBufferType(dataType), "numBands",
numBands, "visibleBand", visibleBand,
"range", NumberRange.create(minimum, true, maximum, false)));
final int n = (pieceStarts != null) ? pieceStarts.length : 0;
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorScaleBuilder.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorScaleBuilder.java
index 2e83936957..f813f2a9da 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorScaleBuilder.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ColorScaleBuilder.java
@@ -276,7 +276,7 @@ public final class ColorScaleBuilder {
* If the model uses floating point values and there is no
"no data" category, add one.
* We force a "no data" category because floating point
values may be NaN.
*/
- if (missingNodata && (model == null ||
!ImageUtilities.isIntegerType(model))) {
+ if (missingNodata && (model == null ||
!DataType.isInteger(model))) {
final int count = entries.length;
entries = Arrays.copyOf(entries, count + 1);
entries[count] = new ColorsForRange(TRANSPARENT,
@@ -303,10 +303,10 @@ public final class ColorScaleBuilder {
*/
public boolean initialize(final SampleModel source, final int band) {
checkInitializationStatus(false);
- if (ImageUtilities.isIntegerType(source)) {
+ if (DataType.isInteger(source)) {
long minimum = 0;
long maximum = Numerics.bitmask(source.getSampleSize(band)) - 1;
- if (!ImageUtilities.isUnsignedType(source)) {
+ if (!DataType.isUnsigned(source)) {
maximum >>>= 1;
minimum = ~maximum;
}
@@ -700,7 +700,7 @@ reuse: if (source != null) {
* @return a color model using a data type inferred from the given sample
model.
*/
public ColorModel createColorModel(final SampleModel target, final int
numBands, final int visibleBand) {
- return
createColorModel(DataType.forDataBufferType(ImageUtilities.getBandType(target)),
numBands, visibleBand);
+ return createColorModel(DataType.forBands(target), numBands,
visibleBand);
}
/**
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ImageUtilities.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ImageUtilities.java
index c2e6dbd489..18f6eeea7b 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ImageUtilities.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/ImageUtilities.java
@@ -30,13 +30,13 @@ import java.awt.image.RenderedImage;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
-import java.awt.image.MultiPixelPackedSampleModel;
import static java.lang.Math.abs;
import static java.lang.Math.rint;
import static java.lang.Math.floorDiv;
import static java.lang.Math.toIntExact;
import static java.lang.Math.multiplyFull;
import org.apache.sis.feature.internal.Resources;
+import org.apache.sis.image.DataType;
import org.apache.sis.image.PlanarImage;
import org.apache.sis.system.Modules;
import org.apache.sis.util.Numbers;
@@ -176,47 +176,6 @@ public final class ImageUtilities extends Static {
return 0;
}
- /**
- * Returns the data type of bands in rasters that use the given sample
model.
- * If each band is stored in its own {@link DataBuffer} element, then this
method returns the same value
- * as {@link SampleModel#getDataType()}. But if multiple sample values are
packed in a single data element
- * ({@link SinglePixelPackedSampleModel} or {@link
MultiPixelPackedSampleModel}), then this method returns
- * a smaller data type. As a general rule, this method returns the
smallest data type capable to store all
- * sample values with a {@link java.awt.image.BandedSampleModel}.
- *
- * @param sm the sample model for which to get the band type, or {@code
null}.
- * @return the data type, or {@link DataBuffer#TYPE_UNDEFINED} if unknown.
- *
- * @see #isIntegerType(int)
- * @see #isUnsignedType(SampleModel)
- */
- public static int getBandType(final SampleModel sm) {
- if (sm == null) {
- return DataBuffer.TYPE_UNDEFINED;
- }
- final int type = sm.getDataType();
- if (!isIntegerType(type)) {
- return type;
- }
- final int maxBits = Math.min(DataBuffer.getDataTypeSize(type),
Short.SIZE + 1);
- int numBits = 0;
- for (int i=sm.getNumBands(); --i >= 0;) {
- final int n = sm.getSampleSize(i);
- if (n > numBits) {
- if (n >= maxBits) {
- return type;
- }
- numBits = n;
- }
- }
- final boolean isUnsignedType = (type <= DataBuffer.TYPE_USHORT)
- || (sm instanceof SinglePixelPackedSampleModel)
- || (sm instanceof MultiPixelPackedSampleModel);
-
- return isUnsignedType ? (numBits <= Byte.SIZE ? DataBuffer.TYPE_BYTE :
DataBuffer.TYPE_USHORT)
- : DataBuffer.TYPE_SHORT;
- }
-
/**
* Names of {@link DataBuffer} types.
*/
@@ -419,45 +378,6 @@ public final class ImageUtilities extends Static {
return dataType >= DataBuffer.TYPE_BYTE && dataType <=
DataBuffer.TYPE_INT;
}
- /**
- * Returns {@code true} if the given sample model uses an integer type.
- * Returns {@code false} if the type is a floating point type or in case
- * of doubt (e.g. for {@link DataBuffer#TYPE_UNDEFINED}).
- *
- * @param sm the sample model, or {@code null}.
- * @return whether the given sample model is for integer values.
- */
- public static boolean isIntegerType(final SampleModel sm) {
- return (sm != null) && isIntegerType(sm.getDataType());
- }
-
- /**
- * Returns {@code true} if the type of sample values is an unsigned
integer type.
- * Returns {@code false} if the type is a floating point type or in case
of doubt
- * (e.g. for {@link DataBuffer#TYPE_UNDEFINED}).
- *
- * @param sm the sample model, or {@code null}.
- * @return whether the given sample model provides unsigned sample values.
- */
- public static boolean isUnsignedType(final SampleModel sm) {
- if (sm != null) {
- final int dataType = sm.getDataType();
- if (dataType >= DataBuffer.TYPE_BYTE) {
- if (dataType <= DataBuffer.TYPE_USHORT) return true;
- if (dataType <= DataBuffer.TYPE_INT) {
- /*
- * Typical case: 4 bands (ARGB) stored in a single data
element of type `int`.
- * The javadoc of those classes explain how to unpack the
sample values,
- * and the result is always unsigned.
- */
- return (sm instanceof SinglePixelPackedSampleModel) ||
- (sm instanceof MultiPixelPackedSampleModel);
- }
- }
- }
- return false;
- }
-
/**
* Returns whether samples values stored using {@code source} model can be
converted to {@code target} model
* without data lost. This method verifies the number of bands and the
size of data in each band.
@@ -491,7 +411,7 @@ public final class ImageUtilities extends Static {
* - Conversion from `int` to `float` can loose significant
digits.
* - Conversion from signed short to unsigned short (or
conversely) can change values.
*/
- if (sourceIsInteger != targetIsInteger ||
isUnsignedType(source) != isUnsignedType(target)) {
+ if (sourceIsInteger != targetIsInteger ||
DataType.isUnsigned(source) != DataType.isUnsigned(target)) {
return false;
}
}
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/RasterFactory.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/RasterFactory.java
index caa5b1edaf..1fb7e06a37 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/RasterFactory.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/RasterFactory.java
@@ -211,9 +211,10 @@ public final class RasterFactory extends Static {
*/
public static Buffer createBuffer(final DataType dataType, final int
capacity) {
switch (dataType) {
+ case BYTE: return ByteBuffer .allocate(capacity);
case USHORT: // Fallthrough
case SHORT: return ShortBuffer .allocate(capacity);
- case BYTE: return ByteBuffer .allocate(capacity);
+ case UINT: // Fallthrough
case INT: return IntBuffer .allocate(capacity);
case FLOAT: return FloatBuffer .allocate(capacity);
case DOUBLE: return DoubleBuffer.allocate(capacity);
@@ -268,10 +269,11 @@ public final class RasterFactory extends Static {
final int numBands = data.length;
final Object[] arrays;
switch (dataType) {
+ case BYTE: arrays = new byte [numBands][]; break;
case USHORT: // fall through
case SHORT: arrays = new short [numBands][]; break;
+ case UINT: // fall through
case INT: arrays = new int [numBands][]; break;
- case BYTE: arrays = new byte [numBands][]; break;
case FLOAT: arrays = new float [numBands][]; break;
case DOUBLE: arrays = new double[numBands][]; break;
default: throw new AssertionError(dataType);
@@ -293,6 +295,7 @@ public final class RasterFactory extends Static {
case BYTE: return new DataBufferByte ( (byte[][]) arrays,
length, offsets);
case SHORT: return new DataBufferShort ( (short[][]) arrays,
length, offsets);
case USHORT: return new DataBufferUShort( (short[][]) arrays,
length, offsets);
+ case UINT: // Fall through
case INT: return new DataBufferInt ( (int[][]) arrays,
length, offsets);
case FLOAT: return new DataBufferFloat ( (float[][]) arrays,
length, offsets);
case DOUBLE: return new DataBufferDouble((double[][]) arrays,
length, offsets);
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/TilePlaceholder.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/TilePlaceholder.java
index 66e60730df..65b4963e1f 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/TilePlaceholder.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/privy/TilePlaceholder.java
@@ -34,6 +34,7 @@ import org.apache.sis.util.Workaround;
import org.apache.sis.util.collection.WeakHashSet;
import org.apache.sis.util.privy.Numerics;
import org.apache.sis.system.ReferenceQueueConsumer;
+import org.apache.sis.image.DataType;
/**
@@ -286,8 +287,8 @@ public class TilePlaceholder {
WithCross(final RenderedImage image) {
super(image.getSampleModel());
samples = new double[model.getNumBands()];
- if (ImageUtilities.isIntegerType(model)) {
- final boolean isUnsigned =
ImageUtilities.isUnsignedType(model);
+ if (DataType.isInteger(model)) {
+ final boolean isUnsigned = DataType.isUnsigned(model);
for (int i=0; i<samples.length; i++) {
int size = model.getSampleSize(i);
if (!isUnsigned) size--;
diff --git
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/DataTypeTest.java
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/DataTypeTest.java
index ae429149a0..ae0728b148 100644
---
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/DataTypeTest.java
+++
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/DataTypeTest.java
@@ -18,6 +18,9 @@ package org.apache.sis.image;
import java.awt.image.DataBuffer;
import java.awt.image.RasterFormatException;
+import java.awt.image.SampleModel;
+import java.awt.image.BandedSampleModel;
+import java.awt.image.SinglePixelPackedSampleModel;
// Test dependencies
import org.junit.jupiter.api.Test;
@@ -39,14 +42,15 @@ public final class DataTypeTest extends TestCase {
}
/**
- * Verifies that {@link DataType} ordinal values match {@link DataBuffer}
constant values.
+ * Verifies {@link DataType#toDataBufferType()}.
*/
@Test
- public void verifyOrdinalValues() {
+ public void verifyToDataBufferType() {
assertEquals(DataBuffer.TYPE_BYTE , DataType.BYTE
.toDataBufferType());
assertEquals(DataBuffer.TYPE_USHORT,
DataType.USHORT.toDataBufferType());
assertEquals(DataBuffer.TYPE_SHORT , DataType.SHORT
.toDataBufferType());
assertEquals(DataBuffer.TYPE_INT , DataType.INT
.toDataBufferType());
+ assertEquals(DataBuffer.TYPE_INT , DataType.UINT
.toDataBufferType());
assertEquals(DataBuffer.TYPE_FLOAT , DataType.FLOAT
.toDataBufferType());
assertEquals(DataBuffer.TYPE_DOUBLE,
DataType.DOUBLE.toDataBufferType());
}
@@ -60,6 +64,7 @@ public final class DataTypeTest extends TestCase {
assertEquals(Short .SIZE, DataType.USHORT.size());
assertEquals(Short .SIZE, DataType.SHORT .size());
assertEquals(Integer.SIZE, DataType.INT .size());
+ assertEquals(Integer.SIZE, DataType.UINT .size());
assertEquals(Float .SIZE, DataType.FLOAT .size());
assertEquals(Double .SIZE, DataType.DOUBLE.size());
}
@@ -73,6 +78,7 @@ public final class DataTypeTest extends TestCase {
assertTrue (DataType.USHORT.isUnsigned());
assertFalse(DataType.SHORT .isUnsigned());
assertFalse(DataType.INT .isUnsigned());
+ assertTrue (DataType.UINT .isUnsigned());
assertFalse(DataType.FLOAT .isUnsigned());
assertFalse(DataType.DOUBLE.isUnsigned());
}
@@ -86,6 +92,7 @@ public final class DataTypeTest extends TestCase {
assertTrue (DataType.USHORT.isInteger());
assertTrue (DataType.SHORT .isInteger());
assertTrue (DataType.INT .isInteger());
+ assertTrue (DataType.UINT .isInteger());
assertFalse(DataType.FLOAT .isInteger());
assertFalse(DataType.DOUBLE.isInteger());
}
@@ -99,6 +106,7 @@ public final class DataTypeTest extends TestCase {
assertEquals(DataType.FLOAT, DataType.USHORT.toFloat());
assertEquals(DataType.FLOAT, DataType.SHORT .toFloat());
assertEquals(DataType.DOUBLE, DataType.INT .toFloat());
+ assertEquals(DataType.DOUBLE, DataType.UINT .toFloat());
assertEquals(DataType.FLOAT, DataType.FLOAT .toFloat());
assertEquals(DataType.DOUBLE, DataType.DOUBLE.toFloat());
}
@@ -113,6 +121,7 @@ public final class DataTypeTest extends TestCase {
assertEquals(DataType.USHORT, DataType.forNumberOfBits(Short.SIZE,
false, false));
assertEquals(DataType.SHORT, DataType.forNumberOfBits(Short.SIZE,
false, true));
assertEquals(DataType.INT, DataType.forNumberOfBits(Integer.SIZE,
false, true));
+ assertEquals(DataType.UINT, DataType.forNumberOfBits(Integer.SIZE,
false, false));
assertEquals(DataType.FLOAT, DataType.forNumberOfBits(Float.SIZE,
true, true));
assertEquals(DataType.DOUBLE, DataType.forNumberOfBits(Double.SIZE,
true, true));
@@ -121,4 +130,19 @@ public final class DataTypeTest extends TestCase {
"Signed bytes should be invalid.");
assertMessageContains(e, "signed", "true");
}
+
+ /**
+ * Tests {@link DataType#forBands(SampleModel)}.
+ */
+ @Test
+ public void testForBands() {
+ SampleModel sm = new BandedSampleModel(DataBuffer.TYPE_INT, 1, 1, 3);
+ assertEquals(DataType.INT, DataType.forBands(sm));
+
+ sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, 1, 1, new
int[] {0x7F0000, 0x00FF00, 0x00007F});
+ assertEquals(DataType.BYTE, DataType.forBands(sm));
+
+ sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, 1, 1, new
int[] {0x7F0000, 0x00FF80, 0x00007F});
+ assertEquals(DataType.USHORT, DataType.forBands(sm));
+ }
}
diff --git
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/privy/ImageUtilitiesTest.java
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/privy/ImageUtilitiesTest.java
index 5e18396cbe..b8b00c3b7b 100644
---
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/privy/ImageUtilitiesTest.java
+++
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/privy/ImageUtilitiesTest.java
@@ -24,7 +24,6 @@ import java.awt.image.RenderedImage;
import java.awt.image.BufferedImage;
import java.awt.image.SampleModel;
import java.awt.image.BandedSampleModel;
-import java.awt.image.SinglePixelPackedSampleModel;
import org.apache.sis.util.Numbers;
import org.apache.sis.util.resources.Vocabulary;
import static org.apache.sis.util.privy.Numerics.COMPARISON_THRESHOLD;
@@ -70,21 +69,6 @@ public final class ImageUtilitiesTest extends TestCase {
assertEquals(3, bounds.height);
}
- /**
- * Tests {@link ImageUtilities#getBandType(SampleModel)}.
- */
- @Test
- public void testGetBandType() {
- SampleModel sm = new BandedSampleModel(DataBuffer.TYPE_INT, 1, 1, 3);
- assertEquals(DataBuffer.TYPE_INT, ImageUtilities.getBandType(sm));
-
- sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, 1, 1, new
int[] {0x7F0000, 0x00FF00, 0x00007F});
- assertEquals(DataBuffer.TYPE_BYTE, ImageUtilities.getBandType(sm));
-
- sm = new SinglePixelPackedSampleModel(DataBuffer.TYPE_INT, 1, 1, new
int[] {0x7F0000, 0x00FF80, 0x00007F});
- assertEquals(DataBuffer.TYPE_USHORT, ImageUtilities.getBandType(sm));
- }
-
/**
* Tests {@link ImageUtilities#getDataTypeName(SampleModel)}.
*/
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
index a041e4109c..75d66ebe5d 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/DataSubset.java
@@ -546,7 +546,7 @@ class DataSubset extends TiledGridCoverage implements
Localized {
final int limit = bank.limit();
final int capacity = bank.capacity(); // Equals `this.capacity`
except for packed sample model.
if (limit != capacity) {
- final Vector v = Vector.create(bank.limit(capacity),
ImageUtilities.isUnsignedType(model));
+ final Vector v = Vector.create(bank.limit(capacity),
DataType.isUnsigned(model));
final Number f = fillValues[band];
/*
* If all values are the same, we can delegate (indirectly) to
an `Arrays.fill(…)` method.
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
index 8eae81ae1a..2249101ef6 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
@@ -1682,7 +1682,7 @@ final class ImageFileDirectory extends DataCube {
case UNSIGNED: {
if (bitsPerSample <= Byte .SIZE) return DataType.BYTE;
if (bitsPerSample <= Short .SIZE) return DataType.USHORT;
- if (bitsPerSample <= Integer.SIZE) return DataType.INT;
+ if (bitsPerSample <= Integer.SIZE) return DataType.UINT;
break;
}
case FLOAT: {
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/Writer.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/Writer.java
index 495927a0e1..d657f0ab60 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/Writer.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/Writer.java
@@ -43,7 +43,7 @@ import org.opengis.referencing.operation.TransformException;
import org.apache.sis.image.ImageProcessor;
import org.apache.sis.coverage.grid.GridGeometry;
import org.apache.sis.coverage.grid.IncompleteGridGeometryException;
-import org.apache.sis.image.privy.ImageUtilities;
+import org.apache.sis.image.DataType;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.DataStoreReferencingException;
import org.apache.sis.storage.IncompatibleResourceException;
@@ -363,7 +363,7 @@ final class Writer extends IOBase implements Flushable {
{
final SampleModel sm = image.exportable.getSampleModel();
Compression compression =
store.getCompression().orElse(Compression.DEFLATE);
- if (!ImageUtilities.isIntegerType(sm)) {
+ if (!DataType.isInteger(sm)) {
compression = compression.withPredictor(PREDICTOR_NONE);
}
/*
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/CopyFromBytes.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/CopyFromBytes.java
index 9e0565af5f..2d47dc5615 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/CopyFromBytes.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/CopyFromBytes.java
@@ -110,9 +110,10 @@ abstract class CopyFromBytes extends Inflater {
throws UnsupportedEncodingException
{
switch (dataType) {
+ case BYTE: return new Bytes (input, chunksPerRow,
samplesPerChunk, skipAfterChunks, pixelsPerElement);
case USHORT: // Fall through
case SHORT: return new Shorts (input, chunksPerRow,
samplesPerChunk, skipAfterChunks, pixelsPerElement);
- case BYTE: return new Bytes (input, chunksPerRow,
samplesPerChunk, skipAfterChunks, pixelsPerElement);
+ case UINT: // Fall through
case INT: return new Ints (input, chunksPerRow,
samplesPerChunk, skipAfterChunks, pixelsPerElement);
case FLOAT: return new Floats (input, chunksPerRow,
samplesPerChunk, skipAfterChunks, pixelsPerElement);
case DOUBLE: return new Doubles(input, chunksPerRow,
samplesPerChunk, skipAfterChunks, pixelsPerElement);
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/HorizontalPredictor.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/HorizontalPredictor.java
index 40e6b87276..82e5a12c89 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/HorizontalPredictor.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/HorizontalPredictor.java
@@ -105,9 +105,10 @@ abstract class HorizontalPredictor extends
PredictorChannel {
final int pixelStride, final int width)
{
switch (dataType) {
- case USHORT:
- case SHORT: return new Shorts (input, pixelStride, width);
case BYTE: return new Bytes (input, pixelStride, width);
+ case USHORT: // Fall through
+ case SHORT: return new Shorts (input, pixelStride, width);
+ case UINT: // Fall through
case INT: return new Integers(input, pixelStride, width);
case FLOAT: return new Floats (input, pixelStride, width);
case DOUBLE: return new Doubles (input, pixelStride, width);
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/HorizontalPredictor.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/HorizontalPredictor.java
index b6c174ec3b..2ec643fac2 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/HorizontalPredictor.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/HorizontalPredictor.java
@@ -72,9 +72,10 @@ abstract class HorizontalPredictor extends PredictorChannel {
final int pixelStride, final int scanlineStride)
{
switch (dataType) {
- case USHORT:
- case SHORT: return new Shorts (output, pixelStride,
scanlineStride);
case BYTE: return new Bytes (output, pixelStride,
scanlineStride);
+ case USHORT: // Fall through
+ case SHORT: return new Shorts (output, pixelStride,
scanlineStride);
+ case UINT: // Fall through
case INT: return new Integers(output, pixelStride,
scanlineStride);
case FLOAT: return new Floats (output, pixelStride,
scanlineStride);
case DOUBLE: return new Doubles (output, pixelStride,
scanlineStride);
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/ReformattedImage.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/ReformattedImage.java
index 0a9e64a32c..cc55c779ef 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/ReformattedImage.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/ReformattedImage.java
@@ -27,6 +27,7 @@ import static javax.imageio.plugins.tiff.BaselineTIFFTagSet.*;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.math.Statistics;
import org.apache.sis.pending.jdk.JDK18;
+import org.apache.sis.image.DataType;
import org.apache.sis.image.ImageLayout;
import org.apache.sis.image.PlanarImage;
import org.apache.sis.image.ImageProcessor;
@@ -208,8 +209,8 @@ found: if (property instanceof Statistics[]) {
*/
public int getSampleFormat() {
final SampleModel sm = exportable.getSampleModel();
- if (ImageUtilities.isUnsignedType(sm)) return
SAMPLE_FORMAT_UNSIGNED_INTEGER;
- if (ImageUtilities.isIntegerType(sm)) return
SAMPLE_FORMAT_SIGNED_INTEGER;
+ if (DataType.isUnsigned(sm)) return SAMPLE_FORMAT_UNSIGNED_INTEGER;
+ if (DataType.isInteger(sm)) return SAMPLE_FORMAT_SIGNED_INTEGER;
return SAMPLE_FORMAT_FLOATING_POINT;
}
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/TileMatrix.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/TileMatrix.java
index 0292e39dbd..e38be04eb6 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/TileMatrix.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/writer/TileMatrix.java
@@ -284,6 +284,7 @@ public final class TileMatrix {
case BYTE: rect.write(compOutput, ((DataBufferByte)
buffer).getData(b), offset, direct); break;
case USHORT: rect.write(compOutput,
((DataBufferUShort) buffer).getData(b), offset); break;
case SHORT: rect.write(compOutput, ((DataBufferShort)
buffer).getData(b), offset); break;
+ case UINT: // Fall through
case INT: rect.write(compOutput, ((DataBufferInt)
buffer).getData(b), offset); break;
case FLOAT: rect.write(compOutput, ((DataBufferFloat)
buffer).getData(b), offset); break;
case DOUBLE: rect.write(compOutput,
((DataBufferDouble) buffer).getData(b), offset); break;
diff --git
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/DataType.java
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/DataType.java
index f527627edc..d41f1d36a5 100644
---
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/DataType.java
+++
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/DataType.java
@@ -95,7 +95,7 @@ public enum DataType {
* 32 bits unsigned integer (netCDF type 9).
* Not available in netCDF classic format.
*/
- UINT(Numbers.INTEGER, Long.class, true, true, (byte) 4,
org.apache.sis.image.DataType.INT),
+ UINT(Numbers.INTEGER, Long.class, true, true, (byte) 4,
org.apache.sis.image.DataType.UINT),
/**
* 64 bits signed integer (netCDF type 10).
diff --git
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridResource.java
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridResource.java
index f62048a07d..c71bc419bd 100644
---
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridResource.java
+++
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/TiledGridResource.java
@@ -377,7 +377,7 @@ public abstract class TiledGridResource extends
AbstractGridCoverageResource {
*/
protected Number[] getFillValues(final int[] bands) throws
DataStoreException {
final SampleModel model = getSampleModel(bands);
- final var dataType = DataType.forDataBufferType(model.getDataType());
+ final var dataType = DataType.forBands(model);
IndexColorModel icm = null;
check: if (dataType.isInteger()) {
final ColorModel colors = getColorModel(bands);
diff --git
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java
index ba0a60df87..f3f1234c5c 100644
---
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java
+++
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/esri/RasterStore.java
@@ -42,9 +42,9 @@ import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.StorageConnector;
import org.apache.sis.storage.base.PRJDataStore;
import org.apache.sis.storage.base.MetadataBuilder;
+import org.apache.sis.image.DataType;
import org.apache.sis.image.privy.ColorModelFactory;
import org.apache.sis.image.privy.ColorModelBuilder;
-import org.apache.sis.image.privy.ImageUtilities;
import org.apache.sis.image.privy.ObservableImage;
import org.apache.sis.coverage.privy.RangeArgument;
import org.apache.sis.util.CharSequences;
@@ -339,9 +339,8 @@ abstract class RasterStore extends PRJDataStore implements
GridCoverageResource
* Build the sample dimensions and the color model.
* Some minimum/maximum values will be used as fallback if no
statistics were found.
*/
- final int dataType = sm.getDataType();
- final boolean isInteger = ImageUtilities.isIntegerType(dataType);
- final boolean isUnsigned = isInteger &&
ImageUtilities.isUnsignedType(sm);
+ final boolean isInteger = DataType.isInteger(sm);
+ final boolean isUnsigned = isInteger && DataType.isUnsigned(sm);
final boolean isRGB = isInteger && (bands.length == 3 ||
bands.length == 4);
final var builder = new SampleDimension.Builder();
for (int band=0; band < bands.length; band++) {
@@ -396,6 +395,7 @@ abstract class RasterStore extends PRJDataStore implements
GridCoverageResource
* The color file is optional and will be used if present.
*/
if (band == VISIBLE_BAND) {
+ final int dataType = sm.getDataType();
try {
if (isRGB) {
colorModel = new ColorModelBuilder().createRGB(sm);
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
index 496cf9bec2..a2670c23d8 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/coverage/GridView.java
@@ -45,7 +45,7 @@ import org.apache.sis.gui.internal.BackgroundThreads;
import org.apache.sis.gui.internal.LogHandler;
import org.apache.sis.gui.internal.Styles;
import org.apache.sis.gui.internal.ExceptionReporter;
-import org.apache.sis.image.privy.ImageUtilities;
+import org.apache.sis.image.DataType;
/**
@@ -492,7 +492,7 @@ public class GridView extends Control {
if (getBand() >= numBands) {
((BandProperty) bandProperty).setNoCheck(numBands - 1);
}
- cellFormat.dataTypeIsInteger =
ImageUtilities.isIntegerType(sm);
+ cellFormat.dataTypeIsInteger = DataType.isInteger(sm);
}
cellFormat.configure(image, getBand());
}