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 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 8 : {
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 90 : int nErr = NC_NOERR;
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 : (long *) pImage );
149 : else
150 : nErr = nc_get_vara_int( cdfid, nZId, start, edge,
151 0 : (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 8 : GMTDataset::~GMTDataset()
182 :
183 : {
184 8 : FlushCache();
185 8 : nc_close (cdfid);
186 8 : }
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 13516 : GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo )
204 :
205 : {
206 : /* -------------------------------------------------------------------- */
207 : /* Does this file have the GMT magic number? */
208 : /* -------------------------------------------------------------------- */
209 13516 : if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 50 )
210 11987 : return NULL;
211 :
212 2167 : if( poOpenInfo->pabyHeader[0] != 'C'
213 220 : || poOpenInfo->pabyHeader[1] != 'D'
214 209 : || poOpenInfo->pabyHeader[2] != 'F'
215 209 : || poOpenInfo->pabyHeader[3] != 1 )
216 1321 : return NULL;
217 :
218 : /* -------------------------------------------------------------------- */
219 : /* Try opening the dataset. */
220 : /* -------------------------------------------------------------------- */
221 : int cdfid, nm_id, dim_count, z_id;
222 :
223 208 : if( nc_open( poOpenInfo->pszFilename, NC_NOWRITE, &cdfid ) != NC_NOERR )
224 0 : return NULL;
225 :
226 208 : 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 200 : nc_close( cdfid );
235 200 : 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 : /* -------------------------------------------------------------------- */
362 : /* Check for external overviews. */
363 : /* -------------------------------------------------------------------- */
364 8 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
365 :
366 8 : 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 19 : 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 19 : if( poSrcDS->GetRasterCount() != 1 )
389 : {
390 : CPLError( CE_Failure, CPLE_AppDefined,
391 5 : "Currently GMT export only supports 1 band datasets." );
392 5 : return NULL;
393 : }
394 :
395 14 : poBand = poSrcDS->GetRasterBand(1);
396 :
397 14 : nXSize = poSrcDS->GetRasterXSize();
398 14 : nYSize = poSrcDS->GetRasterYSize();
399 :
400 14 : if( poBand->GetRasterDataType() == GDT_Int16 )
401 2 : nc_datatype = NC_SHORT;
402 12 : else if( poBand->GetRasterDataType() == GDT_Int32 )
403 1 : nc_datatype = NC_INT;
404 11 : else if( poBand->GetRasterDataType() == GDT_Float32 )
405 1 : nc_datatype = NC_FLOAT;
406 10 : else if( poBand->GetRasterDataType() == GDT_Float64 )
407 1 : nc_datatype = NC_DOUBLE;
408 9 : else if( bStrict )
409 : {
410 : CPLError( CE_Failure, CPLE_AppDefined,
411 : "Band data type %s not supported in GMT, giving up.",
412 8 : GDALGetDataTypeName( poBand->GetRasterDataType() ) );
413 8 : return NULL;
414 : }
415 1 : else if( poBand->GetRasterDataType() == GDT_Byte )
416 1 : 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 6 : poSrcDS->GetGeoTransform( adfGeoTransform );
431 :
432 6 : 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 6 : dfXMax = adfGeoTransform[0] + adfGeoTransform[1] * nXSize;
441 6 : dfYMin = adfGeoTransform[3] + adfGeoTransform[5] * nYSize;
442 :
443 : /* -------------------------------------------------------------------- */
444 : /* Create base file. */
445 : /* -------------------------------------------------------------------- */
446 : int cdfid, err;
447 :
448 6 : err = nc_create (pszFilename, NC_CLOBBER,&cdfid);
449 6 : if( err != NC_NOERR )
450 : {
451 : CPLError( CE_Failure, CPLE_AppDefined,
452 : "nc_create(%s): %s",
453 1 : pszFilename, nc_strerror( err ) );
454 1 : 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 5 : nc_def_dim(cdfid, "side", 2, &side_dim);
464 5 : nc_def_dim(cdfid, "xysize", (int) (nXSize * nYSize), &xysize_dim);
465 :
466 5 : dims[0] = side_dim;
467 5 : nc_def_var (cdfid, "x_range", NC_DOUBLE, 1, dims, &x_range_id);
468 5 : nc_def_var (cdfid, "y_range", NC_DOUBLE, 1, dims, &y_range_id);
469 5 : nc_def_var (cdfid, "z_range", NC_DOUBLE, 1, dims, &z_range_id);
470 5 : nc_def_var (cdfid, "spacing", NC_DOUBLE, 1, dims, &inc_id);
471 5 : nc_def_var (cdfid, "dimension", NC_LONG, 1, dims, &nm_id);
472 :
473 5 : dims[0] = xysize_dim;
474 5 : nc_def_var (cdfid, "z", nc_datatype, 1, dims, &z_id);
475 :
476 : /* -------------------------------------------------------------------- */
477 : /* Assign attributes. */
478 : /* -------------------------------------------------------------------- */
479 5 : double default_scale = 1.0;
480 5 : double default_offset = 0.0;
481 5 : int default_node_offset = 1; // pixel is area
482 :
483 5 : nc_put_att_text (cdfid, x_range_id, "units", 7, "meters");
484 5 : nc_put_att_text (cdfid, y_range_id, "units", 7, "meters");
485 5 : 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 5 : &default_scale );
489 : nc_put_att_double (cdfid, z_id, "add_offset", NC_DOUBLE, 1,
490 5 : &default_offset );
491 :
492 : nc_put_att_int (cdfid, z_id, "node_offset", NC_LONG, 1,
493 5 : &default_node_offset );
494 5 : nc_put_att_text (cdfid, NC_GLOBAL, "title", 1, "");
495 5 : nc_put_att_text (cdfid, NC_GLOBAL, "source", 1, "");
496 :
497 : /* leave define mode */
498 5 : nc_enddef (cdfid);
499 :
500 : /* -------------------------------------------------------------------- */
501 : /* Get raster min/max. */
502 : /* -------------------------------------------------------------------- */
503 : double adfMinMax[2];
504 5 : 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 5 : start[0] = 0;
514 5 : edge[0] = 2;
515 5 : dummy[0] = adfGeoTransform[0];
516 5 : dummy[1] = dfXMax;
517 5 : nc_put_vara_double(cdfid, x_range_id, start, edge, dummy);
518 :
519 5 : dummy[0] = dfYMin;
520 5 : dummy[1] = adfGeoTransform[3];
521 5 : nc_put_vara_double(cdfid, y_range_id, start, edge, dummy);
522 :
523 5 : dummy[0] = adfGeoTransform[1];
524 5 : dummy[1] = -adfGeoTransform[5];
525 5 : nc_put_vara_double(cdfid, inc_id, start, edge, dummy);
526 :
527 5 : nm[0] = nXSize;
528 5 : nm[1] = nYSize;
529 5 : nc_put_vara_int(cdfid, nm_id, start, edge, nm);
530 :
531 5 : 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 5 : padfData = (double *) CPLMalloc( sizeof(double) * nXSize );
540 :
541 5 : edge[0] = nXSize;
542 65 : for( iLine = 0; iLine < nYSize; iLine++ )
543 : {
544 60 : start[0] = iLine * nXSize;
545 : poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
546 60 : padfData, nXSize, 1, GDT_Float64, 0, 0 );
547 60 : err = nc_put_vara_double( cdfid, z_id, start, edge, padfData );
548 60 : 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 5 : CPLFree( padfData );
559 :
560 : /* -------------------------------------------------------------------- */
561 : /* Close file, and reopen. */
562 : /* -------------------------------------------------------------------- */
563 5 : nc_close (cdfid);
564 :
565 : /* -------------------------------------------------------------------- */
566 : /* Re-open dataset, and copy any auxilary pam information. */
567 : /* -------------------------------------------------------------------- */
568 : GDALPamDataset *poDS = (GDALPamDataset *)
569 5 : GDALOpen( pszFilename, GA_ReadOnly );
570 :
571 5 : if( poDS )
572 5 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
573 :
574 5 : return poDS;
575 : }
576 :
577 : /************************************************************************/
578 : /* GDALRegister_GMT() */
579 : /************************************************************************/
580 :
581 582 : void GDALRegister_GMT()
582 :
583 : {
584 : GDALDriver *poDriver;
585 :
586 582 : if (! GDAL_CHECK_VERSION("GMT driver"))
587 0 : return;
588 :
589 582 : if( GDALGetDriverByName( "GMT" ) == NULL )
590 : {
591 561 : poDriver = new GDALDriver();
592 :
593 561 : poDriver->SetDescription( "GMT" );
594 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
595 561 : "GMT NetCDF Grid Format" );
596 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
597 561 : "frmt_various.html#GMT" );
598 561 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "nc" );
599 :
600 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
601 561 : "Int16 Int32 Float32 Float64" );
602 :
603 561 : poDriver->pfnOpen = GMTDataset::Open;
604 561 : poDriver->pfnCreateCopy = GMTCreateCopy;
605 :
606 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
607 : }
608 : }
|