File: gdal_tutorial_br.dox

package info (click to toggle)
gdal 1.10.1+dfsg-8
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 84,320 kB
  • ctags: 74,726
  • sloc: cpp: 677,199; ansic: 162,820; python: 13,816; cs: 11,163; sh: 10,446; java: 5,279; perl: 4,429; php: 2,971; xml: 1,500; yacc: 934; makefile: 494; sql: 112
file content (617 lines) | stat: -rw-r--r-- 23,372 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
/* $Id: gdal_tutorial_br.dox $ */

/*! \page gdal_tutorial_br Tutorial da API do GDAL

\section gdal_tutorial_open Abrindo um Arquivo

Antes de abrir um dataset raster suportado por GDAL é necessário 
registar os drivers, existe um driver para cada formato suportado e o registro
dos driver é realizado normalmente com a função GDALAllRegister().  GDALAllRegister() 
registar todos os drivers conhecidos including os "plug-in", que são bilioteca dinâmicas,  
carregadas pelo método GDALDriverManager::AutoLoadDrivers(). 
Se por algum motivo uma aplicações necessetita limitar o conjunto de drivers seria 
&uacute;til verificar o c&oacute;digo de <a href="gdalallregister.cpp.html">gdalallregister.cpp</a>.

Uma vez que os drivers s&atilde;o registados, a aplica&ccedil;&atilde;o deve chamar a 
fun&ccedil;&atilde;o GDALOpen() para abrir dataset, passando o nome do dataset e a forma de 
acesso (GA_ReadOnly ou GA_Update).

Em C++:
\code
#include "gdal_priv.h"

int main()
{
    GDALDataset  *poDataset;

    GDALAllRegister();

    poDataset = (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
    if( poDataset == NULL )
    {
	...;
    }
\endcode

Em C:
\code
#include "gdal.h"

int main()
{
    GDALDatasetH  hDataset;

    GDALAllRegister();

    hDataset = GDALOpen( pszFilename, GA_ReadOnly );
    if( hDataset == NULL )
    {
	...;
    }
\endcode

Em Python:
\code
    import gdal
    from gdalconst import *

    dataset = gdal.Open( filename, GA_ReadOnly )
    if dataset is None:
        ...
\endcode

Note que se GDALOpen() retornar NULL significa que ocorreu uma falhada, e 
que as mensagens de erro dever&atilde;o ter sido emitidas atrav&eacute;s de CPLError(). 
Se voc&ecirc; quiser controlar como os erros est&atilde;o relatados revise a  
a documenta&ccedil;&atilde;o do usu&aacute;rio de fun&ccedil;&atilde;o CPLError(). 
Em geral, todo o GDAL usa CPLError() para o relat&oacute;rio de erro. 
Note tamb&eacute;m que o pszFilename n&atilde;o necessita 
realmente ser o nome de uma arquivo f&iacute;sico (no entando geralmente &eacute;). 
A interpreta&ccedil;&atilde;o &eacute; dependente do driver, e p&ocirc;de ser um URL, 
um nome de arquivo com os par&acirc;metros adicionais adicionados na 
string para controlar a abertura do arquivo ou qualquer outra coisa. 
Tente por favor n&atilde;o limitar di&aacute;logos da sele&ccedil;&atilde;o da arquivo de 
GDAL somente a selecionar arquivos f&iacute;sicos.

\section gdal_tutorial_dataset Extraindo Informacoes do Arquivo

Como descrita em <a href="gdal_datamodel.html">GDAL Data Model</a>, um 
GDALDataset contem uma lista de bandas raster, todas pertencendo 
&agrave; uma mesma &aacute;rea, e tendo a mesma defini&ccedil;&atilde;o. Possui tamb&eacute;m um metadata, um sistema 
coordenado, uma transforma&ccedil;&atilde;o geogr&aacute;fica, tamanho do raster e v&aacute;rias outras informa&ccedil;&otilde;es.

\code
    adfGeoTransform[0] /* top left x */
    adfGeoTransform[1] /* w-e pixel resolution */
    adfGeoTransform[2] /* rotation, 0 if image is "north up" */
    adfGeoTransform[3] /* top left y */
    adfGeoTransform[4] /* rotation, 0 if image is "north up" */
    adfGeoTransform[5] /* n-s pixel resolution */
\endcode

Se n&oacute;s quis&eacute;ssemos imprimir alguma informa&ccedil;&atilde;o geral sobre a s&eacute;rie 
de dados n&oacute;s pudemos fazer o seguinte:

Em C++:
\code
    double        adfGeoTransform[6];

    printf( "Driver: %s/%s\n",
            poDataset->GetDriver()->GetDescription(), 
            poDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ) );

    printf( "Size is %dx%dx%d\n", 
            poDataset->GetRasterXSize(), poDataset->GetRasterYSize(),
            poDataset->GetRasterCount() );

    if( poDataset->GetProjectionRef()  != NULL )
        printf( "Projection is `%s'\n", poDataset->GetProjectionRef() );

    if( poDataset->GetGeoTransform( adfGeoTransform ) == CE_None )
    {
        printf( "Origin = (%.6f,%.6f)\n",
                adfGeoTransform[0], adfGeoTransform[3] );

        printf( "Pixel Size = (%.6f,%.6f)\n",
                adfGeoTransform[1], adfGeoTransform[5] );
    }
\endcode

Em C:
\code
    GDALDriverH   hDriver;
    double        adfGeoTransform[6];

    hDriver = GDALGetDatasetDriver( hDataset );
    printf( "Driver: %s/%s\n",
            GDALGetDriverShortName( hDriver ),
            GDALGetDriverLongName( hDriver ) );

    printf( "Size is %dx%dx%d\n",
	    GDALGetRasterXSize( hDataset ), 
            GDALGetRasterYSize( hDataset ),
            GDALGetRasterCount( hDataset ) );

    if( GDALGetProjectionRef( hDataset ) != NULL )
        printf( "Projection is `%s'\n", GDALGetProjectionRef( hDataset ) );

    if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
    {
        printf( "Origin = (%.6f,%.6f)\n",
                adfGeoTransform[0], adfGeoTransform[3] );

        printf( "Pixel Size = (%.6f,%.6f)\n",
                adfGeoTransform[1], adfGeoTransform[5] );
    }
\endcode

Em Python:
\code
    print 'Driver: ', dataset.GetDriver().ShortName,'/', \
          dataset.GetDriver().LongName
    print 'Size is ',dataset.RasterXSize,'x',dataset.RasterYSize, \
          'x',dataset.RasterCount
    print 'Projection is ',dataset.GetProjection()
    
    geotransform = dataset.GetGeoTransform()
    if not geotransform is None:
	print 'Origin = (',geotransform[0], ',',geotransform[3],')'
	print 'Pixel Size = (',geotransform[1], ',',geotransform[5],')'
\endcode

\section gdal_tutorial_band Extraindo uma Banda Raster

Neste ponto o acesso aos dados da raster atrav&eacute;s de GDAL pode ser feito 
uma banda de cada vez. A Band tamb&eacute;m possui metadata, tamanho de block, tabelas da cor, 
e v&aacute;rio a outra informa&ccedil;&atilde;o dispon&iacute;vel na classe GDALRasterBand. 
Os seguintes c&oacute;digos buscam um objeto de GDALRasterBand da s&eacute;rie de dados 
(numerada a partir de 1 em GetRasterCount()) e a exposi&ccedil;&otilde;es de algums 
informa&ccedil;&otilde;es sobre ela.

Em C++:
\code
	GDALRasterBand  *poBand;
        int             nBlockXSize, nBlockYSize;
        int             bGotMin, bGotMax;
        double          adfMinMax[2];
	
        poBand = poDataset->GetRasterBand( 1 );
	poBand->GetBlockSize( &nBlockXSize, &nBlockYSize );
        printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
                nBlockXSize, nBlockYSize,
                GDALGetDataTypeName(poBand->GetRasterDataType()),
                GDALGetColorInterpretationName(
                    poBand->GetColorInterpretation()) );

        adfMinMax[0] = poBand->GetMinimum( &bGotMin );
        adfMinMax[1] = poBand->GetMaximum( &bGotMax );
        if( ! (bGotMin && bGotMax) )
            GDALComputeRasterMinMax((GDALRasterBandH)poBand, TRUE, adfMinMax);

        printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
        
        if( poBand->GetOverviewCount() > 0 )
            printf( "Band has %d overviews.\n", poBand->GetOverviewCount() );

        if( poBand->GetColorTable() != NULL )
            printf( "Band has a color table with %d entries.\n", 
                     poBand->GetColorTable()->GetColorEntryCount() );
\endcode

Em C:
\code
	GDALRasterBandH hBand;
        int             nBlockXSize, nBlockYSize;
        int             bGotMin, bGotMax;
        double          adfMinMax[2];
	
        hBand = GDALGetRasterBand( hDataset, 1 );
        GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
        printf( "Block=%dx%d Type=%s, ColorInterp=%s\n",
                nBlockXSize, nBlockYSize,
                GDALGetDataTypeName(GDALGetRasterDataType(hBand)),
                GDALGetColorInterpretationName(
                    GDALGetRasterColorInterpretation(hBand)) );

        adfMinMax[0] = GDALGetRasterMinimum( hBand, &bGotMin );
        adfMinMax[1] = GDALGetRasterMaximum( hBand, &bGotMax );
        if( ! (bGotMin && bGotMax) )
            GDALComputeRasterMinMax( hBand, TRUE, adfMinMax );

        printf( "Min=%.3fd, Max=%.3f\n", adfMinMax[0], adfMinMax[1] );
        
        if( GDALGetOverviewCount(hBand) > 0 )
            printf( "Band has %d overviews.\n", GDALGetOverviewCount(hBand));

        if( GDALGetRasterColorTable( hBand ) != NULL )
            printf( "Band has a color table with %d entries.\n", 
                     GDALGetColorEntryCount(
                         GDALGetRasterColorTable( hBand ) ) );
\endcode

In Python (note several bindings are missing):
\code
	band = dataset.GetRasterBand(1)

	print 'Band Type=',gdal.GetDataTypeName(band.DataType)

	min = band.GetMinimum()
	max = band.GetMaximum()
	if min is not None and max is not None:
	    (min,max) = ComputeRasterMinMax(1)
	print 'Min=%.3f, Max=%.3f' % (min,max)

	if band.GetOverviewCount() > 0:
	    print 'Band has ', band.GetOverviewCount(), ' overviews.'

        if not band.GetRasterColorTable() is None:
	    print 'Band has a color table with ', \
	    band.GetRasterColorTable().GetCount(), ' entries.'
\endcode

\section gdal_tutorial_read Lendo dato Raster

H&aacute; algumas maneiras diferentes de ler dados da raster, mas o mais comum &eacute; 
atrav&eacute;s do M&eacute;todo GDALRasterBand::RasterIO(). Este m&eacute;todo tomar&aacute; 
automaticamente cuidado da convers&atilde;o do tipo de dados, amostragem e janela
de dados requerida. O seguinte c&oacute;digo ler&aacute; o primeiro scanline dos dados em um 
buffer em tamanho similar &agrave; quantidade lida, convertendo os valores para ponto 
flutuando como parte da opera&ccedil;&atilde;o:

Em C++:
\code
        float *pafScanline;
        int   nXSize = poBand->GetXSize();

        pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
        poBand->RasterIO( GF_Read, 0, 0, nXSize, 1, 
                          pafScanline, nXSize, 1, GDT_Float32, 
                          0, 0 );
\endcode

Em C:
\code
        float *pafScanline;
        int   nXSize = GDALGetRasterBandXSize( hBand );

        pafScanline = (float *) CPLMalloc(sizeof(float)*nXSize);
	    GDALRasterIO( hBand, GF_Read, 0, 0, nXSize, 1, 
                      pafScanline, nXSize, 1, GDT_Float32, 
                      0, 0 );
\endcode

Em Python:
 
\code
  	scanline = band.ReadRaster( 0, 0, band.XSize, 1, \
                                     band.XSize, 1, GDT_Float32 )
\endcode
 
Note que o scanline retornado &eacute; do tipo char*, e contem os 
bytes xsize*4 de dados bin&aacute;rios brutos de ponto flutuando. Isto 
pode ser convertido em Python usando o m&oacute;dulo do <b>struct</b> 
da biblioteca padr&atilde;o:

\code
	import struct

	tuple_of_floats = struct.unpack('f' * b2.XSize, scanline)
\endcode

A chamada de RasterIO espera os seguintes argumentos.
\code
CPLErr GDALRasterBand::RasterIO( GDALRWFlag eRWFlag,
                                 int nXOff, int nYOff, int nXSize, int nYSize,
                                 void * pData, int nBufXSize, int nBufYSize,
                                 GDALDataType eBufType,
                                 int nPixelSpace,
                                 int nLineSpace )
\endcode

Note que a mesma chamada de RasterIO() poder&aacute; ler, ou gravar dependendo do valor
de eRWFlag (GF_Read ou GF_Write). Os argumentos nXOff, nYOff, nXSize, nYSize 
descreve a janela de dados da raster para ler (ou para gravar). 
N&atilde;o necessita ser coincidente com os limites da image embora o acesso pode ser mais eficiente se for.

O pData &eacute; o buffer de mem&oacute;ria para os dados que ser&atilde;o lidos ou gravados. 
O verdadeiro tipo de dado &eacute aquele passado por eBufType, tal como GDT_Float32, 
ou GDT_Byte. A chamada de RasterIO() cuidar&aacute; de converter entre o tipo 
de dados do buffer e o tipo de dados da banda. Anotar que ao converter dados do 
ponto flutuando para o inteiro RasterIO arredonda para baixo, e ao converter de 
para fora dos limites de valores v&aacute;lidos para o tipo de sa&iacute;da, ser&aacute; escolhido o mais
pr&oacute;ximo valor poss&iacute;vel. 
Isto implica, por exemplo, que os dados 16bit lidos em um buffer de GDT_Byte 
converter&atilde;o todos os valores maiores de 255 para 255, os <b>dados n&atilde;o est&atilde;o escalados!</b>

Os valores nBufXSize e nBufYSize descrevem o tamanho do buffer. Ao carregar dados na 
resolu&ccedil;&atilde;o completa os valores seria o mesmo que o tamanho da janela. Entretanto, para carregar 
uma vista de solu&ccedil;&atilde;o reduzida (overview) os valores podiam ser ajustado para menos do que a janela 
no arquivo. Neste caso o RasterIO() utilizar&aacute; overview para fazer 
mais eficientemente o IO se as overview forem apropriadas.

O nPixelSpace, e o nLineSpace s&atilde;o normalmente zero indicando que os valores default
devem ser usados. Entretanto, podem ser usados controlar o acesso &agrave; dados da mem&oacute;ria, 
permitindo a leitura em um buffer que contem dados intercalados (interleave) pixel por exemplo.  

\section gdal_tutorial_close Fechando o Dataset

Por favor tenha em mente que os objetos de GDALRasterBand est&atilde;o possu&iacute;dos por sua 
dataset, e nunca devem ser destru&iacute;dos com o operador delete de C++. 
GDALDataset podem ser fechado chamando GDALClose() ou usando o operador delete 
no GDALDataset. Um ou outro resultado na finaliza&ccedil;&atilde;o apropriada, e resolver 
grava&ccedil;&otilde;es pendentes.

\section gdal_tutorial_creation Tecnicas para criar arquivos

As arquivos em formatos suportados GDAL podem ser criadas se o driver do formato 
suportar a cria&ccedil;&atilde;o. H&aacute; duas t&eacute;cnicas gerais para criar arquivos, usando CreateCopy() e Create(). 
O m&eacute;todo de CreateCopy chama o m&eacute;todo CreateCopy() do driver do formato, e 
passar como par&acirc;metro dataset que ser&aacute; copiado. O m&eacute;todo criar chama o 
m&eacute;todo Create() do driver, e ent&atilde;o explicitamente grava todos os metadata, e dados 
da raster com as chamadas separadas. Todos os drivers que suportam criar arquivos 
novos suportam o m&eacute;todo de CreateCopy(), mas somente algum sustenta&ccedil;&atilde;o o m&eacute;todo Create().

Para determinar se o driver de um formato suporta Create ou CreateCopy &eacute; necess&aacute;rio verificar o 
DCAP_CREATE e os metadata de DCAP_CREATECOPY no driver do formato 
objetam. Assegurar-se de que GDALAllRegister() tenha sido chamado antes de chamar GetDriverByName(). 

Em C++:
\code
#include "cpl_string.h"
...
    const char *pszFormat = "GTiff";
    GDALDriver *poDriver;
    char **papszMetadata;

    poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);

    if( poDriver == NULL )
        exit( 1 );

    papszMetadata = poDriver->GetMetadata();
    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) )
        printf( "Driver %s supports Create() method.\n", pszFormat );
    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
        printf( "Driver %s supports CreateCopy() method.\n", pszFormat );
\endcode

Em C:
\code
#include "cpl_string.h"
...
    const char *pszFormat = "GTiff";
    GDALDriver hDriver = GDALGetDriverByName( pszFormat );
    char **papszMetadata;

    if( hDriver == NULL )
        exit( 1 );

    papszMetadata = GDALGetMetadata( hDriver, NULL );
    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) )
        printf( "Driver %s supports Create() method.\n", pszFormat );
    if( CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )
        printf( "Driver %s supports CreateCopy() method.\n", pszFormat );
\endcode

Em Python:

\code
    format = "GTiff"
    driver = gdal.GetDriverByName( format )
    metadata = driver.GetMetadata()
    if metadata.has_key(gdal.DCAP_CREATE) \
       and metadata[gdal.DCAP_CREATE] == 'YES':
        print 'Driver %s supports Create() method.' % format
    if metadata.has_key(gdal.DCAP_CREATECOPY) \
       and metadata[gdal.DCAP_CREATECOPY] == 'YES':
        print 'Driver %s supports CreateCopy() method.' % format
\endcode

Note que um n&uacute;mero de drivers s&atilde;o de leitura apenas e n&atilde;o suportar&atilde;o 
Create() ou CreateCopy ().

\section gdal_tutorial_createcopy Usando CreateCopy()

O GDALDriver:: O m&eacute;todo de CreateCopy() pode ser usado razoavelmente 
simples enquanto a maioria de informa&ccedil;&atilde;o &eacute; coletada do dataset de entrada.
Entretanto, inclui op&ccedil;&otilde;es para passar a formato op&ccedil;&otilde;es 
espec&iacute;ficas da cria&ccedil;&atilde;o, e para relatar o progresso ao usu&aacute;rio enquanto 
uma c&oacute;pia longa da s&eacute;rie de dados ocorre. Uma c&oacute;pia simples de uma arquivo 
nomeou o pszSrcFilename, a uma arquivo nova nomeada pszDstFilename usando 
op&ccedil;&otilde;es de defeito em um formato cujo o driver fosse buscado previamente 
pudesse olhar como este:

Em C++:
\code
    GDALDataset *poSrcDS = 
       (GDALDataset *) GDALOpen( pszSrcFilename, GA_ReadOnly );
    GDALDataset *poDstDS;

    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE, 
                                    NULL, NULL, NULL );
    if( poDstDS != NULL )
        delete poDstDS;
\endcode

Em C:
\code
    GDALDatasetH hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
    GDALDatasetH hDstDS;

    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE, 
                             NULL, NULL, NULL );
    if( hDstDS != NULL )
        GDALClose( hDstDS );
\endcode

Em Python:

\code
    src_ds = gdal.Open( src_filename )
    dst_ds = driver.CreateCopy( dst_filename, src_ds, 0 )
\endcode

Note que o m&eacute;todo de CreateCopy() retorna um dataset writeable, 
e que deve ser fechado corretamente &agrave; escrita completa e a nivelar a s&eacute;rie 
de dados ao disco. No Python encaixotar isto ocorre automaticamente quando 
os "dst_ds" saem do espa&ccedil;o. O valor FALSO (ou 0) usado para a op&ccedil;&atilde;o do 
bStrict imediatamente depois que o nome de arquivo do destino na chamada 
de CreateCopy() indica que a chamada de CreateCopy() deve proseguir sem
um erro fatal mesmo se a s&eacute;rie de dados do destino n&atilde;o puder ser criada 
para combinar exatamente a s&eacute;rie de dados da entrada. Isto p&ocirc;de ser porque 
o formato da sa&iacute;da n&atilde;o suporta o datatype do pixel do dataset de entrada, 
ou porque o destino n&atilde;o pode suportar a escrita que georeferencing 
por exemplo.

Casos mais complexo p&ocirc;dem envolver passar op&ccedil;&otilde;es da cria&ccedil;&atilde;o, e usar
um monitor predefinido do progresso como este:

Em C++:
\code
#include "cpl_string.h"
...
    char **papszOptions = NULL;
    
    papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
    papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
    poDstDS = poDriver->CreateCopy( pszDstFilename, poSrcDS, FALSE, 
                                    papszOptions, GDALTermProgress, NULL );
    if( poDstDS != NULL )
        delete poDstDS;
    CSLDestroy( papszOptions );
\endcode

Em C:
\code
#include "cpl_string.h"
...
    char **papszOptions = NULL;
    
    papszOptions = CSLSetNameValue( papszOptions, "TILED", "YES" );
    papszOptions = CSLSetNameValue( papszOptions, "COMPRESS", "PACKBITS" );
    hDstDS = GDALCreateCopy( hDriver, pszDstFilename, hSrcDS, FALSE, 
                             papszOptions, GDALTermProgres, NULL );
    if( hDstDS != NULL )
        GDALClose( hDstDS );
    CSLDestroy( papszOptions );
\endcode

Em Python:

\code
    src_ds = gdal.Open( src_filename )
    dst_ds = driver.CreateCopy( dst_filename, src_ds, 0, 
                                [ 'TILED=YES', 'COMPRESS=PACKBITS' ] )
\endcode

\section gdal_tutorial_create Usando Create()

Em situa&ccedil;&otilde;es em que n&atilde;o se quer somente exportar um arquivo existente 
para uma arquivo novo, geralmente usa-se o m&eacute;todo GDALDriver::Criar() (embora algumas 
op&ccedil;&otilde;es interessantes s&atilde;o poss&iacute;veis 
com o uso de arquivos virtuais ou de arquivos da em-mem&oacute;ria). 
O m&eacute;todo Create() examina uma lista de op&ccedil;&otilde;es bem como o CreateCopy(), mas 
o tamanho da imagem, n&uacute;mero das bandas e o tipo da banda deve ser fornecido explicitamente.
<p>

Em C++:
\code
    GDALDataset *poDstDS;	
    char **papszOptions = NULL;

    poDstDS = poDriver->Create( pszDstFilename, 512, 512, 1, GDT_Byte, 
                                papszOptions );
\endcode

Em C:
\code
    GDALDatasetH hDstDS;	
    char **papszOptions = NULL;

    hDstDS = GDALCreate( hDriver, pszDstFilename, 512, 512, 1, GDT_Byte, 
                         papszOptions );
\endcode

Em Python:

\code
    dst_ds = driver.Create( dst_filename, 512, 512, 1, gdal.GDT_Byte )
\endcode

Uma vez que o dataset &eacute; criado com sucesso, todos os metadata apropriados devem 
ser gravados no arquivo. O que variar&aacute; de acordo com o uso, 
mas um caso simples com proje&ccedil;&atilde;o, do geotransform e da raster &eacute; 
mostrado a seguir:<p>

Em C++:
\code
    double adfGeoTransform[6] = { 444720, 30, 0, 3751320, 0, -30 };
    OGRSpatialReference oSRS;
    char *pszSRS_WKT = NULL;
    GDALRasterBand *poBand;
    GByte abyRaster[512*512];

    poDstDS->SetGeoTransform( adfGeoTransform );
    
    oSRS.SetUTM( 11, TRUE );
    oSRS.SetWellKnownGeogCS( "NAD27" );
    oSRS.exportToWkt( &pszSRS_WKT );
    poDstDS->SetProjection( pszSRS_WKT );
    CPLFree( pszSRS_WKT );

    poBand = poDstDS->GetRasterBand(1);
    poBand->RasterIO( GF_Write, 0, 0, 512, 512, 
                      abyRaster, 512, 512, GDT_Byte, 0, 0 );    

    delete poDstDS;
\endcode

Em C:
\code
    double adfGeoTransform[6] = { 444720, 30, 0, 3751320, 0, -30 };
    OGRSpatialReferenceH hSRS;
    char *pszSRS_WKT = NULL;
    GDALRasterBandH hBand;
    GByte abyRaster[512*512];

    GDALSetGeoTransform( hDstDS, adfGeoTransform );

    hSRS = OSRNewSpatialReference( NULL );
    OSRSetUTM( hSRS, 11, TRUE );
    OSRSetWellKnownGeogCS( hSRS, "NAD27" );			
    OSRExportToWkt( hSRS, &pszSRS_WKT );
    OSRDestroySpatialReference( hSRS );

    GDALSetProjection( hDstDS, pszSRS_WKT );
    CPLFree( pszSRS_WKT );

    hBand = GDALGetRasterBand( hDstDS, 1 );
    GDALRasterIO( hBand, GF_Write, 0, 0, 512, 512, 
                  abyRaster, 512, 512, GDT_Byte, 0, 0 );    

    GDALClose( hDstDS );
\endcode

Em Python:

\code
    import Numeric, osr

    dst_ds.SetGeoTransform( [ 444720, 30, 0, 3751320, 0, -30 ] )
    
    srs = osr.SpatialReference()
    srs.SetUTM( 11, 1 )
    srs.SetWellKnownGeogCS( 'NAD27' )
    dst_ds.SetProjection( srs.ExportToWkt() )

    raster = Numeric.zeros( (512, 512) )    
    dst_ds.GetRasterBand(1).WriteArray( raster )
\endcode

\htmlonly
<p>
$Id: gdal_tutorial_br.dox $
</p>
\endhtmlonly

*/