root/tags/gdal_1_2_3/gcore/gdal_tutorial.dox

Revision 5964, 19.4 kB (checked in by warmerda, 5 years ago)

Fixed a couple of typoes care of Jerry Black.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*!
2 \page gdal_tutorial
3
4 <center>
5 <title>GDAL API Tutorial</title>
6 </center>
7
8 <h2>Opening the File</h2>
9
10
11
12 Before opening a GDAL supported raster datastore it is necessary to
13 register drivers.  There is a driver for each supported format.  Normally
14 this is accomplished with the GDALAllRegister() function which attempts
15 to register all known drivers, including those auto-loaded from .so files
16 using GDALDriverManager::AutoLoadDrivers().  If for some applications it
17 is necessary to limit the set of drivers it may be helpful to review
18 the code from <a href="gdalallregister.cpp.html">gdalallregister.cpp</a>.
19
20 Once the drivers are registered, the application should call the free
21 standing GDALOpen() function to open a dataset, passing the name of the
22 dataset and the access desired (GA_ReadOnly or GA_Update).
23
24 In C++:
25 \code
26 #include "gdal_priv.h"
27
28 int main()
29 {
30     GDALDataset  *poDataset;
31
32     GDALAllRegister();
33
34     poDataset = (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
35     if( poDataset == NULL )
36     {
37         ...;
38     }
39 \endcode
40
41 In C:
42 \code
43 #include "gdal.h"
44
45 int main()
46 {
47     GDALDatasetH  hDataset;
48
49     GDALAllRegister();
50
51     hDataset = GDALOpen( pszFilename, GA_ReadOnly );
52     if( hDataset == NULL )
53     {
54         ...;
55     }
56 \endcode
57
58 In Python:
59 \code
60     import gdal
61     from gdalconst import *
62
63     dataset = gdal.Open( filename, GA_ReadOnly )
64     if dataset is None:
65         ...
66 \endcode
67
68 Note that if GDALOpen() returns NULL it means the open failed, and that
69 an error messages will already have been emitted via CPLError().  If you want
70 to control how errors are reported to the user review the CPLError()
71 documentation.  Generally speaking all of GDAL uses CPLError() for error
72 reporting.  Also, note that pszFilename need not actually be the name
73 of a physical file (though it usually is).  It's interpretation is driver
74 dependent, and it might be an URL, a filename with additional parameters
75 added at the end controlling the open or almost anything.  Please try not
76 to limit GDAL file selection dialogs to only selecting physical files.
77
78 <h2>Getting Dataset Information</h2>
79
80 As described in the <a href="gdal_datamodel.html">GDAL Data Model</a>, a
81 GDALDataset contains a list of raster bands, all pertaining to the same
82 area, and having the same resolution.  It also has metadata, a coordinate
83 system, a georeferencing transform, size of raster and various other
84 information. 
85
86 \code
87     adfGeoTransform[0] /* top left x */
88     adfGeoTransform[1] /* w-e pixel resolution */
89     adfGeoTransform[2] /* rotation, 0 if image is "north up" */
90     adfGeoTransform[3] /* top left y */
91     adfGeoTransform[4] /* rotation, 0 if image is "north up" */
92     adfGeoTransform[5] /* n-s pixel resolution */
93 \endcode
94
95 If we wanted to print some general information about the
96 dataset we might do the following:
97
98 In C++:
99 \code
100     double        adfGeoTransform[6];
101
102     printf( "Driver: %s/%s\n",
103             poDataset->GetDriver()->GetDescription(),
104             poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) );
105
106     printf( "Size is %dx%dx%d\n",
107             poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
108             poDataset->GetRasterCount() );
109
110     if( poDataset->GetProjectionRef()  != NULL )
111         printf( "Projection is `%s'\n", poDataset->GetProjectionRef() );
112
113     if( poDataset->GetGeoTransform( adfGeoTransform ) == CE_None )
114     {
115         printf( "Origin = (%.6f,%.6f)\n",
116                 adfGeoTransform[0], adfGeoTransform[3] );
117
118         printf( "Pixel Size = (%.6f,%.6f)\n",
119                 adfGeoTransform[1], adfGeoTransform[5] );
120     }
121 \endcode
122
123 In C:
124 \code
125     GDALDriverH   hDriver;
126     double        adfGeoTransform[6];
127
128     hDriver = GDALGetDatasetDriver( hDataset );
129     printf( "Driver: %s/%s\n",
130             GDALGetDriverShortName( hDriver ),
131             GDALGetDriverLongName( hDriver ) );
132
133     printf( "Size is %dx%dx%d\n",
134             GDALGetRasterXSize( hDataset ),
135             GDALGetRasterYSize( hDataset ),
136             GDALGetRasterCount( hDataset ) );
137
138     if( GDALGetProjectionRef( hDataset ) != NULL )
139         printf( "Projection is `%s'\n", GDALGetProjectionRef( hDataset ) );
140
141     if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
142     {
143         printf( "Origin = (%.6f,%.6f)\n",
144                 adfGeoTransform[0], adfGeoTransform[3] );
145
146         printf( "Pixel Size = (%.6f,%.6f)\n",
147                 adfGeoTransform[1], adfGeoTransform[5] );
148     }
149 \endcode
150
151 In Python (note, driver bindings are not currently available):
152 \code
153     print 'Size is ',dataset.RasterXSize,'x',dataset.RasterYSize, \
154           'x',dataset.RasterCount
155     print 'Projection is ',dataset.GetProjection()
156    
157     geotransform = dataset.GetGeoTransform()
158     if not geotransform is None:
159         print 'Origin = (',geotransform[0], ',',geotransform[3],')'
160         print 'Pixel Size = (',geotransform[1], ',',geotransform[5],')'
161 \endcode
162
163 <h2>Fetching a Raster Band</h2>
164
165 At this time access to raster data via GDAL is done one band at a time.
166 Also, there is metadata, blocksizes, color tables, and various other
167 information available on a band by band basis.  The following codes fetches
168 a GDALRasterBand object from the dataset (numbered 1 through GetRasterCount())
169 and displays a little information about it.
170
171 In C++:
172 \code
173         GDALRasterBand  *poBand;
174         int             nBlockXSize, nBlockYSize;
175         int             bGotMin, bGotMax;
176         double          adfMinMax[2];
177        
178         poBand = poDataset->GetRasterBand( 1 );
179         poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
180         printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
181                 nBlockXSize, nBlockYSize,
182                 GDALGetDataTypeName(poBand->GetRasterDataType()),
183                 GDALGetColorInterpretationName(
184                     poBand->GetColorInterpretation()) );
185
186         adfMinMax[0] = poBand->GetMinimum( &bGotMin );
187         adfMinMax[1] = poBand->GetMaximum( &bGotMax );
188         if( ! (bGotMin && bGotMax) )
189             GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);
190
191         printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
192        
193         if( poBand->GetOverviewCount() > 0 )
194             printf( "Band has %d overviews.\n", poBand->GetOverviewCount() );
195
196         if( poBand->GetColorTable() != NULL )
197             printf( "Band has a color table with %d entries.\n",
198                      poBand->GetColorTable()->GetColorEntryCount() );
199 \endcode
200
201 In C:
202 \code
203         GDALRasterBandH hBand;
204         int             nBlockXSize, nBlockYSize;
205         int             bGotMin, bGotMax;
206         double          adfMinMax[2];
207        
208         hBand = GDALGetRasterBand( hDataset, 1 );
209         GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
210         printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
211                 nBlockXSize, nBlockYSize,
212                 GDALGetDataTypeName(GDALGetRasterDataType(hBand)),
213                 GDALGetColorInterpretationName(
214                     GDALGetRasterColorInterpretation(hBand)) );
215
216         adfMinMax[0] = GDALGetRasterMinimum( hBand, &bGotMin );
217         adfMinMax[1] = GDALGetRasterMaximum( hBand, &bGotMax );
218         if( ! (bGotMin && bGotMax) )
219             GDALComputeRasterMinMax( hBand, TRUE, adfMinMax );
220
221         printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
222        
223         if( GDALGetOverviewCount(hBand) > 0 )
224             printf( "Band has %d overviews.\n", GDALGetOverviewCount(hBand));
225
226         if( GDALGetRasterColorTable( hBand ) != NULL )
227             printf( "Band has a color table with %d entries.\n",
228                      GDALGetColorEntryCount(
229                          GDALGetRasterColorTable( hBand ) ) );
230 \endcode
231
232 In Python (note several bindings are missing):
233 \code
234         band = dataset.GetRasterBand(1)
235
236         print 'Band Type=',gdal.GetDataTypeName(band.DataType)
237
238         if not band.GetRasterColorTable() is None:
239             print 'Band has a color table.'
240 \endcode
241
242 <h2>Reading Raster Data</h2>
243
244 There are a few ways to read raster data, but the most common is via
245 the GDALRasterBand::RasterIO() method.  This method will automatically take
246 care of data type conversion, up/down sampling and windowing.  The following
247 code will read the first scanline of data into a similarly sized buffer,
248 converting it to floating point as part of the operation.
249
250 In C++:
251 \code
252         float *pafScanline;
253         int   nXSize = poBand->GetXSize();
254
255         pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
256         poBand->RasterIO( GF_Read, 0, 0, nXSize, 1,
257                           pafScanline, nXSize, 1, GDT_Float32,
258                           0, 0 );
259 \endcode
260
261 In C:
262 \code
263         float *pafScanline;
264         int   nXSize = GDALGetRasterBandXSize( hBand );
265
266         pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
267         GDALRasterIO( hBand, GF_Read, 0, 0, nXSize, 1,
268                       pafScanline, nXSize, 1, GDT_Float32,
269                       0, 0 );
270 \endcode
271
272 In Python (note that the returned scanline is of type string, and contains
273 xsize*4 bytes of raw binary floating point data):
274
275 \code
276         scanline = band.ReadRaster( 0, 0, band.XSize, 1, \
277                                     band.XSize, 1, GDT_Float32 )
278 \endcode
279
280 The RasterIO call takes the following arguments.
281 \code
282 CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
283                                  int nXOff, int nYOff, int nXSize, int nYSize,
284                                  void * pData, int nBufXSize, int nBufYSize,
285                                  GDALDataType eBufType,
286                                  int nPixelSpace,
287                                  int nLineSpace )
288 \endcode
289
290 Note that the same RasterIO() call is used to read, or write based on
291 the setting of eRWFlag (either GF_Read or GF_Write).  The nXOff, nYOff,
292 nXSize, nYSize argument describe the window of raster data on disk to
293 read (or write).  It doesn't have to fall on tile boundaries though access
294 may be more efficient if it does. 
295
296 The pData is the memory buffer the data is read into, or written from.  It's
297 real type must be whatever is passed as eBufType, such as GDT_Float32, or
298 GDT_Byte.  The RasterIO() call will take care of converting between the
299 buffer's data type and the data type of the band.  Note that when converting
300 floating point data to integer RasterIO() rounds down, and when converting
301 source values outside the legal range of the output the nearest legal value
302 is used.  This implies, for instance, that 16bit data read into a GDT_Byte
303 buffer will map all values greater than 255 to 255, <b>the data is not
304 scaled!</b>
305
306 The nBufXSize and nBufYSize
307 values describe the size of the buffer.  When loading data at full resolution
308 this would be the same as the window size.  However, to load a reduced
309 resolution overview this could be set to smaller than the window on disk.  In
310 this case the RasterIO() will utilize overviews to do the IO more efficiently
311 if the overviews are suitable.
312
313 The nPixelSpace, and nLineSpace are normally zero indicating that default
314 values should be used.  However, they can be used to control access to
315 the memory data buffer, allowing reading into a buffer containing other
316 pixel interleaved data for instance. 
317
318 <h2>Closing the Dataset</h2>
319
320 Please keep in mind that GDALRasterBand objects are <i>owned</i> by their
321 dataset, and they should never be destroyed with the C++ delete operator.
322 GDALDataset's can be closed either by calling GDALClose() or using the
323 delete operator on the GDALDataset.   Either will result in proper cleanup,
324 and flushing of any pending writes. 
325
326 <h2>Techniques for Creating Files</h2>
327
328 New files in GDAL supported formats may be created if the format driver
329 supports creation.  There are two general techniques for creating files,
330 using CreateCopy() and Create().
331 The CreateCopy method involves calling the CreateCopy() method on the
332 format driver, and passing in a source dataset that should be copied.  The
333 Create method involves calling the Create() method on the driver, and then
334 explicitly writing all the metadata, and raster data with separate calls.
335 All drivers that support creating new files support the CreateCopy() method,
336 but only a few support the Create() method.
337
338 To determine if a particular format supports Create or CreateCopy
339 it is possible to check the DCAP_CREATE  and DCAP_CREATECOPY metadata on the
340 format driver object.  Ensure that GDALAllRegister() has been called before
341 calling GetDriverByName().  In this example we
342
343 In C++:
344 \code
345     const char *pszFormat = "GTiff";
346     GDALDriver *poDriver;
347     char **papszMetadata;
348
349     poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
350
351     if( poDriver == NULL )
352         exit( 1 );
353
354     papszMetadata = poDriver->GetMetadata();
355     if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) )
356         printf( "Driver %s supports Create() method.\n" );
357     if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
358         printf( "Driver %s supports CreateCopy() method.\n" );
359 \endcode
360
361 In C:
362 \code
363     const char *pszFormat = "GTiff";
364     GDALDriver hDriver = GDALGetDriverByName( pszFormat );
365     char **papszMetadata;
366
367     if( hDriver == NULL )
368         exit( 1 );
369
370     papszMetadata = GDALGetMetadata( hDriver, NULL );
371     if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) )
372         printf( "Driver %s supports Create() method.\n" );
373     if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
374         printf( "Driver %s supports CreateCopy() method.\n" );
375 \endcode
376
377 In Python:
378
379 \code
380     format = "GTiff"
381     metadata = gdal.GetDriverByName( format )
382     if metadata.has_key(gdal.DCAP_CREATE) \
383        and metadata[gdal.DCAP_CREATE] == 'YES':
384         print 'Driver %s supports Create() method.' % format
385     if metadata.has_key(gdal.DCAP_CREATECOPY) \
386        and metadata[gdal.DCAP_CREATECOPY] == 'YES':
387         print 'Driver %s supports CreateCopy() method.' % format
388 \endcode
389
390 Note that a number of drivers are read-only and won't support Create()
391 or CreateCopy().
392
393 <h2>Using CreateCopy()</h2>
394
395 The GDALDriver::CreateCopy() method can be used fairly simply as most
396 information is collected from the source dataset.  However, it includes
397 options for passing format specific creation options, and for reporting
398 progress to the user as a long dataset copy takes place.  A simple copy
399 from the a file named pszSrcFilename, to a new file named pszDstFilename
400 using default options on a format whose driver was previously fetched might
401 look like this:
402
403 In C++:
404 \code
405     GDALDataset *poSrcDS =
406        (GDALDataset *) GDALOpen( pszSrcFilename, GA_ReadOnly );
407     GDALDataset *poDstDS;
408
409     poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE,
410                                     NULL, NULL, NULL );
411     if( poDstDS != NULL )
412         delete poDstDS;
413 \endcode
414
415 In C:
416 \code
417     GDALDatasetH hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
418     GDALDatasetH hDstDS;
419
420     hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE,
421                              NULL, NULL, NULL );
422     if( hDstDS != NULL )
423         GDALClose( hDstDS );
424 \endcode
425
426 In Python:
427
428 \code
429     src_ds = gdal.Open( src_filename )
430     dst_ds = driver.CreateCopy( dst_filename, src_ds, 0 )
431 \endcode
432
433 Note that the CreateCopy() method returns a writeable dataset, and that it
434 must be closed properly to complete writing and flushing the dataset to disk.
435 In the Python case this occurs automatically when "dst_ds" goes out of scope.
436 The FALSE (or 0) value used for the bStrict option just after the destination
437 filename in the CreateCopy() call indicates that the CreateCopy() call
438 should proceed without a fatal error even if the destination dataset cannot
439 be created to exactly match the input dataset.  This might be because the
440 output format does not support the pixel datatype of the input dataset, or
441 because the destination cannot support writing georeferencing for instance.
442
443 A more complex case might involve passing creation options, and using a
444 predefined progress monitor like this:
445
446 In C++:
447 \code
448 #include "cpl_string.h"
449 ...
450     const char **papszOptions = NULL;
451    
452     papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
453     papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
454     poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE,
455                                     papzOptions, GDALTermProgress, NULL );
456     if( poDstDS != NULL )
457         delete poDstDS;
458 \endcode
459
460 In C:
461 \code
462 #include "cpl_string.h"
463 ...
464     const char **papszOptions = NULL;
465    
466     papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
467     papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
468     hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE,
469                              papzOptions, GDALTermProgres, NULL );
470     if( hDstDS != NULL )
471         GDALClose( hDstDS );
472 \endcode
473
474 In Python:
475
476 \code
477     src_ds = gdal.Open( src_filename )
478     dst_ds = driver.CreateCopy( dst_filename, src_ds, 0,
479                                 [ 'TILED=YES', 'COMPRESS=PACKBITS' ] )
480 \endcode
481
482 <h2>Using Create()</h2>
483
484 For situations in which you are not just exporting an existing file to a new
485 file, it is generally necessary to use the GDALDriver::Create() method (though
486 some interesting options are possible through use of virtual files or in-memory
487 files).  The Create() method takes an options list much like CreateCopy(),
488 but the image size, number of bands and band type must be provided explicitly.
489 <p>
490
491 In C++:
492 \code
493     GDALDataset *poDstDS;       
494     char **papszOptions = NULL;
495
496     poDstDS = poDriver->Create( pszDstFilename, 512, 512, 1, GDT_Byte,
497                                 papszOptions );
498 \endcode
499
500 In C:
501 \code
502     GDALDatasetH hDstDS;       
503     char **papszOptions = NULL;
504
505     hDstDS = GDALCreate( hDriver, pszDstFilename, 512, 512, 1, GDT_Byte,
506                          papszOptions );
507 \endcode
508
509 In Python:
510
511 \code
512     dst_ds = driver.Create( dst_filename, 512, 512, 1, gdal.GDT_Byte )
513 \endcode
514
515 Once the dataset is successfully created, all appropriate metadata and raster
516 data must be written to the file.  What this is will vary according to usage,
517 but a simple case with a projection, geotransform and raster data is covered
518 here.<p>
519
520 In C++:
521 \code
522     double adfGeoTransform[6] = { 444720, 30, 0, 3751320, 0, -30 };
523     OGRSpatialReference oSRS;
524     char *pszSRS_WKT = NULL;
525     GDALRasterBand *poBand;
526     GByte abyRaster[512*512];
527
528     poDstDS->SetGeoTransform( adfGeoTransform );
529    
530     oSRS.SetUTM( 11, TRUE );
531     oSRS.SetWellKnownGeogCS( "NAD27" );
532     oSRS.exportToWkt( &pszSRS_WKT );
533     poDstDS->SetProjection( pszSRS_WKT );
534     CPLFree( pszSRS_WKT );
535
536     poBand = poDstDS->GetRasterBand(1);
537     poBand->RasterIO( GF_Write, 0, 0, 512, 512,
538                       abyRaster, 512, 512, GDT_Byte, 0, 0 );   
539
540     delete poDstDS;
541 \endcode
542
543 In C:
544 \code
545     double adfGeoTransform[6] = { 444720, 30, 0, 3751320, 0, -30 };
546     OGRSpatialReferenceH hSRS;
547     char *pszSRS_WKT = NULL;
548     GDALRasterBandH hBand;
549     GByte abyRaster[512*512];
550
551     GDALSetGeoTransform( hDstDS, adfGeoTransform );
552
553     hSRS = OSRNewSpatialReference( NULL );
554     OSRSetUTM( hSRS, 11, TRUE );
555     OSRSetWellKnownGeogCS( hSRS, "NAD27" );                     
556     OSRExportToWkt( hSRS, &pszSRS_WKT );
557     OSRDestroySpatialReference( hSRS );
558
559     GDALSetProjection( hDstDS, pszSRS_WKT );
560     CPLFree( pszSRS_WKT );
561
562     hBand = GDALGetRasterBand( hDstDS, 1 );
563     GDALRasterIO( hBand, GF_Write, 0, 0, 512, 512,
564                   abyRaster, 512, 512, GDT_Byte, 0, 0 );   
565
566     GDALClose( hDstDS );
567 \endcode
568
569 In Python:
570
571 \code
572     import Numeric, osr
573
574     dst_ds.SetGeoTransform( [ 444720, 30, 0, 3751320, 0, -30 ] )
575    
576     srs = osr.SpatialReference()
577     srs.SetUTM( 11, 1 )
578     srs.SetWellKnownGeogCS( 'NAD27' )
579     dst_ds.SetProjection( srs.ExportToWkt() )
580
581     raster = Numeric.zeros( (512, 512) )   
582     dst_ds.GetRasterBand(1).WriteArray( raster )
583 \endcode
584
585 */
586
587
588
Note: See TracBrowser for help on using the browser.