1 : /******************************************************************************
2 : * $Id: gmtdataset.cpp 23060 2011-09-05 17:58:30Z rouault $
3 : *
4 : * Project: netCDF read/write Driver
5 : * Purpose: GDAL bindings over netCDF library for GMT Grids.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2004, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gdal_pam.h"
31 : #include "gdal_frmts.h"
32 : #include "netcdf.h"
33 :
34 : CPL_CVSID("$Id: gmtdataset.cpp 23060 2011-09-05 17:58:30Z rouault $");
35 :
36 : /************************************************************************/
37 : /* ==================================================================== */
38 : /* GMTDataset */
39 : /* ==================================================================== */
40 : /************************************************************************/
41 :
42 : class GMTRasterBand;
43 :
44 : class GMTDataset : public GDALPamDataset
45 16 : {
46 : int z_id;
47 : double adfGeoTransform[6];
48 :
49 : public:
50 : int cdfid;
51 :
52 : ~GMTDataset();
53 :
54 : static GDALDataset *Open( GDALOpenInfo * );
55 :
56 : CPLErr GetGeoTransform( double * padfTransform );
57 : };
58 :
59 : /************************************************************************/
60 : /* ==================================================================== */
61 : /* GMTRasterBand */
62 : /* ==================================================================== */
63 : /************************************************************************/
64 :
65 : class GMTRasterBand : public GDALPamRasterBand
66 16 : {
67 : nc_type nc_datatype;
68 : int nZId;
69 :
70 : public:
71 :
72 : GMTRasterBand( GMTDataset *poDS, int nZId, int nBand );
73 :
74 : virtual CPLErr IReadBlock( int, int, void * );
75 : };
76 :
77 :
78 : /************************************************************************/
79 : /* GMTRasterBand() */
80 : /************************************************************************/
81 :
82 16 : GMTRasterBand::GMTRasterBand( GMTDataset *poDS, int nZId, int nBand )
83 :
84 : {
85 16 : this->poDS = poDS;
86 16 : this->nBand = nBand;
87 16 : this->nZId = nZId;
88 :
89 16 : nBlockXSize = poDS->GetRasterXSize();
90 16 : nBlockYSize = 1;
91 :
92 : /* -------------------------------------------------------------------- */
93 : /* Get the type of the "z" variable, our target raster array. */
94 : /* -------------------------------------------------------------------- */
95 16 : if( nc_inq_var( poDS->cdfid, nZId, NULL, &nc_datatype, NULL, NULL,
96 : NULL ) != NC_NOERR )
97 : {
98 : CPLError( CE_Failure, CPLE_AppDefined,
99 0 : "Error in nc_var_inq() on 'z'." );
100 0 : return;
101 : }
102 :
103 16 : if( nc_datatype == NC_BYTE )
104 0 : eDataType = GDT_Byte;
105 16 : else if( nc_datatype == NC_SHORT )
106 8 : eDataType = GDT_Int16;
107 8 : else if( nc_datatype == NC_INT )
108 2 : eDataType = GDT_Int32;
109 6 : else if( nc_datatype == NC_FLOAT )
110 4 : eDataType = GDT_Float32;
111 2 : else if( nc_datatype == NC_DOUBLE )
112 2 : eDataType = GDT_Float64;
113 : else
114 : {
115 0 : if( nBand == 1 )
116 : CPLError( CE_Warning, CPLE_AppDefined,
117 : "Unsupported GMT datatype (%d), treat as Float32.",
118 0 : (int) nc_datatype );
119 0 : eDataType = GDT_Float32;
120 : }
121 0 : }
122 :
123 : /************************************************************************/
124 : /* IReadBlock() */
125 : /************************************************************************/
126 :
127 180 : CPLErr GMTRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
128 : void * pImage )
129 :
130 : {
131 : size_t start[2], edge[2];
132 180 : int nErr = NC_NOERR;
133 180 : int cdfid = ((GMTDataset *) poDS)->cdfid;
134 :
135 180 : start[0] = nBlockYOff * nBlockXSize;
136 180 : edge[0] = nBlockXSize;
137 :
138 180 : if( eDataType == GDT_Byte )
139 : nErr = nc_get_vara_uchar( cdfid, nZId, start, edge,
140 0 : (unsigned char *) pImage );
141 180 : else if( eDataType == GDT_Int16 )
142 : nErr = nc_get_vara_short( cdfid, nZId, start, edge,
143 80 : (short int *) pImage );
144 100 : else if( eDataType == GDT_Int32 )
145 : {
146 : if( sizeof(long) == 4 )
147 : nErr = nc_get_vara_long( cdfid, nZId, start, edge,
148 : (long *) pImage );
149 : else
150 : nErr = nc_get_vara_int( cdfid, nZId, start, edge,
151 0 : (int *) pImage );
152 : }
153 100 : else if( eDataType == GDT_Float32 )
154 : nErr = nc_get_vara_float( cdfid, nZId, start, edge,
155 100 : (float *) pImage );
156 0 : else if( eDataType == GDT_Float64 )
157 : nErr = nc_get_vara_double( cdfid, nZId, start, edge,
158 0 : (double *) pImage );
159 :
160 180 : if( nErr != NC_NOERR )
161 : {
162 : CPLError( CE_Failure, CPLE_AppDefined,
163 : "GMT scanline fetch failed: %s",
164 0 : nc_strerror( nErr ) );
165 0 : return CE_Failure;
166 : }
167 : else
168 180 : return CE_None;
169 : }
170 :
171 : /************************************************************************/
172 : /* ==================================================================== */
173 : /* GMTDataset */
174 : /* ==================================================================== */
175 : /************************************************************************/
176 :
177 : /************************************************************************/
178 : /* ~GMTDataset() */
179 : /************************************************************************/
180 :
181 16 : GMTDataset::~GMTDataset()
182 :
183 : {
184 16 : FlushCache();
185 16 : nc_close (cdfid);
186 16 : }
187 :
188 : /************************************************************************/
189 : /* GetGeoTransform() */
190 : /************************************************************************/
191 :
192 14 : CPLErr GMTDataset::GetGeoTransform( double * padfTransform )
193 :
194 : {
195 14 : memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
196 14 : return CE_None;
197 : }
198 :
199 : /************************************************************************/
200 : /* Open() */
201 : /************************************************************************/
202 :
203 25512 : GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
204 :
205 : {
206 : /* -------------------------------------------------------------------- */
207 : /* Does this file have the GMT magic number? */
208 : /* -------------------------------------------------------------------- */
209 25512 : if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 50 )
210 22592 : return NULL;
211 :
212 4182 : if( poOpenInfo->pabyHeader[0] != 'C'
213 434 : || poOpenInfo->pabyHeader[1] != 'D'
214 414 : || poOpenInfo->pabyHeader[2] != 'F'
215 414 : || poOpenInfo->pabyHeader[3] != 1 )
216 2508 : return NULL;
217 :
218 : /* -------------------------------------------------------------------- */
219 : /* Try opening the dataset. */
220 : /* -------------------------------------------------------------------- */
221 : int cdfid, nm_id, dim_count, z_id;
222 :
223 412 : if( nc_open( poOpenInfo->pszFilename, NC_NOWRITE, &cdfid ) != NC_NOERR )
224 0 : return NULL;
225 :
226 412 : if( nc_inq_varid( cdfid, "dimension", &nm_id ) != NC_NOERR
227 : || nc_inq_varid( cdfid, "z", &z_id ) != NC_NOERR )
228 : {
229 : #ifdef notdef
230 : CPLError( CE_Warning, CPLE_AppDefined,
231 : "%s is a GMT file, but not in GMT configuration.",
232 : poOpenInfo->pszFilename );
233 : #endif
234 396 : nc_close( cdfid );
235 396 : return NULL;
236 : }
237 :
238 16 : if( nc_inq_ndims( cdfid, &dim_count ) != NC_NOERR || dim_count < 2 )
239 : {
240 0 : nc_close( cdfid );
241 0 : return NULL;
242 : }
243 :
244 : /* -------------------------------------------------------------------- */
245 : /* Confirm the requested access is supported. */
246 : /* -------------------------------------------------------------------- */
247 16 : if( poOpenInfo->eAccess == GA_Update )
248 : {
249 0 : nc_close( cdfid );
250 : CPLError( CE_Failure, CPLE_NotSupported,
251 : "The GMT driver does not support update access to existing"
252 0 : " datasets.\n" );
253 0 : return NULL;
254 : }
255 :
256 : /* -------------------------------------------------------------------- */
257 : /* Create a corresponding GDALDataset. */
258 : /* -------------------------------------------------------------------- */
259 : GMTDataset *poDS;
260 :
261 16 : poDS = new GMTDataset();
262 :
263 16 : poDS->cdfid = cdfid;
264 16 : poDS->z_id = z_id;
265 :
266 : /* -------------------------------------------------------------------- */
267 : /* Get dimensions. If we can't find this, then this is a */
268 : /* GMT file, but not a normal grid product. */
269 : /* -------------------------------------------------------------------- */
270 : size_t start[2], edge[2];
271 : int nm[2];
272 :
273 16 : start[0] = 0;
274 16 : edge[0] = 2;
275 :
276 16 : nc_get_vara_int(cdfid, nm_id, start, edge, nm);
277 :
278 16 : poDS->nRasterXSize = nm[0];
279 16 : poDS->nRasterYSize = nm[1];
280 :
281 : /* -------------------------------------------------------------------- */
282 : /* Fetch "z" attributes scale_factor, add_offset, and */
283 : /* node_offset. */
284 : /* -------------------------------------------------------------------- */
285 16 : double scale_factor=1.0, add_offset=0.0;
286 16 : int node_offset = 1;
287 :
288 16 : nc_get_att_double( cdfid, z_id, "scale_factor", &scale_factor );
289 16 : nc_get_att_double( cdfid, z_id, "add_offset", &add_offset );
290 16 : nc_get_att_int( cdfid, z_id, "node_offset", &node_offset );
291 :
292 : /* -------------------------------------------------------------------- */
293 : /* Get x/y range information. */
294 : /* -------------------------------------------------------------------- */
295 : int x_range_id, y_range_id;
296 :
297 32 : if( nc_inq_varid (cdfid, "x_range", &x_range_id) == NC_NOERR
298 : && nc_inq_varid (cdfid, "y_range", &y_range_id) == NC_NOERR )
299 : {
300 : double x_range[2], y_range[2];
301 :
302 16 : nc_get_vara_double( cdfid, x_range_id, start, edge, x_range );
303 16 : nc_get_vara_double( cdfid, y_range_id, start, edge, y_range );
304 :
305 : // Pixel is area
306 16 : if( node_offset == 1 )
307 : {
308 16 : poDS->adfGeoTransform[0] = x_range[0];
309 : poDS->adfGeoTransform[1] =
310 16 : (x_range[1] - x_range[0]) / poDS->nRasterXSize;
311 16 : poDS->adfGeoTransform[2] = 0.0;
312 16 : poDS->adfGeoTransform[3] = y_range[1];
313 16 : poDS->adfGeoTransform[4] = 0.0;
314 : poDS->adfGeoTransform[5] =
315 16 : (y_range[0] - y_range[1]) / poDS->nRasterYSize;
316 : }
317 :
318 : // Pixel is point - offset by half pixel.
319 : else /* node_offset == 0 */
320 : {
321 : poDS->adfGeoTransform[1] =
322 0 : (x_range[1] - x_range[0]) / (poDS->nRasterXSize-1);
323 : poDS->adfGeoTransform[0] =
324 0 : x_range[0] - poDS->adfGeoTransform[1]*0.5;
325 0 : poDS->adfGeoTransform[2] = 0.0;
326 0 : poDS->adfGeoTransform[4] = 0.0;
327 : poDS->adfGeoTransform[5] =
328 0 : (y_range[0] - y_range[1]) / (poDS->nRasterYSize-1);
329 : poDS->adfGeoTransform[3] =
330 0 : y_range[1] - poDS->adfGeoTransform[5]*0.5;
331 : }
332 : }
333 : else
334 : {
335 0 : poDS->adfGeoTransform[0] = 0.0;
336 0 : poDS->adfGeoTransform[1] = 1.0;
337 0 : poDS->adfGeoTransform[2] = 0.0;
338 0 : poDS->adfGeoTransform[3] = 0.0;
339 0 : poDS->adfGeoTransform[4] = 0.0;
340 0 : poDS->adfGeoTransform[5] = 1.0;
341 : }
342 :
343 : /* -------------------------------------------------------------------- */
344 : /* Create band information objects. */
345 : /* -------------------------------------------------------------------- */
346 16 : poDS->nBands = 1;
347 16 : poDS->SetBand( 1, new GMTRasterBand( poDS, z_id, 1 ));
348 :
349 32 : if( scale_factor != 1.0 || add_offset != 0.0 )
350 : {
351 0 : poDS->GetRasterBand(1)->SetOffset( add_offset );
352 0 : poDS->GetRasterBand(1)->SetScale( scale_factor );
353 : }
354 :
355 : /* -------------------------------------------------------------------- */
356 : /* Initialize any PAM information. */
357 : /* -------------------------------------------------------------------- */
358 16 : poDS->SetDescription( poOpenInfo->pszFilename );
359 16 : poDS->TryLoadXML();
360 :
361 : /* -------------------------------------------------------------------- */
362 : /* Check for external overviews. */
363 : /* -------------------------------------------------------------------- */
364 16 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
365 :
366 16 : return( poDS );
367 : }
368 :
369 : /************************************************************************/
370 : /* GMTCreateCopy() */
371 : /* */
372 : /* This code mostly cribbed from GMT's "gmt_cdf.c" module. */
373 : /************************************************************************/
374 :
375 : static GDALDataset *
376 38 : GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
377 : int bStrict, char ** papszOptions,
378 : GDALProgressFunc pfnProgress, void * pProgressData )
379 :
380 : {
381 : /* -------------------------------------------------------------------- */
382 : /* Figure out general characteristics. */
383 : /* -------------------------------------------------------------------- */
384 : nc_type nc_datatype;
385 : GDALRasterBand *poBand;
386 : int nXSize, nYSize;
387 :
388 38 : if( poSrcDS->GetRasterCount() != 1 )
389 : {
390 : CPLError( CE_Failure, CPLE_AppDefined,
391 10 : "Currently GMT export only supports 1 band datasets." );
392 10 : return NULL;
393 : }
394 :
395 28 : poBand = poSrcDS->GetRasterBand(1);
396 :
397 28 : nXSize = poSrcDS->GetRasterXSize();
398 28 : nYSize = poSrcDS->GetRasterYSize();
399 :
400 28 : if( poBand->GetRasterDataType() == GDT_Int16 )
401 4 : nc_datatype = NC_SHORT;
402 24 : else if( poBand->GetRasterDataType() == GDT_Int32 )
403 2 : nc_datatype = NC_INT;
404 22 : else if( poBand->GetRasterDataType() == GDT_Float32 )
405 2 : nc_datatype = NC_FLOAT;
406 20 : else if( poBand->GetRasterDataType() == GDT_Float64 )
407 2 : nc_datatype = NC_DOUBLE;
408 18 : else if( bStrict )
409 : {
410 : CPLError( CE_Failure, CPLE_AppDefined,
411 : "Band data type %s not supported in GMT, giving up.",
412 16 : GDALGetDataTypeName( poBand->GetRasterDataType() ) );
413 16 : return NULL;
414 : }
415 2 : else if( poBand->GetRasterDataType() == GDT_Byte )
416 2 : nc_datatype = NC_SHORT;
417 0 : else if( poBand->GetRasterDataType() == GDT_UInt16 )
418 0 : nc_datatype = NC_INT;
419 0 : else if( poBand->GetRasterDataType() == GDT_UInt32 )
420 0 : nc_datatype = NC_INT;
421 : else
422 0 : nc_datatype = NC_FLOAT;
423 :
424 : /* -------------------------------------------------------------------- */
425 : /* Establish bounds from geotransform. */
426 : /* -------------------------------------------------------------------- */
427 : double adfGeoTransform[6];
428 : double dfXMax, dfYMin;
429 :
430 12 : poSrcDS->GetGeoTransform( adfGeoTransform );
431 :
432 12 : if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 )
433 : {
434 : CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_AppDefined,
435 0 : "Geotransform has rotational coefficients not supported in GMT." );
436 0 : if( bStrict )
437 0 : return NULL;
438 : }
439 :
440 12 : dfXMax = adfGeoTransform[0] + adfGeoTransform[1] * nXSize;
441 12 : dfYMin = adfGeoTransform[3] + adfGeoTransform[5] * nYSize;
442 :
443 : /* -------------------------------------------------------------------- */
444 : /* Create base file. */
445 : /* -------------------------------------------------------------------- */
446 : int cdfid, err;
447 :
448 12 : err = nc_create (pszFilename, NC_CLOBBER,&cdfid);
449 12 : if( err != NC_NOERR )
450 : {
451 : CPLError( CE_Failure, CPLE_AppDefined,
452 : "nc_create(%s): %s",
453 2 : pszFilename, nc_strerror( err ) );
454 2 : return NULL;
455 : }
456 :
457 : /* -------------------------------------------------------------------- */
458 : /* Define the dimensions and so forth. */
459 : /* -------------------------------------------------------------------- */
460 : int side_dim, xysize_dim, dims[1];
461 : int x_range_id, y_range_id, z_range_id, inc_id, nm_id, z_id;
462 :
463 10 : nc_def_dim(cdfid, "side", 2, &side_dim);
464 10 : nc_def_dim(cdfid, "xysize", (int) (nXSize * nYSize), &xysize_dim);
465 :
466 10 : dims[0] = side_dim;
467 10 : nc_def_var (cdfid, "x_range", NC_DOUBLE, 1, dims, &x_range_id);
468 10 : nc_def_var (cdfid, "y_range", NC_DOUBLE, 1, dims, &y_range_id);
469 10 : nc_def_var (cdfid, "z_range", NC_DOUBLE, 1, dims, &z_range_id);
470 10 : nc_def_var (cdfid, "spacing", NC_DOUBLE, 1, dims, &inc_id);
471 10 : nc_def_var (cdfid, "dimension", NC_LONG, 1, dims, &nm_id);
472 :
473 10 : dims[0] = xysize_dim;
474 10 : nc_def_var (cdfid, "z", nc_datatype, 1, dims, &z_id);
475 :
476 : /* -------------------------------------------------------------------- */
477 : /* Assign attributes. */
478 : /* -------------------------------------------------------------------- */
479 10 : double default_scale = 1.0;
480 10 : double default_offset = 0.0;
481 10 : int default_node_offset = 1; // pixel is area
482 :
483 10 : nc_put_att_text (cdfid, x_range_id, "units", 7, "meters");
484 10 : nc_put_att_text (cdfid, y_range_id, "units", 7, "meters");
485 10 : nc_put_att_text (cdfid, z_range_id, "units", 7, "meters");
486 :
487 : nc_put_att_double (cdfid, z_id, "scale_factor", NC_DOUBLE, 1,
488 10 : &default_scale );
489 : nc_put_att_double (cdfid, z_id, "add_offset", NC_DOUBLE, 1,
490 10 : &default_offset );
491 :
492 : nc_put_att_int (cdfid, z_id, "node_offset", NC_LONG, 1,
493 10 : &default_node_offset );
494 10 : nc_put_att_text (cdfid, NC_GLOBAL, "title", 1, "");
495 10 : nc_put_att_text (cdfid, NC_GLOBAL, "source", 1, "");
496 :
497 : /* leave define mode */
498 10 : nc_enddef (cdfid);
499 :
500 : /* -------------------------------------------------------------------- */
501 : /* Get raster min/max. */
502 : /* -------------------------------------------------------------------- */
503 : double adfMinMax[2];
504 10 : GDALComputeRasterMinMax( (GDALRasterBandH) poBand, FALSE, adfMinMax );
505 :
506 : /* -------------------------------------------------------------------- */
507 : /* Set range variables. */
508 : /* -------------------------------------------------------------------- */
509 : size_t start[2], edge[2];
510 : double dummy[2];
511 : int nm[2];
512 :
513 10 : start[0] = 0;
514 10 : edge[0] = 2;
515 10 : dummy[0] = adfGeoTransform[0];
516 10 : dummy[1] = dfXMax;
517 10 : nc_put_vara_double(cdfid, x_range_id, start, edge, dummy);
518 :
519 10 : dummy[0] = dfYMin;
520 10 : dummy[1] = adfGeoTransform[3];
521 10 : nc_put_vara_double(cdfid, y_range_id, start, edge, dummy);
522 :
523 10 : dummy[0] = adfGeoTransform[1];
524 10 : dummy[1] = -adfGeoTransform[5];
525 10 : nc_put_vara_double(cdfid, inc_id, start, edge, dummy);
526 :
527 10 : nm[0] = nXSize;
528 10 : nm[1] = nYSize;
529 10 : nc_put_vara_int(cdfid, nm_id, start, edge, nm);
530 :
531 10 : nc_put_vara_double(cdfid, z_range_id, start, edge, adfMinMax);
532 :
533 : /* -------------------------------------------------------------------- */
534 : /* Write out the image one scanline at a time. */
535 : /* -------------------------------------------------------------------- */
536 : double *padfData;
537 : int iLine;
538 :
539 10 : padfData = (double *) CPLMalloc( sizeof(double) * nXSize );
540 :
541 10 : edge[0] = nXSize;
542 130 : for( iLine = 0; iLine < nYSize; iLine++ )
543 : {
544 120 : start[0] = iLine * nXSize;
545 : poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
546 120 : padfData, nXSize, 1, GDT_Float64, 0, 0 );
547 120 : err = nc_put_vara_double( cdfid, z_id, start, edge, padfData );
548 120 : if( err != NC_NOERR )
549 : {
550 : CPLError( CE_Failure, CPLE_AppDefined,
551 : "nc_put_vara_double(%s): %s",
552 0 : pszFilename, nc_strerror( err ) );
553 0 : nc_close (cdfid);
554 0 : return( NULL );
555 : }
556 : }
557 :
558 10 : CPLFree( padfData );
559 :
560 : /* -------------------------------------------------------------------- */
561 : /* Close file, and reopen. */
562 : /* -------------------------------------------------------------------- */
563 10 : nc_close (cdfid);
564 :
565 : /* -------------------------------------------------------------------- */
566 : /* Re-open dataset, and copy any auxilary pam information. */
567 : /* -------------------------------------------------------------------- */
568 : GDALPamDataset *poDS = (GDALPamDataset *)
569 10 : GDALOpen( pszFilename, GA_ReadOnly );
570 :
571 10 : if( poDS )
572 10 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
573 :
574 10 : return poDS;
575 : }
576 :
577 : /************************************************************************/
578 : /* GDALRegister_GMT() */
579 : /************************************************************************/
580 :
581 1135 : void GDALRegister_GMT()
582 :
583 : {
584 : GDALDriver *poDriver;
585 :
586 1135 : if (! GDAL_CHECK_VERSION("GMT driver"))
587 0 : return;
588 :
589 1135 : if( GDALGetDriverByName( "GMT" ) == NULL )
590 : {
591 1093 : poDriver = new GDALDriver();
592 :
593 1093 : poDriver->SetDescription( "GMT" );
594 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
595 1093 : "GMT NetCDF Grid Format" );
596 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
597 1093 : "frmt_various.html#GMT" );
598 1093 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nc" );
599 :
600 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
601 1093 : "Int16 Int32 Float32 Float64" );
602 :
603 1093 : poDriver->pfnOpen = GMTDataset::Open;
604 1093 : poDriver->pfnCreateCopy = GMTCreateCopy;
605 :
606 1093 : GetGDALDriverManager()->RegisterDriver( poDriver );
607 : }
608 : }
|