1 : /******************************************************************************
2 : * $Id: gmtdataset.cpp 17664 2009-09-21 21:16:45Z 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 17664 2009-09-21 21:16:45Z rouault $");
35 :
36 : /************************************************************************/
37 : /* ==================================================================== */
38 : /* GMTDataset */
39 : /* ==================================================================== */
40 : /************************************************************************/
41 :
42 : class GMTRasterBand;
43 :
44 : class GMTDataset : public GDALPamDataset
45 8 : {
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 8 : GMTRasterBand::GMTRasterBand( GMTDataset *poDS, int nZId, int nBand )
83 :
84 : {
85 8 : this->poDS = poDS;
86 8 : this->nBand = nBand;
87 8 : this->nZId = nZId;
88 :
89 8 : nBlockXSize = poDS->GetRasterXSize();
90 8 : nBlockYSize = 1;
91 :
92 : /* -------------------------------------------------------------------- */
93 : /* Get the type of the "z" variable, our target raster array. */
94 : /* -------------------------------------------------------------------- */
95 8 : 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 8 : if( nc_datatype == NC_BYTE )
104 0 : eDataType = GDT_Byte;
105 8 : else if( nc_datatype == NC_SHORT )
106 4 : eDataType = GDT_Int16;
107 4 : else if( nc_datatype == NC_INT )
108 1 : eDataType = GDT_Int32;
109 3 : else if( nc_datatype == NC_FLOAT )
110 2 : eDataType = GDT_Float32;
111 1 : else if( nc_datatype == NC_DOUBLE )
112 1 : 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 90 : CPLErr GMTRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
128 : void * pImage )
129 :
130 : {
131 : size_t start[2], edge[2];
132 : int nErr;
133 90 : int cdfid = ((GMTDataset *) poDS)->cdfid;
134 :
135 90 : start[0] = nBlockYOff * nBlockXSize;
136 90 : edge[0] = nBlockXSize;
137 :
138 90 : if( eDataType == GDT_Byte )
139 : nErr = nc_get_vara_uchar( cdfid, nZId, start, edge,
140 0 : (unsigned char *) pImage );
141 90 : else if( eDataType == GDT_Int16 )
142 : nErr = nc_get_vara_short( cdfid, nZId, start, edge,
143 40 : (short int *) pImage );
144 50 : else if( eDataType == GDT_Int32 )
145 : {
146 : if( sizeof(long) == 4 )
147 : nErr = nc_get_vara_long( cdfid, nZId, start, edge,
148 0 : (long *) pImage );
149 : else
150 : nErr = nc_get_vara_int( cdfid, nZId, start, edge,
151 : (int *) pImage );
152 : }
153 50 : else if( eDataType == GDT_Float32 )
154 : nErr = nc_get_vara_float( cdfid, nZId, start, edge,
155 50 : (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 90 : 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 90 : return CE_None;
169 : }
170 :
171 : /************************************************************************/
172 : /* ==================================================================== */
173 : /* GMTDataset */
174 : /* ==================================================================== */
175 : /************************************************************************/
176 :
177 : /************************************************************************/
178 : /* ~GMTDataset() */
179 : /************************************************************************/
180 :
181 16 : GMTDataset::~GMTDataset()
182 :
183 : {
184 8 : FlushCache();
185 8 : nc_close (cdfid);
186 16 : }
187 :
188 : /************************************************************************/
189 : /* GetGeoTransform() */
190 : /************************************************************************/
191 :
192 7 : CPLErr GMTDataset::GetGeoTransform( double * padfTransform )
193 :
194 : {
195 7 : memcpy( padfTransform, adfGeoTransform, sizeof(double) * 6 );
196 7 : return CE_None;
197 : }
198 :
199 : /************************************************************************/
200 : /* Open() */
201 : /************************************************************************/
202 :
203 9504 : GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
204 :
205 : {
206 : /* -------------------------------------------------------------------- */
207 : /* Does this file have the GMT magic number? */
208 : /* -------------------------------------------------------------------- */
209 9504 : if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 50 )
210 8702 : return NULL;
211 :
212 883 : if( poOpenInfo->pabyHeader[0] != 'C'
213 29 : || poOpenInfo->pabyHeader[1] != 'D'
214 26 : || poOpenInfo->pabyHeader[2] != 'F'
215 26 : || poOpenInfo->pabyHeader[3] != 1 )
216 776 : return NULL;
217 :
218 : /* -------------------------------------------------------------------- */
219 : /* Try opening the dataset. */
220 : /* -------------------------------------------------------------------- */
221 : int cdfid, nm_id, dim_count, z_id;
222 :
223 26 : if( nc_open( poOpenInfo->pszFilename, NC_NOWRITE, &cdfid ) != NC_NOERR )
224 0 : return NULL;
225 :
226 26 : 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 18 : nc_close( cdfid );
235 18 : return NULL;
236 : }
237 :
238 8 : 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 8 : 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 8 : poDS = new GMTDataset();
262 :
263 8 : poDS->cdfid = cdfid;
264 8 : 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 8 : start[0] = 0;
274 8 : edge[0] = 2;
275 :
276 8 : nc_get_vara_int(cdfid, nm_id, start, edge, nm);
277 :
278 8 : poDS->nRasterXSize = nm[0];
279 8 : poDS->nRasterYSize = nm[1];
280 :
281 : /* -------------------------------------------------------------------- */
282 : /* Fetch "z" attributes scale_factor, add_offset, and */
283 : /* node_offset. */
284 : /* -------------------------------------------------------------------- */
285 8 : double scale_factor=1.0, add_offset=0.0;
286 8 : int node_offset = 1;
287 :
288 8 : nc_get_att_double( cdfid, z_id, "scale_factor", &scale_factor );
289 8 : nc_get_att_double( cdfid, z_id, "add_offset", &add_offset );
290 8 : 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 16 : 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 8 : nc_get_vara_double( cdfid, x_range_id, start, edge, x_range );
303 8 : nc_get_vara_double( cdfid, y_range_id, start, edge, y_range );
304 :
305 : // Pixel is area
306 8 : if( node_offset == 1 )
307 : {
308 8 : poDS->adfGeoTransform[0] = x_range[0];
309 : poDS->adfGeoTransform[1] =
310 8 : (x_range[1] - x_range[0]) / poDS->nRasterXSize;
311 8 : poDS->adfGeoTransform[2] = 0.0;
312 8 : poDS->adfGeoTransform[3] = y_range[1];
313 8 : poDS->adfGeoTransform[4] = 0.0;
314 : poDS->adfGeoTransform[5] =
315 8 : (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 8 : poDS->nBands = 1;
347 8 : poDS->SetBand( 1, new GMTRasterBand( poDS, z_id, 1 ));
348 :
349 16 : 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 8 : poDS->SetDescription( poOpenInfo->pszFilename );
359 8 : poDS->TryLoadXML();
360 :
361 8 : return( poDS );
362 : }
363 :
364 : /************************************************************************/
365 : /* GMTCreateCopy() */
366 : /* */
367 : /* This code mostly cribbed from GMT's "gmt_cdf.c" module. */
368 : /************************************************************************/
369 :
370 : static GDALDataset *
371 17 : GMTCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
372 : int bStrict, char ** papszOptions,
373 : GDALProgressFunc pfnProgress, void * pProgressData )
374 :
375 : {
376 : /* -------------------------------------------------------------------- */
377 : /* Figure out general characteristics. */
378 : /* -------------------------------------------------------------------- */
379 : nc_type nc_datatype;
380 : GDALRasterBand *poBand;
381 : int nXSize, nYSize;
382 :
383 17 : if( poSrcDS->GetRasterCount() != 1 )
384 : {
385 : CPLError( CE_Failure, CPLE_AppDefined,
386 5 : "Currently GMT export only supports 1 band datasets." );
387 5 : return NULL;
388 : }
389 :
390 12 : poBand = poSrcDS->GetRasterBand(1);
391 :
392 12 : nXSize = poSrcDS->GetRasterXSize();
393 12 : nYSize = poSrcDS->GetRasterYSize();
394 :
395 12 : if( poBand->GetRasterDataType() == GDT_Int16 )
396 2 : nc_datatype = NC_SHORT;
397 10 : else if( poBand->GetRasterDataType() == GDT_Int32 )
398 1 : nc_datatype = NC_INT;
399 9 : else if( poBand->GetRasterDataType() == GDT_Float32 )
400 1 : nc_datatype = NC_FLOAT;
401 8 : else if( poBand->GetRasterDataType() == GDT_Float64 )
402 1 : nc_datatype = NC_DOUBLE;
403 7 : else if( bStrict )
404 : {
405 : CPLError( CE_Failure, CPLE_AppDefined,
406 : "Band data type %s not supported in GMT, giving up.",
407 7 : GDALGetDataTypeName( poBand->GetRasterDataType() ) );
408 7 : return NULL;
409 : }
410 0 : else if( poBand->GetRasterDataType() == GDT_Byte )
411 0 : nc_datatype = NC_SHORT;
412 0 : else if( poBand->GetRasterDataType() == GDT_UInt16 )
413 0 : nc_datatype = NC_INT;
414 0 : else if( poBand->GetRasterDataType() == GDT_UInt32 )
415 0 : nc_datatype = NC_INT;
416 : else
417 0 : nc_datatype = NC_FLOAT;
418 :
419 : /* -------------------------------------------------------------------- */
420 : /* Establish bounds from geotransform. */
421 : /* -------------------------------------------------------------------- */
422 : double adfGeoTransform[6];
423 : double dfXMax, dfYMin;
424 :
425 5 : poSrcDS->GetGeoTransform( adfGeoTransform );
426 :
427 5 : if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 )
428 : {
429 : CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_AppDefined,
430 0 : "Geotransform has rotational coefficients not supported in GMT." );
431 0 : if( bStrict )
432 0 : return NULL;
433 : }
434 :
435 5 : dfXMax = adfGeoTransform[0] + adfGeoTransform[1] * nXSize;
436 5 : dfYMin = adfGeoTransform[3] + adfGeoTransform[5] * nYSize;
437 :
438 : /* -------------------------------------------------------------------- */
439 : /* Create base file. */
440 : /* -------------------------------------------------------------------- */
441 : int cdfid, err;
442 :
443 5 : err = nc_create (pszFilename, NC_CLOBBER,&cdfid);
444 5 : if( err != NC_NOERR )
445 : {
446 : CPLError( CE_Failure, CPLE_AppDefined,
447 : "nc_create(%s): %s",
448 0 : pszFilename, nc_strerror( err ) );
449 0 : return NULL;
450 : }
451 :
452 : /* -------------------------------------------------------------------- */
453 : /* Define the dimensions and so forth. */
454 : /* -------------------------------------------------------------------- */
455 : int side_dim, xysize_dim, dims[1];
456 : int x_range_id, y_range_id, z_range_id, inc_id, nm_id, z_id;
457 :
458 5 : nc_def_dim(cdfid, "side", 2, &side_dim);
459 5 : nc_def_dim(cdfid, "xysize", (int) (nXSize * nYSize), &xysize_dim);
460 :
461 5 : dims[0] = side_dim;
462 5 : nc_def_var (cdfid, "x_range", NC_DOUBLE, 1, dims, &x_range_id);
463 5 : nc_def_var (cdfid, "y_range", NC_DOUBLE, 1, dims, &y_range_id);
464 5 : nc_def_var (cdfid, "z_range", NC_DOUBLE, 1, dims, &z_range_id);
465 5 : nc_def_var (cdfid, "spacing", NC_DOUBLE, 1, dims, &inc_id);
466 5 : nc_def_var (cdfid, "dimension", NC_LONG, 1, dims, &nm_id);
467 :
468 5 : dims[0] = xysize_dim;
469 5 : nc_def_var (cdfid, "z", nc_datatype, 1, dims, &z_id);
470 :
471 : /* -------------------------------------------------------------------- */
472 : /* Assign attributes. */
473 : /* -------------------------------------------------------------------- */
474 5 : double default_scale = 1.0;
475 5 : double default_offset = 0.0;
476 5 : int default_node_offset = 1; // pixel is area
477 :
478 5 : nc_put_att_text (cdfid, x_range_id, "units", 7, "meters");
479 5 : nc_put_att_text (cdfid, y_range_id, "units", 7, "meters");
480 5 : nc_put_att_text (cdfid, z_range_id, "units", 7, "meters");
481 :
482 : nc_put_att_double (cdfid, z_id, "scale_factor", NC_DOUBLE, 1,
483 5 : &default_scale );
484 : nc_put_att_double (cdfid, z_id, "add_offset", NC_DOUBLE, 1,
485 5 : &default_offset );
486 :
487 : nc_put_att_int (cdfid, z_id, "node_offset", NC_LONG, 1,
488 5 : &default_node_offset );
489 5 : nc_put_att_text (cdfid, NC_GLOBAL, "title", 1, "");
490 5 : nc_put_att_text (cdfid, NC_GLOBAL, "source", 1, "");
491 :
492 : /* leave define mode */
493 5 : nc_enddef (cdfid);
494 :
495 : /* -------------------------------------------------------------------- */
496 : /* Get raster min/max. */
497 : /* -------------------------------------------------------------------- */
498 : double adfMinMax[2];
499 5 : GDALComputeRasterMinMax( (GDALRasterBandH) poBand, FALSE, adfMinMax );
500 :
501 : /* -------------------------------------------------------------------- */
502 : /* Set range variables. */
503 : /* -------------------------------------------------------------------- */
504 : size_t start[2], edge[2];
505 : double dummy[2];
506 : int nm[2];
507 :
508 5 : start[0] = 0;
509 5 : edge[0] = 2;
510 5 : dummy[0] = adfGeoTransform[0];
511 5 : dummy[1] = dfXMax;
512 5 : nc_put_vara_double(cdfid, x_range_id, start, edge, dummy);
513 :
514 5 : dummy[0] = dfYMin;
515 5 : dummy[1] = adfGeoTransform[3];
516 5 : nc_put_vara_double(cdfid, y_range_id, start, edge, dummy);
517 :
518 5 : dummy[0] = adfGeoTransform[1];
519 5 : dummy[1] = -adfGeoTransform[5];
520 5 : nc_put_vara_double(cdfid, inc_id, start, edge, dummy);
521 :
522 5 : nm[0] = nXSize;
523 5 : nm[1] = nYSize;
524 5 : nc_put_vara_int(cdfid, nm_id, start, edge, nm);
525 :
526 5 : nc_put_vara_double(cdfid, z_range_id, start, edge, adfMinMax);
527 :
528 : /* -------------------------------------------------------------------- */
529 : /* Write out the image one scanline at a time. */
530 : /* -------------------------------------------------------------------- */
531 : double *padfData;
532 : int iLine;
533 :
534 5 : padfData = (double *) CPLMalloc( sizeof(double) * nXSize );
535 :
536 5 : edge[0] = nXSize;
537 65 : for( iLine = 0; iLine < nYSize; iLine++ )
538 : {
539 60 : start[0] = iLine * nXSize;
540 : poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
541 60 : padfData, nXSize, 1, GDT_Float64, 0, 0 );
542 60 : err = nc_put_vara_double( cdfid, z_id, start, edge, padfData );
543 60 : if( err != NC_NOERR )
544 : {
545 : CPLError( CE_Failure, CPLE_AppDefined,
546 : "nc_put_vara_double(%s): %s",
547 0 : pszFilename, nc_strerror( err ) );
548 0 : nc_close (cdfid);
549 0 : return( NULL );
550 : }
551 : }
552 :
553 5 : CPLFree( padfData );
554 :
555 : /* -------------------------------------------------------------------- */
556 : /* Close file, and reopen. */
557 : /* -------------------------------------------------------------------- */
558 5 : nc_close (cdfid);
559 :
560 : /* -------------------------------------------------------------------- */
561 : /* Re-open dataset, and copy any auxilary pam information. */
562 : /* -------------------------------------------------------------------- */
563 : GDALPamDataset *poDS = (GDALPamDataset *)
564 5 : GDALOpen( pszFilename, GA_ReadOnly );
565 :
566 5 : if( poDS )
567 5 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
568 :
569 5 : return poDS;
570 : }
571 :
572 : /************************************************************************/
573 : /* GDALRegister_GMT() */
574 : /************************************************************************/
575 :
576 338 : void GDALRegister_GMT()
577 :
578 : {
579 : GDALDriver *poDriver;
580 :
581 338 : if (! GDAL_CHECK_VERSION("GMT driver"))
582 0 : return;
583 :
584 338 : if( GDALGetDriverByName( "GMT" ) == NULL )
585 : {
586 336 : poDriver = new GDALDriver();
587 :
588 336 : poDriver->SetDescription( "GMT" );
589 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
590 336 : "GMT NetCDF Grid Format" );
591 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
592 336 : "frmt_various.html#GMT" );
593 336 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nc" );
594 :
595 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
596 336 : "Int16 Int32 Float32 Float64" );
597 :
598 336 : poDriver->pfnOpen = GMTDataset::Open;
599 336 : poDriver->pfnCreateCopy = GMTCreateCopy;
600 :
601 336 : GetGDALDriverManager()->RegisterDriver( poDriver );
602 : }
603 : }
|