in endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/RasterReader.java [184:299]
public WritableRaster readAsRaster(final ChannelDataInput input) throws IOException {
final ByteOrder order;
switch (input.readUnsignedByte()) {
case 0: order = ByteOrder.BIG_ENDIAN; break;
case 1: order = ByteOrder.LITTLE_ENDIAN; break;
default: throw malformed(input);
}
input.buffer.order(order);
final int version = input.readUnsignedShort();
if (version != 0) {
throw new IOException(Errors.format(Errors.Keys.UnsupportedFormatVersion_2, "WKB", version));
}
final int numBands = input.readUnsignedShort();
final double scaleX = input.readDouble();
final double scaleY = input.readDouble();
final double ipX = input.readDouble();
final double ipY = input.readDouble();
final double skewX = input.readDouble();
final double skewY = input.readDouble();
gridToCRS = new AffineTransform2D(scaleX, skewY, skewX, scaleY, ipX, ipY);
srid = input.readInt();
if (numBands == 0) { // Empty raster.
return null;
}
final int width = input.readUnsignedShort();
final int height = input.readUnsignedShort();
final Band[] bands = new Band[numBands];
for (int i=0; i<numBands; i++) {
final Band band = new Band(input.readUnsignedByte());
final int dataType = band.getDataBufferType();
final Number nodata;
switch (dataType) {
case DataBuffer.TYPE_BYTE: nodata = input.readUnsignedByte(); break;
case DataBuffer.TYPE_BYTE | OPPOSITE_SIGN: nodata = input.readByte(); break;
case DataBuffer.TYPE_SHORT: nodata = input.readShort(); break;
case DataBuffer.TYPE_USHORT: nodata = input.readUnsignedShort(); break;
case DataBuffer.TYPE_INT: nodata = input.readInt(); break;
case DataBuffer.TYPE_INT | OPPOSITE_SIGN: nodata = input.readUnsignedInt(); break;
case DataBuffer.TYPE_FLOAT: nodata = input.readFloat(); break;
case DataBuffer.TYPE_DOUBLE: nodata = input.readDouble(); break;
case DataBuffer.TYPE_UNDEFINED: // For detecting case conflict at compile time.
default: throw malformed(input);
}
if (band.hasNodata()) {
band.noDataValue = nodata;
}
if (band.isOffline()) {
throw new RasterFormatException("Offline raster data is not yet supported.");
} else {
/*
* Read sample values for the current band.
* We ignore the signed or unsigned nature of values here.
*/
final int sampleSize = band.getDataTypeSize(); // In bits: 1, 2, 4, 8, 16, 32 or 64.
final int elementSize = DataBuffer.getDataTypeSize(dataType); // Same as above except for 1, 2, 4.
final int length = Math.toIntExact(JDK18.ceilDiv(Math.multiplyFull(width, height) * sampleSize, elementSize));
final Object data;
switch (dataType & ~OPPOSITE_SIGN) {
case DataBuffer.TYPE_USHORT:
case DataBuffer.TYPE_SHORT: data = input.readShorts (length); break;
case DataBuffer.TYPE_BYTE: data = input.readBytes (length); break;
case DataBuffer.TYPE_INT: data = input.readInts (length); break;
case DataBuffer.TYPE_FLOAT: data = band.toNaN(input.readFloats (length)); break;
case DataBuffer.TYPE_DOUBLE: data = band.toNaN(input.readDoubles(length)); break;
default: throw malformed(input);
}
band.data = data;
}
bands[i] = band;
}
/*
* All bands should be of the same type. We could convert data to
* a common type (the largest one), but this is not yet implemented.
*/
final Band firstBand = bands[0];
int dataType = firstBand.getDataBufferType();
final int length = Array.getLength(firstBand.data);
final Object[] arrays = (Object[]) Array.newInstance(firstBand.data.getClass(), numBands);
arrays[0] = firstBand.data;
for (int b=1; b<numBands; b++) {
final Band band = bands[b];
if (band.getDataBufferType() != dataType || Array.getLength(band.data) != length) {
throw new RasterFormatException("Bands of different types are not yet supported.");
}
arrays[b] = band.data;
}
this.bands = bands;
/*
* Create the `DataBuffer` and `SampleModel` for the bands.
* Objects are only wrappers; pixel values are not copied.
*/
final DataBuffer buffer;
switch (dataType &= ~OPPOSITE_SIGN) {
case DataBuffer.TYPE_BYTE: buffer = new DataBufferByte ((byte [][]) arrays, length); break;
case DataBuffer.TYPE_SHORT: buffer = new DataBufferShort ((short [][]) arrays, length); break;
case DataBuffer.TYPE_USHORT: buffer = new DataBufferUShort((short [][]) arrays, length); break;
case DataBuffer.TYPE_INT: buffer = new DataBufferInt ((int [][]) arrays, length); break;
case DataBuffer.TYPE_FLOAT: buffer = new DataBufferFloat ((float [][]) arrays, length); break;
case DataBuffer.TYPE_DOUBLE: buffer = new DataBufferDouble((double[][]) arrays, length); break;
default: throw malformed(input);
}
SampleModel model;
final int sampleSize = firstBand.getDataTypeSize();
if (sampleSize >= Byte.SIZE) {
model = new BandedSampleModel(dataType, width, height, numBands);
} else if (numBands == 1) {
model = new MultiPixelPackedSampleModel(dataType, width, height, sampleSize);
} else {
throw new RasterFormatException("Multi-bands packed model is not yet supported.");
}
if (model.equals(cachedModel)) {
model = cachedModel;
}
cachedModel = model;
return WritableRaster.createWritableRaster(model, buffer, null);
}