rdf4j-postgis  Version 0.1.0.0
WKBRasterReader Class Reference

WKB Raster Reader, used in postGIS 2 but can be used elsewhere. More...

Collaboration diagram for WKBRasterReader:

Public Member Functions

 WKBRasterReader ()
 
void reset ()
 Reset values before new read call. More...
 
AffineTransform2D getGridToCRS ()
 Get the Grid to CRS transform, can be called after read only. More...
 
int getSRID ()
 Get the postgis srid, can be called after read only. More...
 
GridCoverage readCoverage (byte[] data, CRSAuthorityFactory authorityFactory) throws IOException, NoSuchAuthorityCodeException, FactoryException
 Parse given byte[] and rebuild a GridCoverage2D. More...
 
GridCoverage readCoverage (final InputStream stream, CRSAuthorityFactory authorityFactory) throws IOException, NoSuchAuthorityCodeException, FactoryException
 Parse given InputStream and rebuild a GridCoverage2D. More...
 
BufferedImage read (byte[] data) throws IOException
 Parse given byte[] and rebuild RenderedImage. More...
 
BufferedImage read (final InputStream stream) throws IOException
 Parse given InputStream and rebuild RenderedImage. More...
 

Private Attributes

AffineTransform2D gridToCRS = null
 
int srid = 0
 

Detailed Description

WKB Raster Reader, used in postGIS 2 but can be used elsewhere.

Author
Johann Sorel (Geomatys)

Constructor & Destructor Documentation

◆ WKBRasterReader()

74  {
75  }

Member Function Documentation

◆ getGridToCRS()

AffineTransform2D getGridToCRS ( )

Get the Grid to CRS transform, can be called after read only.

Returns
AffineTransform2D
89  {
90  return gridToCRS;
91  }
AffineTransform2D gridToCRS
Definition: WKBRasterReader.java:71

References WKBRasterReader.gridToCRS.

Referenced by WKBRasterReader.readCoverage().

◆ getSRID()

int getSRID ( )

Get the postgis srid, can be called after read only.

Returns
int, postgid srid
97  {
98  return srid;
99  }
int srid
Definition: WKBRasterReader.java:72

References WKBRasterReader.srid.

◆ read() [1/2]

BufferedImage read ( byte[]  data) throws IOException

Parse given byte[] and rebuild RenderedImage.

Parameters
data
Returns
Exceptions
IOException
150  {
151  final InputStream stream = new ByteArrayInputStream(data);
152  return read(stream);
153  }
BufferedImage read(byte[] data)
Parse given byte[] and rebuild RenderedImage.
Definition: WKBRasterReader.java:150

Referenced by WKBRasterImageReader.read(), and WKBRasterReader.readCoverage().

◆ read() [2/2]

BufferedImage read ( final InputStream  stream) throws IOException

Parse given InputStream and rebuild RenderedImage.

Parameters
stream
Returns
Exceptions
IOException
162  {
163 
164  final DataInput ds;
165  final boolean littleEndian = stream.read() == 1;
166  if(littleEndian){
167  //big endian
168  ds = new LEDataInputStream(stream);
169  }else{
170  //little endian
171  ds = new DataInputStream(stream);
172  }
173 
174  final int version = ds.readUnsignedShort();
175  final int nbBand = ds.readUnsignedShort();
176  //grid to crs
177  final double scaleX = ds.readDouble();
178  final double scaleY = ds.readDouble();
179  final double ipX = ds.readDouble();
180  final double ipY = ds.readDouble();
181  final double skewX = ds.readDouble();
182  final double skewY = ds.readDouble();
183  gridToCRS = new AffineTransform2D(scaleX, skewY, skewX, scaleY, ipX, ipY);
184 
185 
186  srid = ds.readInt();
187  final int width = ds.readUnsignedShort();
188  final int height = ds.readUnsignedShort();
189 
190  if(nbBand == 0){
191  //possible for empty raster
192  return null;
193  }
194 
195  final WKBRasterBand[] bands = new WKBRasterBand[nbBand];
196 
197  for(int i=0;i<nbBand;i++){
198  final WKBRasterBand band = new WKBRasterBand();
199 
200  final byte b = ds.readByte();
201  band.setPixelType(b & BANDTYPE_PIXTYPE_MASK);
202  band.setOffDatabase( (b & BANDTYPE_FLAG_OFFDB) != 0);
203  band.setHasNodata( (b & BANDTYPE_FLAG_HASNODATA) != 0);
204  band.setIsNodata( (b & BANDTYPE_FLAG_ISNODATA) != 0);
205  band.setReserved( (b & BANDTYPE_FLAG_RESERVED3) != 0);
206 
207  /* read nodata value */
208  switch (band.getPixelType()) {
209  case PT_1BB:
210  case PT_2BUI:
211  case PT_4BUI:
212  case PT_8BUI:
213  band.setNoDataValue(ds.readUnsignedByte());
214  break;
215  case PT_8BSI:
216  band.setNoDataValue(ds.readByte());
217  break;
218  case PT_16BSI:
219  band.setNoDataValue(ds.readShort());
220  break;
221  case PT_16BUI:
222  band.setNoDataValue(ds.readUnsignedShort());
223  break;
224  case PT_32BSI:
225  band.setNoDataValue(ds.readInt());
226  break;
227  case PT_32BUI:
228  band.setNoDataValue(ds.readInt() & 0x00000000ffffffffL);
229  break;
230  case PT_32BF:
231  band.setNoDataValue(ds.readFloat());
232  break;
233  case PT_64BF:
234  band.setNoDataValue(ds.readDouble());
235  break;
236  default:
237  throw new IOException("unknowned pixel type : "+band.getPixelType());
238  }
239 
240  if(band.isOffDatabase()){
241  throw new IOException("can not access data which are off database");
242  }else{
243  //read values
244  final int nbBytePerPixel = band.getNbBytePerPixel();
245  final byte[] datas = new byte[width*height*band.getNbBytePerPixel()];
246  ds.readFully(datas);
247  if(littleEndian && nbBytePerPixel > 1){
248  //image databank expect values in big endian so we must flip bytes
249  byte temp;
250  for(int k=0;k<datas.length;k+=nbBytePerPixel){
251  for(int p=0,n=nbBytePerPixel/2; p<n ;p++){
252  final int index1 = k+p;
253  final int index2 = k+(nbBytePerPixel-p-1);
254  temp = datas[index1];
255  datas[index1] = datas[index2];
256  datas[index2] = temp;
257  }
258  }
259  }
260  band.setDatas(datas);
261  }
262 
263  bands[i] = band;
264  }
265 
266  //we expect all bands to have the same type
267  final int dataBufferType = bands[0].getDataBufferType();
268 
269  //rebuild raster
270  final WritableRaster raster;
271  double min = Double.MAX_VALUE;
272  double max = Double.MIN_VALUE;
273 
274  if(dataBufferType == DataBuffer.TYPE_BYTE){
275  //more efficient but only works for byte type bands
276  //check all band have the same sample model and rebuild data buffer
277  Integer dataType = null;
278  final byte[][] dataArray = new byte[nbBand][0];
279  final int[] bankIndices = new int[nbBand];
280  final int[] bankOffsets = new int[nbBand];
281  for(int i=0;i<bands.length;i++){
282  final WKBRasterBand band = bands[i];
283  if(dataType == null){
284  dataType = band.getDataBufferType();
285  }else if(dataType != band.getDataBufferType()){
286  throw new IOException("Band type differ, can not be mapped to java image.");
287  }
288  dataArray[i] = band.getDatas();
289  bankIndices[i] = i;
290  bankOffsets[i] = 0;
291  }
292 
293  min = -100.0;
294  max = 100.0;
295 
296  //rebuild data buffer
297  final DataBuffer db = new DataBufferByte(dataArray, dataArray[0].length);
298  final int scanlineStride = width;
299  raster = RasterFactory.createBandedRaster(
300  db, width, height, scanlineStride, bankIndices, bankOffsets, new Point(0,0));
301 
302  }else{
303  raster = RasterFactory.createBandedRaster(dataBufferType,width,height,nbBand,new Point(0,0));
304  for(int i=0;i<bands.length;i++){
305  final byte[] datas = bands[i].getDatas();
306  final DataInputStream dds = new DataInputStream(new ByteArrayInputStream(datas));
307  for(int y=0;y<height;y++){
308  for(int x=0;x<width;x++){
309  switch (dataBufferType) {
310  case DataBuffer.TYPE_SHORT:
311  short d1 = dds.readShort();
312  raster.setSample(x, y, i, d1);
313  min = Math.min(min, (double)d1);
314  max = Math.max(max, (double)d1);
315  break;
316  case DataBuffer.TYPE_USHORT:
317  int d2 = dds.readUnsignedShort();
318  raster.setSample(x, y, i, d2);
319  min = Math.min(min, (double)d2);
320  max = Math.max(max, (double)d2);
321  break;
322  case DataBuffer.TYPE_INT:
323  int d3 = dds.readInt();
324  raster.setSample(x, y, i, d3);
325  min = Math.min(min, (double)d3);
326  max = Math.max(max, (double)d3);
327  break;
328  case DataBuffer.TYPE_FLOAT:
329  float d4 = dds.readFloat();
330  raster.setSample(x, y, i, d4);
331  min = Math.min(min, (double)d4);
332  max = Math.max(max, (double)d4);
333  break;
334  case DataBuffer.TYPE_DOUBLE:
335  double d5 = dds.readDouble();
336  raster.setSample(x, y, i, d5);
337  min = Math.min(min, d5);
338  max = Math.max(max, d5);
339  break;
340  default:
341  throw new IllegalArgumentException("unknowned data buffer type : " + dataBufferType);
342  }
343  }
344  }
345  }
346  }
347  //rebuild image
348  final SampleModel sm = raster.getSampleModel();
349  ColorModel cm = PlanarImage.getDefaultColorModel(sm.getDataType(), raster.getNumBands());
350  if(cm==null){
351  //fallback
352  cm = (ColorModel) ColorModelFactory.GRAYSCALE; //createGrayScale(sm.getDataType(), raster.getNumBands(), 0, min, max);
353  }
354  return new BufferedImage(cm, raster, false, null);
355  }

References WKBRasterBand.getDataBufferType(), WKBRasterBand.getDatas(), WKBRasterBand.getNbBytePerPixel(), WKBRasterBand.getPixelType(), WKBRasterReader.gridToCRS, WKBRasterBand.isOffDatabase(), WKBRasterBand.setDatas(), WKBRasterBand.setHasNodata(), WKBRasterBand.setIsNodata(), WKBRasterBand.setNoDataValue(), WKBRasterBand.setOffDatabase(), WKBRasterBand.setPixelType(), WKBRasterBand.setReserved(), and WKBRasterReader.srid.

◆ readCoverage() [1/2]

GridCoverage readCoverage ( byte[]  data,
CRSAuthorityFactory  authorityFactory 
) throws IOException, NoSuchAuthorityCodeException, FactoryException

Parse given byte[] and rebuild a GridCoverage2D.

Parameters
data
Returns
Exceptions
IOException
109  {
110  final InputStream stream = new ByteArrayInputStream(data);
111  return readCoverage(stream,authorityFactory);
112  }
GridCoverage readCoverage(byte[] data, CRSAuthorityFactory authorityFactory)
Parse given byte[] and rebuild a GridCoverage2D.
Definition: WKBRasterReader.java:108

Referenced by HexWKBRastDatatype.read(), and WKBRastDatatype.read().

◆ readCoverage() [2/2]

GridCoverage readCoverage ( final InputStream  stream,
CRSAuthorityFactory  authorityFactory 
) throws IOException, NoSuchAuthorityCodeException, FactoryException

Parse given InputStream and rebuild a GridCoverage2D.

Parameters
stream
Returns
Exceptions
IOException
122  {
123  final BufferedImage image = read(stream);
124  final String epsgCode = "EPSG:"+srid;
125  final CoordinateReferenceSystem crs;
126  if (authorityFactory != null) {
127  crs = authorityFactory.createCoordinateReferenceSystem(epsgCode);
128  } else {
129  crs = CRS.forCode(epsgCode);
130  }
131  GridExtent extent=new GridExtent(image.getWidth(), image.getHeight());
132  GridGeometry gridgeom=new GridGeometry(extent, PixelInCell.CELL_CENTER, getGridToCRS(), crs);
133  List<SampleDimension> dimensions=new LinkedList<SampleDimension>();
134  DefaultNameFactory fac=new DefaultNameFactory();
135  for(int i=0;i<image.getRaster().getNumBands();i++) {
136  dimensions.add(new SampleDimension(fac.createGenericName(null, "Dimension "+i),0.,new LinkedList<Category>()));
137  }
138  BufferedGridCoverage cov=new BufferedGridCoverage(
139  gridgeom, dimensions, image.getData().getDataBuffer());
140  return cov;
141  }
AffineTransform2D getGridToCRS()
Get the Grid to CRS transform, can be called after read only.
Definition: WKBRasterReader.java:89

References WKBRasterReader.getGridToCRS(), WKBRasterReader.read(), and WKBRasterReader.srid.

◆ reset()

void reset ( )

Reset values before new read call.

80  {
81  gridToCRS = null;
82  srid = 0;
83  }

References WKBRasterReader.gridToCRS, and WKBRasterReader.srid.

Member Data Documentation

◆ gridToCRS

AffineTransform2D gridToCRS = null
private

◆ srid