1 : /******************************************************************************
2 : * File : wktraster.h
3 : * Project: WKT Raster driver
4 : * Purpose: Main header file for PostGIS WKTRASTER/GDAL Driver
5 : * Author: Jorge Arevalo, jorgearevalo@gis4free.org
6 : *
7 : * Last changes: $Id: wktraster.h 18163 2009-12-03 17:47:38Z jorgearevalo $
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2009, Jorge Arevalo, jorgearevalo@gis4free.org
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ******************************************************************************/
30 : #include "gdal_priv.h"
31 : #include "libpq-fe.h"
32 : //#include "liblwgeom.h"
33 :
34 : /* Constant values for boolean variables */
35 : #define TRUE 1
36 : #define FALSE 0
37 :
38 : #define NDR 1 // Little endian
39 : #define XDR 0 // Big endian
40 :
41 :
42 : /* Working modes */
43 : #define REGULARLY_TILED_MODE "REGULARLY_TILED_MODE"
44 : #define IRREGULARLY_TILED_MODE "IRREGULARLY_TILED_MODE"
45 : #define IMAGE_WAREHOUSE "IMAGE_WAREHOUSE"
46 :
47 : #define DEFAULT_SCHEMA "public"
48 :
49 : // Supported raster version
50 : #define WKT_RASTER_VERSION (GUInt16)0
51 :
52 :
53 :
54 : // Utility function
55 : GByte GetMachineEndianess();
56 :
57 :
58 : class WKTRasterRasterBand;
59 : class WKTRasterWrapper;
60 :
61 : /************************************************************************
62 : * ====================================================================
63 : * WKTRasterDataset
64 : * ====================================================================
65 : * A set of associated raster bands, normally for one PostGIS table.
66 : ************************************************************************/
67 : class WKTRasterDataset : public GDALDataset {
68 : friend class WKTRasterRasterBand;
69 :
70 : // Private attributes and methods
71 : PGconn * hPGconn;
72 : GBool bCloseConnection;
73 : char * pszSchemaName;
74 : char * pszTableName;
75 : char * pszRasterColumnName;
76 : char * pszWhereClause;
77 : char * pszProjection;
78 : GBool bTableHasGISTIndex;
79 : int nVersion;
80 : int nBlockSizeX;
81 : int nBlockSizeY;
82 : double dfPixelSizeX;
83 : double dfPixelSizeY;
84 : double dfUpperLeftX;
85 : double dfUpperLeftY;
86 : double dfLowerRightX;
87 : double dfLowerRightY;
88 : double dfRotationX;
89 : double dfRotationY;
90 : int nSrid;
91 : char * pszWorkingMode;
92 : int nOverviews;
93 : WKTRasterDataset ** papoWKTRasterOv;
94 : GDALDataset * poOutdbRasterDS;
95 :
96 : // To be delete
97 : WKTRasterWrapper ** papoBlocks;
98 : int nBlocks;
99 :
100 :
101 :
102 :
103 : /**
104 : * Populate the georeference information fields of dataset
105 : * Parameters: none
106 : * Returns:
107 : * CPLErr: CE_None if the fields are populated, CE_Failure otherwise
108 : */
109 : CPLErr SetRasterProperties();
110 :
111 :
112 : /**
113 : * Explode a string representing an array into an array of strings. The input
114 : * string has this format: {element1,element2,element3,....,elementN}
115 : * Parameters:
116 : * const char *: a string representing an array
117 : * int *: pointer to an int that will contain the number of elements
118 : * Returns:
119 : * char **: An array of strings, one per element
120 : */
121 : char ** ExplodeArrayString(const char *, int *);
122 :
123 : /**
124 : * Implode an array of strings, to transform it into a PostgreSQL-style
125 : * array, with this format: {element1,element2,element3,....,elementN}
126 : * Parameters:
127 : * char **: An array of strings, one per element
128 : * int: An int that contains the number of elements
129 : * Returns:
130 : * const char *: a string representing an array
131 : */
132 : char * ImplodeStrings(char ** papszElements, int);
133 :
134 :
135 : /* Public attributes and methods */
136 : public:
137 :
138 : /**
139 : * Constructor. Init the class properties with default values
140 : */
141 : WKTRasterDataset();
142 :
143 : /**
144 : * Destructor. Frees allocated memory.
145 : */
146 : ~WKTRasterDataset();
147 :
148 : /**
149 : * Method: Open
150 : * Open a connection wiht PostgreSQL. The connection string will have this
151 : * format:
152 : * PG:[host='<host>]' user='<user>' [password='<password>]'
153 : * dbname='<dbname>' table='<raster_table>' [mode='working_mode'
154 : * where='<where_clause>'].
155 : * All the connection string, apart from table='table_name',
156 : * where='sql_where' and mode ='working_mode' is PQconnectdb-valid.
157 : *
158 : * NOTE: The table name can't include the schema in the form
159 : * <schema>.<table_name>,
160 : * and this is a TODO task.
161 : * Parameters:
162 : * - GDALOpenInfo *: pointer to a GDALOpenInfo structure, with useful
163 : * information for Dataset
164 : * Returns:
165 : * - GDALDataset *: pointer to a new GDALDataset instance on success,
166 : * NULL otherwise
167 : */
168 : static GDALDataset * Open(GDALOpenInfo *);
169 :
170 :
171 : /**
172 : * Method: GetGeoTransform
173 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
174 : * space and projection coordinates (Xp, Yp) space
175 : * The affine transformation performed is:
176 : * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
177 : * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
178 : * Parameters:
179 : * - double *: pointer to a double array, that will contains the affine
180 : * transformation matrix coefficients
181 : * Returns:
182 : * - CPLErr: CE_None on success, or CE_Failure if no transform can be
183 : * fetched.
184 : */
185 : CPLErr GetGeoTransform(double * padfTransform);
186 :
187 : /**
188 : * Fetch the projection definition string for this dataset in OpenGIS WKT
189 : * format. It should be suitable for use with the OGRSpatialReference class
190 : * Parameters: none
191 : * Returns:
192 : * - const char *: a pointer to an internal projection reference string.
193 : * It should not be altered, freed or expected to last for
194 : * long.
195 : */
196 : const char * GetProjectionRef();
197 :
198 : /**
199 : * Set the projection reference string for this dataset. The string should
200 : * be in OGC WKT or PROJ.4 format
201 : * Parameters:
202 : * - const char *: projection reference string.
203 : * Returns:
204 : * - CE_Failure if an error occurs, otherwise CE_None.
205 : */
206 : CPLErr SetProjection(const char *);
207 :
208 : /**
209 : * Set the affine transformation coefficients.
210 : * Parameters:
211 : * - double *:a six double buffer containing the transformation
212 : * coefficients to be written with the dataset.
213 : * Returns:
214 : * - CE_None on success, or CE_Failure if this transform cannot be written.
215 : */
216 : CPLErr SetGeoTransform(double *);
217 :
218 : };
219 :
220 : /************************************************************************
221 : * ====================================================================
222 : * WKTRasterRasterBand
223 : * ====================================================================
224 : *
225 : * A single WKT Raster band
226 : ************************************************************************/
227 0 : class WKTRasterRasterBand : public GDALRasterBand {
228 : // Friend class
229 : friend class WKTRasterDataset;
230 :
231 : // class attributes
232 : double dfNoDataValue;
233 : GBool bIsSignedByte;
234 : int nBitDepth;
235 :
236 : /**
237 : * Set the block data to the null value if it is set, or zero if there is
238 : * no null data value.
239 : * Parameters:
240 : * - void *: the block data
241 : * Returns: nothing
242 : */
243 : void NullBlock(void *);
244 :
245 : protected:
246 :
247 : /**
248 : * Read a block of image data
249 : * Parameters:
250 : * int: horizontal block offset
251 : * int: vertical block offset
252 : * void *: The buffer into the data will be read
253 : * Returns:
254 : * CE_None on success, CE_Failure on error
255 : */
256 : virtual CPLErr IReadBlock(int, int, void *);
257 :
258 : /**
259 : * Write a block of data to the raster band. First establish if a
260 : * corresponding row to the block already exists with a SELECT. If so,
261 : * update the raster column contents. If it does not exist create a new
262 : * row for the block.
263 : * Parameters:
264 : * int: horizontal block offset
265 : * int: vertical block offset
266 : * void *: The buffer wit the data to be written
267 : * Returns:
268 : * CE_None on success, CE_Failure on error
269 : */
270 : virtual CPLErr IWriteBlock(int, int, void *);
271 :
272 : public:
273 : /**
274 : * Constructor.
275 : * Parameters:
276 : * - WKTRasterDataset *: The Dataset this band belongs to
277 : * - int: the band number
278 : * - GDALDataType: The data type for this band
279 : * - double: The nodata value. Could be any kind of data (GByte, GUInt16,
280 : * GInt32...) but the variable has the bigger type.
281 : * - GBool: if the data type is signed byte or not. If yes, the SIGNEDBYTE
282 : * metadata value is added to IMAGE_STRUCTURE domain
283 : * - int: The bit depth, to add NBITS as metadata value in IMAGE_STRUCTURE
284 : * domain.
285 : */
286 : WKTRasterRasterBand(WKTRasterDataset *, int, GDALDataType, double, GBool,
287 : int);
288 :
289 : /**
290 : * Set the no data value for this band.
291 : * Parameters:
292 : * - double: The nodata value
293 : * Returns:
294 : * - CE_None.
295 : */
296 : CPLErr SetNoDataValue(double);
297 :
298 : /**
299 : * Fetch the no data value for this band.
300 : * Parameters:
301 : * - int *: pointer to a boolean to use to indicate if a value is actually
302 : * associated with this layer. May be NULL (default).
303 : * Returns:
304 : * - double: the nodata value for this band.
305 : */
306 : virtual double GetNoDataValue(int *pbSuccess = NULL);
307 :
308 : /**
309 : * Returns the number of overview layers available.
310 : * Parameters: none
311 : * Returns:
312 : * int: the number of overviews layers available
313 : */
314 : virtual int GetOverviewCount();
315 :
316 : /**
317 : * Fetch overview raster band object.
318 : * Parameters:
319 : * - int: overview index between 0 and GetOverviewCount()-1
320 : * Returns:
321 : * - GDALRasterBand *: overview GDALRasterBand.
322 : */
323 : virtual GDALRasterBand * GetOverview(int);
324 :
325 :
326 : /**
327 : * Get the natural block size for this band.
328 : * Parameters:
329 : * - int *: pointer to int to store the natural X block size
330 : * - int *: pointer to int to store the natural Y block size
331 : * Returns: nothing
332 : */
333 : virtual void GetBlockSize(int *, int *);
334 :
335 : /**
336 : * Says if the datatype for this band is signedbyte.
337 : * Parameters: none
338 : * Returns:
339 : * - TRUE if the datatype for this band is signedbyte, FALSE otherwise
340 : */
341 : GBool IsSignedByteDataType();
342 :
343 : /**
344 : * Get the bit depth for this raster band
345 : * Parameters: none.
346 : * Returns: the bit depth
347 : */
348 : int GetNBitDepth();
349 :
350 : };
351 :
352 :
353 :
354 :
355 : /**************************************************************************
356 : * ======================================================================
357 : * WKTRasterBandWrapper
358 : * ======================================================================
359 : *
360 : * This class wrapps the HEXWKB representation of a PostGIS WKT Raster
361 : * Band, that is a part of the wrapper of a WKT Raster.
362 : *
363 : * TODO:
364 : * - Allow changing the size of the nodatavalue, that implies modify the
365 : * allocated memory for HexWkb representation of the WKT Raster. Now, you
366 : * only can change the value, not the size.
367 : * - Avoid the use of double instead of double, to ensure compatibility
368 : * with WKTRasterRasterBand types. Discuss it.
369 : ***************************************************************************/
370 :
371 : // To declare this class as friend class
372 : class WKTRasterWrapper;
373 :
374 : class WKTRasterBandWrapper {
375 : // Friend classes
376 : friend class WKTRasterWrapper;
377 : friend class WKTRasterRasterBand;
378 :
379 : // Class attributes
380 : GBool bIsOffline;
381 : GByte byReserved;
382 : GByte byPixelType;
383 : double dfNodata;
384 : GByte * pbyData;
385 : GUInt32 nDataSize;
386 : GUInt16 nBand;
387 : GByte nOutDbBandNumber;
388 :
389 :
390 : // Pointer to the raster wrapper
391 : WKTRasterWrapper * poRW;
392 :
393 : public:
394 : /**
395 : * Constructor.
396 : * Parameters:
397 : * - WKTRasterWrapper *: the WKT Raster wrapper this band belongs to
398 : * - GUInt16: band number
399 : * - GByte: The first byte of the band header (contains the value for
400 : * other class properties).
401 : * - double: The nodata value. Could be any kind of data (GByte,
402 : * GUInt16, GInt32...) but the variable has the bigger type
403 : */
404 : WKTRasterBandWrapper(WKTRasterWrapper *, GUInt16, GByte, double);
405 :
406 :
407 : /**
408 : * Class destructor. Frees the memory and resources allocated.
409 : */
410 : ~WKTRasterBandWrapper();
411 :
412 : /**
413 : * Set the raster band data. This method updates the data of the raster
414 : * band. Then, when the HexWkb representation of the raster is
415 : * required (via WKTRasterWrapper::GetBinaryRepresentation or
416 : * WKTRasterWrapper::GetHexWkbRepresentation), the new data will
417 : * be packed instead the data of the original HexWkb representation
418 : * used to create the WKTRasterWrapper.
419 : * Parameters:
420 : * - GByte *: The data to set
421 : * - GUInt32: data size
422 : * Returns:
423 : * - CE_None if the data is set, CE_Failure otherwise
424 : */
425 : CPLErr SetData(GByte *, GUInt32);
426 :
427 :
428 : /**
429 : * Get the raster band data.
430 : * Parameters: nothing
431 : * Returns:
432 : * - GByte *: The raster band data
433 : */
434 : GByte * GetData();
435 : };
436 :
437 : /************************************************************************
438 : * ====================================================================
439 : * WKTRasterWrapper
440 : * ====================================================================
441 : *
442 : * This class wraps the HEXWKB representation of a PostGIS WKT Raster.
443 : *
444 : * It splits the hexwkb string into fields, and reconstructs this string
445 : * from the fields each time that the representation is required (see
446 : * GetBinaryRepresentation method).
447 : *
448 : * The best way to get the representation of the raster is by using the
449 : * GetBinaryRepresentation and GetHexWkbRepresentation methods. This
450 : * methods construct the representation based on the class properties.
451 : *
452 : * If you access the pszHexWkb or pbyHexWkb variables directly, you may
453 : * get a non-updated version of the raster. Anyway, you only can access
454 : * this variables from friend classes.
455 : ************************************************************************/
456 : class WKTRasterWrapper {
457 : // Friend classes
458 : friend class WKTRasterBandWrapper;
459 : friend class WKTRasterRasterBand;
460 :
461 : // Attributes of a PostGIS WKT Raster
462 : GByte byEndianess;
463 : GUInt16 nVersion;
464 : GUInt16 nBands;
465 : double dfScaleX;
466 : double dfScaleY;
467 : double dfIpX;
468 : double dfIpY;
469 : double dfSkewX;
470 : double dfSkewY;
471 : GInt32 nSrid;
472 : GUInt16 nWidth;
473 : GUInt16 nHeight;
474 : WKTRasterBandWrapper ** papoBands;
475 : int nLengthHexWkbString;
476 : int nLengthByWkbString;
477 :
478 : // binary and string hexwkb representations
479 : char * pszHexWkb;
480 : GByte * pbyHexWkb;
481 :
482 : // WKT string (polygon)
483 : char * pszWktExtent;
484 :
485 :
486 :
487 : public:
488 :
489 : /**
490 : * Class constructor
491 : */
492 : WKTRasterWrapper();
493 :
494 : /**
495 : * Class destructor. Frees the memory and resources allocated.
496 : */
497 : ~WKTRasterWrapper();
498 :
499 : /**
500 : * Fill all the raster properties with the string
501 : * hexwkb representation given as input.
502 : * This method swaps words if the raster endianess is distinct from
503 : * the machine endianess
504 : * Properties:
505 : * const char *: the string hexwkb representation of the raster
506 : * Returns :
507 : * - int : TRUE if all right
508 : */
509 : int Initialize(const char* pszHex);
510 :
511 : /**
512 : * Creates a polygon in WKT representation that wrapps all the extent
513 : * covered by the raster
514 : * Parameters: nothing
515 : * Returns:
516 : * char *: The polygon in WKT format
517 : */
518 : const char * GetWktExtent();
519 :
520 : /**
521 : * Constructs the binary representation of the PostGIS WKT raster wrapped
522 : * by this class, based on all the class properties.
523 : * This method swaps words if the raster endianess is distinct from
524 : * the machine endianess.
525 : * Parameters: nothing
526 : * Returns:
527 : * - GByte *: Binary representation of the hexwkb string
528 : */
529 : GByte * GetBinaryRepresentation();
530 :
531 :
532 : /**
533 : * Constructs the hexwkb representation of the PostGIS WKT raster wrapped
534 : * by this class, based on all the class properties.
535 : * This method swaps words if the raster endianess is distinct from
536 : * the machine endianess.
537 : * Parameters: nothing
538 : * Returns:
539 : * - GByte *: Hexwkb string
540 : */
541 : char * GetHexWkbRepresentation();
542 :
543 : /**
544 : * Gets a wrapper of a RasterBand, as a WKTRasterBandWrapper object.
545 : * Properties:
546 : * - GUInt16: the band number.
547 : * Returns:
548 : * - WKTRasterWrapper *: an object that wrapps the RasterBand
549 : */
550 : WKTRasterBandWrapper * GetBand(GUInt16);
551 : };
|