1 : /******************************************************************************
2 : * $Id: gdaldataset.cpp 18494 2010-01-09 15:55:52Z mloskot $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Base class for raster file formats.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1998, 2003, 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_priv.h"
31 : #include "cpl_string.h"
32 : #include "cpl_hash_set.h"
33 : #include "cpl_multiproc.h"
34 :
35 : CPL_CVSID("$Id: gdaldataset.cpp 18494 2010-01-09 15:55:52Z mloskot $");
36 :
37 : typedef struct
38 : {
39 : /* PID of the thread that mark the dataset as shared */
40 : /* This may not be the actual PID, but the responsiblePID */
41 : GIntBig nPID;
42 : char *pszDescription;
43 : GDALAccess eAccess;
44 :
45 : GDALDataset *poDS;
46 : } SharedDatasetCtxt;
47 :
48 : typedef struct
49 : {
50 : GDALDataset *poDS;
51 : /* In the case of a shared dataset, memorize the PID of the thread */
52 : /* that marked the dataset as shared, so that we can remove it from */
53 : /* the phSharedDatasetSet in the destructor of the dataset, even */
54 : /* if GDALClose is called from a different thread */
55 : /* Ideally, this should be stored in the GDALDataset object itself */
56 : /* but this is inconvenient to change the object size at that time */
57 : GIntBig nPIDCreatorForShared;
58 : } DatasetCtxt;
59 :
60 : /* Set of datasets opened as shared datasets (with GDALOpenShared) */
61 : /* The values in the set are of type SharedDatasetCtxt */
62 : static CPLHashSet* phSharedDatasetSet = NULL;
63 :
64 : /* Set of all datasets created in the constructor of GDALDataset */
65 : /* The values in the set are of type DatasetCtxt */
66 : static CPLHashSet* phAllDatasetSet = NULL;
67 : static void *hDLMutex = NULL;
68 :
69 : /* Static array of all datasets. Used by GDALGetOpenDatasets */
70 : /* Not thread-safe. See GDALGetOpenDatasets */
71 : static GDALDataset** ppDatasets = NULL;
72 :
73 5912 : static unsigned long GDALSharedDatasetHashFunc(const void* elt)
74 : {
75 5912 : SharedDatasetCtxt* psStruct = (SharedDatasetCtxt*) elt;
76 5912 : return (unsigned long) (CPLHashSetHashStr(psStruct->pszDescription) ^ psStruct->eAccess ^ psStruct->nPID);
77 : }
78 :
79 5326 : static int GDALSharedDatasetEqualFunc(const void* elt1, const void* elt2)
80 : {
81 5326 : SharedDatasetCtxt* psStruct1 = (SharedDatasetCtxt*) elt1;
82 5326 : SharedDatasetCtxt* psStruct2 = (SharedDatasetCtxt*) elt2;
83 : return strcmp(psStruct1->pszDescription, psStruct2->pszDescription) == 0 &&
84 : psStruct1->nPID == psStruct2->nPID &&
85 5326 : psStruct1->eAccess == psStruct2->eAccess;
86 : }
87 :
88 139 : static void GDALSharedDatasetFreeFunc(void* elt)
89 : {
90 139 : SharedDatasetCtxt* psStruct = (SharedDatasetCtxt*) elt;
91 139 : CPLFree(psStruct->pszDescription);
92 139 : CPLFree(psStruct);
93 139 : }
94 :
95 66858 : static unsigned long GDALDatasetHashFunc(const void* elt)
96 : {
97 66858 : DatasetCtxt* psStruct = (DatasetCtxt*) elt;
98 66858 : return (unsigned long)psStruct->poDS;
99 : }
100 :
101 28602 : static int GDALDatasetEqualFunc(const void* elt1, const void* elt2)
102 : {
103 28602 : DatasetCtxt* psStruct1 = (DatasetCtxt*) elt1;
104 28602 : DatasetCtxt* psStruct2 = (DatasetCtxt*) elt2;
105 28602 : return psStruct1->poDS == psStruct2->poDS ;
106 : }
107 :
108 11858 : static void GDALDatasetFreeFunc(void* elt)
109 : {
110 11858 : DatasetCtxt* psStruct = (DatasetCtxt*) elt;
111 11858 : CPLFree(psStruct);
112 11858 : }
113 :
114 : /************************************************************************/
115 : /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
116 : /************************************************************************/
117 :
118 : void** GDALGetphDLMutex();
119 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID);
120 : GIntBig GDALGetResponsiblePIDForCurrentThread();
121 :
122 : /* The open-shared mutex must be used by the ProxyPool too */
123 8550 : void** GDALGetphDLMutex()
124 : {
125 8550 : return &hDLMutex;
126 : }
127 :
128 : /* The current thread will act in the behalf of the thread of PID responsiblePID */
129 8384 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID)
130 : {
131 8384 : GIntBig* pResponsiblePID = (GIntBig*) CPLGetTLS(CTLS_RESPONSIBLEPID);
132 8384 : if (pResponsiblePID == NULL)
133 : {
134 17 : pResponsiblePID = (GIntBig*) CPLMalloc(sizeof(GIntBig));
135 17 : CPLSetTLS(CTLS_RESPONSIBLEPID, pResponsiblePID, TRUE);
136 : }
137 8384 : *pResponsiblePID = responsiblePID;
138 8384 : }
139 :
140 : /* Get the PID of the thread that the current thread will act in the behalf of */
141 : /* By default : the current thread acts in the behalf of itself */
142 30316 : GIntBig GDALGetResponsiblePIDForCurrentThread()
143 : {
144 30316 : GIntBig* pResponsiblePID = (GIntBig*) CPLGetTLS(CTLS_RESPONSIBLEPID);
145 30316 : if (pResponsiblePID == NULL)
146 16724 : return CPLGetPID();
147 13592 : return *pResponsiblePID;
148 : }
149 :
150 :
151 : /************************************************************************/
152 : /* ==================================================================== */
153 : /* GDALDataset */
154 : /* ==================================================================== */
155 : /************************************************************************/
156 :
157 : /**
158 : * \class GDALDataset "gdal_priv.h"
159 : *
160 : * A dataset encapsulating one or more raster bands. Details are
161 : * further discussed in the <a href="gdal_datamodel.html#GDALDataset">GDAL
162 : * Data Model</a>.
163 : *
164 : * Use GDALOpen() or GDALOpenShared() to create a GDALDataset for a named file,
165 : * or GDALDriver::Create() or GDALDriver::CreateCopy() to create a new
166 : * dataset.
167 : */
168 :
169 : /************************************************************************/
170 : /* GDALDataset() */
171 : /************************************************************************/
172 :
173 11859 : GDALDataset::GDALDataset()
174 :
175 : {
176 11859 : poDriver = NULL;
177 11859 : eAccess = GA_ReadOnly;
178 11859 : nRasterXSize = 512;
179 11859 : nRasterYSize = 512;
180 11859 : nBands = 0;
181 11859 : papoBands = NULL;
182 11859 : nRefCount = 1;
183 11859 : bShared = FALSE;
184 :
185 : /* -------------------------------------------------------------------- */
186 : /* Add this dataset to the open dataset list. */
187 : /* -------------------------------------------------------------------- */
188 : {
189 11859 : CPLMutexHolderD( &hDLMutex );
190 :
191 11859 : if (phAllDatasetSet == NULL)
192 2969 : phAllDatasetSet = CPLHashSetNew(GDALDatasetHashFunc, GDALDatasetEqualFunc, GDALDatasetFreeFunc);
193 11859 : DatasetCtxt* ctxt = (DatasetCtxt*)CPLMalloc(sizeof(DatasetCtxt));
194 11859 : ctxt->poDS = this;
195 11859 : ctxt->nPIDCreatorForShared = -1;
196 11859 : CPLHashSetInsert(phAllDatasetSet, ctxt);
197 : }
198 :
199 : /* -------------------------------------------------------------------- */
200 : /* Set forced caching flag. */
201 : /* -------------------------------------------------------------------- */
202 : bForceCachedIO = CSLTestBoolean(
203 11859 : CPLGetConfigOption( "GDAL_FORCE_CACHING", "NO") );
204 11859 : }
205 :
206 :
207 : /************************************************************************/
208 : /* ~GDALDataset() */
209 : /************************************************************************/
210 :
211 : /**
212 : * \brief Destroy an open GDALDataset.
213 : *
214 : * This is the accepted method of closing a GDAL dataset and deallocating
215 : * all resources associated with it.
216 : *
217 : * Equivelent of the C callable GDALClose(). Except that GDALClose() first
218 : * decrements the reference count, and then closes only if it has dropped to
219 : * zero.
220 : *
221 : * For Windows users, it is not recommanded using the delete operator on the
222 : * dataset object because of known issues when allocating and freeing memory across
223 : * module boundaries. Calling GDALClose() is then a better option.
224 : */
225 :
226 11858 : GDALDataset::~GDALDataset()
227 :
228 : {
229 : int i;
230 :
231 : // we don't want to report destruction of datasets that
232 : // were never really open.
233 11858 : if( nBands != 0 || !EQUAL(GetDescription(),"") )
234 : {
235 11572 : if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
236 : CPLDebug( "GDAL",
237 : "GDALClose(%s, this=%p) (pid=%d, responsiblePID=%d)", GetDescription(), this,
238 : (int)CPLGetPID(),
239 0 : (int)GDALGetResponsiblePIDForCurrentThread() );
240 : else
241 : CPLDebug( "GDAL",
242 11572 : "GDALClose(%s, this=%p)", GetDescription(), this );
243 : }
244 :
245 : /* -------------------------------------------------------------------- */
246 : /* Remove dataset from the "open" dataset list. */
247 : /* -------------------------------------------------------------------- */
248 : {
249 11858 : CPLMutexHolderD( &hDLMutex );
250 :
251 : DatasetCtxt sStruct;
252 11858 : sStruct.poDS = this;
253 11858 : DatasetCtxt* psStruct = (DatasetCtxt*) CPLHashSetLookup(phAllDatasetSet, &sStruct);
254 11858 : GIntBig nPIDCreatorForShared = psStruct->nPIDCreatorForShared;
255 11858 : CPLHashSetRemove(phAllDatasetSet, psStruct);
256 :
257 11858 : if (bShared && phSharedDatasetSet != NULL)
258 : {
259 : SharedDatasetCtxt* psStruct;
260 : SharedDatasetCtxt sStruct;
261 214 : sStruct.nPID = nPIDCreatorForShared;
262 214 : sStruct.eAccess = eAccess;
263 214 : sStruct.pszDescription = (char*) GetDescription();
264 214 : psStruct = (SharedDatasetCtxt*) CPLHashSetLookup(phSharedDatasetSet, &sStruct);
265 353 : if (psStruct && psStruct->poDS == this)
266 : {
267 139 : CPLHashSetRemove(phSharedDatasetSet, psStruct);
268 : }
269 : else
270 : {
271 75 : CPLDebug("GDAL", "Should not happen. Cannot find %s, this=%p in phSharedDatasetSet", GetDescription(), this);
272 : }
273 : }
274 :
275 11858 : if (CPLHashSetSize(phAllDatasetSet) == 0)
276 : {
277 2968 : CPLHashSetDestroy(phAllDatasetSet);
278 2968 : phAllDatasetSet = NULL;
279 2968 : if (phSharedDatasetSet)
280 : {
281 85 : CPLHashSetDestroy(phSharedDatasetSet);
282 : }
283 2968 : phSharedDatasetSet = NULL;
284 2968 : CPLFree(ppDatasets);
285 2968 : ppDatasets = NULL;
286 11858 : }
287 : }
288 :
289 : /* -------------------------------------------------------------------- */
290 : /* Destroy the raster bands if they exist. */
291 : /* -------------------------------------------------------------------- */
292 628726 : for( i = 0; i < nBands && papoBands != NULL; i++ )
293 : {
294 616868 : if( papoBands[i] != NULL )
295 616866 : delete papoBands[i];
296 : }
297 :
298 11858 : CPLFree( papoBands );
299 11858 : }
300 :
301 : /************************************************************************/
302 : /* FlushCache() */
303 : /************************************************************************/
304 :
305 : /**
306 : * \brief Flush all write cached data to disk.
307 : *
308 : * Any raster (or other GDAL) data written via GDAL calls, but buffered
309 : * internally will be written to disk.
310 : *
311 : * Using this method does not prevent use from calling GDALClose()
312 : * to properly close a dataset and ensure that important data not addressed
313 : * by FlushCache() is written in the file.
314 : *
315 : * This method is the same as the C function GDALFlushCache().
316 : */
317 :
318 15788 : void GDALDataset::FlushCache()
319 :
320 : {
321 : int i;
322 :
323 : // This sometimes happens if a dataset is destroyed before completely
324 : // built.
325 :
326 15788 : if( papoBands == NULL )
327 309 : return;
328 :
329 1031123 : for( i = 0; i < nBands; i++ )
330 : {
331 1015644 : if( papoBands[i] != NULL )
332 1015644 : papoBands[i]->FlushCache();
333 : }
334 : }
335 :
336 : /************************************************************************/
337 : /* GDALFlushCache() */
338 : /************************************************************************/
339 :
340 : /**
341 : * \brief Flush all write cached data to disk.
342 : *
343 : * @see GDALDataset::FlushCache().
344 : */
345 :
346 14 : void CPL_STDCALL GDALFlushCache( GDALDatasetH hDS )
347 :
348 : {
349 14 : VALIDATE_POINTER0( hDS, "GDALFlushCache" );
350 :
351 14 : ((GDALDataset *) hDS)->FlushCache();
352 : }
353 :
354 : /************************************************************************/
355 : /* BlockBasedFlushCache() */
356 : /* */
357 : /* This helper method can be called by the */
358 : /* GDALDataset::FlushCache() for particular drivers to ensure */
359 : /* that buffers will be flushed in a manner suitable for pixel */
360 : /* interleaved (by block) IO. That is, if all the bands have */
361 : /* the same size blocks then a given block will be flushed for */
362 : /* all bands before proceeding to the next block. */
363 : /************************************************************************/
364 :
365 19 : void GDALDataset::BlockBasedFlushCache()
366 :
367 : {
368 : GDALRasterBand *poBand1;
369 : int nBlockXSize, nBlockYSize, iBand;
370 :
371 19 : poBand1 = GetRasterBand( 1 );
372 19 : if( poBand1 == NULL )
373 : {
374 1 : GDALDataset::FlushCache();
375 1 : return;
376 : }
377 :
378 18 : poBand1->GetBlockSize( &nBlockXSize, &nBlockYSize );
379 :
380 : /* -------------------------------------------------------------------- */
381 : /* Verify that all bands match. */
382 : /* -------------------------------------------------------------------- */
383 32 : for( iBand = 1; iBand < nBands; iBand++ )
384 : {
385 : int nThisBlockXSize, nThisBlockYSize;
386 14 : GDALRasterBand *poBand = GetRasterBand( iBand+1 );
387 :
388 14 : poBand->GetBlockSize( &nThisBlockXSize, &nThisBlockYSize );
389 14 : if( nThisBlockXSize != nBlockXSize && nThisBlockYSize != nBlockYSize )
390 : {
391 0 : GDALDataset::FlushCache();
392 0 : return;
393 : }
394 : }
395 :
396 : /* -------------------------------------------------------------------- */
397 : /* Now flush writable data. */
398 : /* -------------------------------------------------------------------- */
399 318 : for( int iY = 0; iY < poBand1->nBlocksPerColumn; iY++ )
400 : {
401 600 : for( int iX = 0; iX < poBand1->nBlocksPerRow; iX++ )
402 : {
403 1000 : for( iBand = 0; iBand < nBands; iBand++ )
404 : {
405 700 : GDALRasterBand *poBand = GetRasterBand( iBand+1 );
406 :
407 700 : if( poBand->papoBlocks[iX + iY*poBand1->nBlocksPerRow] != NULL)
408 : {
409 : CPLErr eErr;
410 :
411 400 : eErr = poBand->FlushBlock( iX, iY );
412 :
413 400 : if( eErr != CE_None )
414 0 : return;
415 : }
416 : }
417 : }
418 : }
419 : }
420 :
421 : /************************************************************************/
422 : /* RasterInitialize() */
423 : /* */
424 : /* Initialize raster size */
425 : /************************************************************************/
426 :
427 0 : void GDALDataset::RasterInitialize( int nXSize, int nYSize )
428 :
429 : {
430 : CPLAssert( nXSize > 0 && nYSize > 0 );
431 :
432 0 : nRasterXSize = nXSize;
433 0 : nRasterYSize = nYSize;
434 0 : }
435 :
436 : /************************************************************************/
437 : /* AddBand() */
438 : /************************************************************************/
439 :
440 : /**
441 : * \brief Add a band to a dataset.
442 : *
443 : * This method will add a new band to the dataset if the underlying format
444 : * supports this action. Most formats do not.
445 : *
446 : * Note that the new GDALRasterBand is not returned. It may be fetched
447 : * after successful completion of the method by calling
448 : * GDALDataset::GetRasterBand(GDALDataset::GetRasterCount()-1) as the newest
449 : * band will always be the last band.
450 : *
451 : * @param eType the data type of the pixels in the new band.
452 : *
453 : * @param papszOptions a list of NAME=VALUE option strings. The supported
454 : * options are format specific. NULL may be passed by default.
455 : *
456 : * @return CE_None on success or CE_Failure on failure.
457 : */
458 :
459 0 : CPLErr GDALDataset::AddBand( GDALDataType eType, char ** papszOptions )
460 :
461 : {
462 : (void) eType;
463 : (void) papszOptions;
464 :
465 : CPLError( CE_Failure, CPLE_NotSupported,
466 0 : "Dataset does not support the AddBand() method." );
467 :
468 0 : return CE_Failure;
469 : }
470 :
471 : /************************************************************************/
472 : /* GDALAddBand() */
473 : /************************************************************************/
474 :
475 : /**
476 : * \brief Add a band to a dataset.
477 : *
478 : * @see GDALDataset::AddBand().
479 : */
480 :
481 25 : CPLErr CPL_STDCALL GDALAddBand( GDALDatasetH hDataset,
482 : GDALDataType eType, char **papszOptions )
483 :
484 : {
485 25 : VALIDATE_POINTER1( hDataset, "GDALAddBand", CE_Failure );
486 :
487 25 : return ((GDALDataset *) hDataset)->AddBand( eType, papszOptions );
488 : }
489 :
490 : /************************************************************************/
491 : /* SetBand() */
492 : /* */
493 : /* Set a band in the band array, updating the band count, and */
494 : /* array size appropriately. */
495 : /************************************************************************/
496 :
497 617288 : void GDALDataset::SetBand( int nNewBand, GDALRasterBand * poBand )
498 :
499 : {
500 : /* -------------------------------------------------------------------- */
501 : /* Do we need to grow the bands list? */
502 : /* -------------------------------------------------------------------- */
503 617288 : if( nBands < nNewBand || papoBands == NULL ) {
504 : int i;
505 : GDALRasterBand** papoNewBands;
506 :
507 353421 : if( papoBands == NULL )
508 : papoNewBands = (GDALRasterBand **)
509 11544 : VSICalloc(sizeof(GDALRasterBand*), MAX(nNewBand,nBands));
510 : else
511 : papoNewBands = (GDALRasterBand **)
512 : VSIRealloc(papoBands, sizeof(GDALRasterBand*) *
513 341877 : MAX(nNewBand,nBands));
514 353421 : if (papoNewBands == NULL)
515 : {
516 : CPLError(CE_Failure, CPLE_OutOfMemory,
517 0 : "Cannot allocate band array");
518 0 : return;
519 : }
520 353421 : papoBands = papoNewBands;
521 :
522 702461 : for( i = nBands; i < nNewBand; i++ )
523 349040 : papoBands[i] = NULL;
524 :
525 353421 : nBands = MAX(nBands,nNewBand);
526 : }
527 :
528 : /* -------------------------------------------------------------------- */
529 : /* Set the band. Resetting the band is currently not permitted. */
530 : /* -------------------------------------------------------------------- */
531 617288 : if( papoBands[nNewBand-1] != NULL )
532 : {
533 : CPLError(CE_Failure, CPLE_NotSupported,
534 0 : "Cannot set band %d as it is already set", nNewBand);
535 0 : return;
536 : }
537 :
538 617288 : papoBands[nNewBand-1] = poBand;
539 :
540 : /* -------------------------------------------------------------------- */
541 : /* Set back reference information on the raster band. Note */
542 : /* that the GDALDataset is a friend of the GDALRasterBand */
543 : /* specifically to allow this. */
544 : /* -------------------------------------------------------------------- */
545 617288 : poBand->nBand = nNewBand;
546 617288 : poBand->poDS = this;
547 617288 : poBand->nRasterXSize = nRasterXSize;
548 617288 : poBand->nRasterYSize = nRasterYSize;
549 617288 : poBand->eAccess = eAccess; /* default access to be same as dataset */
550 : }
551 :
552 : /************************************************************************/
553 : /* GetRasterXSize() */
554 : /************************************************************************/
555 :
556 : /**
557 :
558 : \brief Fetch raster width in pixels.
559 :
560 : Equivelent of the C function GDALGetRasterXSize().
561 :
562 : @return the width in pixels of raster bands in this GDALDataset.
563 :
564 : */
565 :
566 375736 : int GDALDataset::GetRasterXSize()
567 :
568 : {
569 375736 : return nRasterXSize;
570 : }
571 :
572 : /************************************************************************/
573 : /* GDALGetRasterXSize() */
574 : /************************************************************************/
575 :
576 : /**
577 : * \brief Fetch raster width in pixels.
578 : *
579 : * @see GDALDataset::GetRasterXSize().
580 : */
581 :
582 3620 : int CPL_STDCALL GDALGetRasterXSize( GDALDatasetH hDataset )
583 :
584 : {
585 3620 : VALIDATE_POINTER1( hDataset, "GDALGetRasterXSize", 0 );
586 :
587 3620 : return ((GDALDataset *) hDataset)->GetRasterXSize();
588 : }
589 :
590 :
591 : /************************************************************************/
592 : /* GetRasterYSize() */
593 : /************************************************************************/
594 :
595 : /**
596 :
597 : \brief Fetch raster height in pixels.
598 :
599 : Equivelent of the C function GDALGetRasterYSize().
600 :
601 : @return the height in pixels of raster bands in this GDALDataset.
602 :
603 : */
604 :
605 102011 : int GDALDataset::GetRasterYSize()
606 :
607 : {
608 102011 : return nRasterYSize;
609 : }
610 :
611 : /************************************************************************/
612 : /* GDALGetRasterYSize() */
613 : /************************************************************************/
614 :
615 : /**
616 : * \brief Fetch raster height in pixels.
617 : *
618 : * @see GDALDataset::GetRasterYSize().
619 : */
620 :
621 11979 : int CPL_STDCALL GDALGetRasterYSize( GDALDatasetH hDataset )
622 :
623 : {
624 11979 : VALIDATE_POINTER1( hDataset, "GDALGetRasterYSize", 0 );
625 :
626 11979 : return ((GDALDataset *) hDataset)->GetRasterYSize();
627 : }
628 :
629 : /************************************************************************/
630 : /* GetRasterBand() */
631 : /************************************************************************/
632 :
633 : /**
634 :
635 : \brief Fetch a band object for a dataset.
636 :
637 : Equivalent of the C function GDALGetRasterBand().
638 :
639 : @param nBandId the index number of the band to fetch, from 1 to
640 : GetRasterCount().
641 :
642 : @return the nBandId th band object
643 :
644 : */
645 :
646 1926553 : GDALRasterBand * GDALDataset::GetRasterBand( int nBandId )
647 :
648 : {
649 1926553 : if ( papoBands )
650 : {
651 1926538 : if( nBandId < 1 || nBandId > nBands )
652 : {
653 : CPLError( CE_Failure, CPLE_IllegalArg,
654 : "GDALDataset::GetRasterBand(%d) - Illegal band #\n",
655 0 : nBandId );
656 0 : return NULL;
657 : }
658 : else
659 1926538 : return( papoBands[nBandId-1] );
660 : }
661 15 : return NULL;
662 : }
663 :
664 : /************************************************************************/
665 : /* GDALGetRasterBand() */
666 : /************************************************************************/
667 :
668 : /**
669 : * \brief Fetch a band object for a dataset.
670 : * @see GDALDataset::GetRasterBand().
671 : */
672 :
673 174495 : GDALRasterBandH CPL_STDCALL GDALGetRasterBand( GDALDatasetH hDS, int nBandId )
674 :
675 : {
676 174495 : VALIDATE_POINTER1( hDS, "GDALGetRasterBand", NULL );
677 :
678 174495 : return( (GDALRasterBandH) ((GDALDataset *) hDS)->GetRasterBand(nBandId) );
679 : }
680 :
681 : /************************************************************************/
682 : /* GetRasterCount() */
683 : /************************************************************************/
684 :
685 : /**
686 : * \brief Fetch the number of raster bands on this dataset.
687 : *
688 : * Same as the C function GDALGetRasterCount().
689 : *
690 : * @return the number of raster bands.
691 : */
692 :
693 1704363 : int GDALDataset::GetRasterCount()
694 :
695 : {
696 1704363 : return papoBands ? nBands : 0;
697 : }
698 :
699 : /************************************************************************/
700 : /* GDALGetRasterCount() */
701 : /************************************************************************/
702 :
703 : /**
704 : * \brief Fetch the number of raster bands on this dataset.
705 : *
706 : * @see GDALDataset::GetRasterCount().
707 : */
708 :
709 337566 : int CPL_STDCALL GDALGetRasterCount( GDALDatasetH hDS )
710 :
711 : {
712 337566 : VALIDATE_POINTER1( hDS, "GDALGetRasterCount", 0 );
713 :
714 337566 : return( ((GDALDataset *) hDS)->GetRasterCount() );
715 : }
716 :
717 : /************************************************************************/
718 : /* GetProjectionRef() */
719 : /************************************************************************/
720 :
721 : /**
722 : * \brief Fetch the projection definition string for this dataset.
723 : *
724 : * Same as the C function GDALGetProjectionRef().
725 : *
726 : * The returned string defines the projection coordinate system of the
727 : * image in OpenGIS WKT format. It should be suitable for use with the
728 : * OGRSpatialReference class.
729 : *
730 : * When a projection definition is not available an empty (but not NULL)
731 : * string is returned.
732 : *
733 : * @return a pointer to an internal projection reference string. It should
734 : * not be altered, freed or expected to last for long.
735 : *
736 : * @see http://www.gdal.org/ogr/osr_tutorial.html
737 : */
738 :
739 3271 : const char *GDALDataset::GetProjectionRef()
740 :
741 : {
742 3271 : return( "" );
743 : }
744 :
745 : /************************************************************************/
746 : /* GDALGetProjectionRef() */
747 : /************************************************************************/
748 :
749 : /**
750 : * \brief Fetch the projection definition string for this dataset.
751 : *
752 : * @see GDALDataset::GetProjectionRef()
753 : */
754 :
755 1819 : const char * CPL_STDCALL GDALGetProjectionRef( GDALDatasetH hDS )
756 :
757 : {
758 1819 : VALIDATE_POINTER1( hDS, "GDALGetProjectionRef", NULL );
759 :
760 1819 : return( ((GDALDataset *) hDS)->GetProjectionRef() );
761 : }
762 :
763 : /************************************************************************/
764 : /* SetProjection() */
765 : /************************************************************************/
766 :
767 : /**
768 : * \brief Set the projection reference string for this dataset.
769 : *
770 : * The string should be in OGC WKT or PROJ.4 format. An error may occur
771 : * because of incorrectly specified projection strings, because the dataset
772 : * is not writable, or because the dataset does not support the indicated
773 : * projection. Many formats do not support writing projections.
774 : *
775 : * This method is the same as the C GDALSetProjection() function.
776 : *
777 : * @param pszProjection projection reference string.
778 : *
779 : * @return CE_Failure if an error occurs, otherwise CE_None.
780 : */
781 :
782 2 : CPLErr GDALDataset::SetProjection( const char * )
783 :
784 : {
785 2 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
786 : CPLError( CE_Failure, CPLE_NotSupported,
787 0 : "Dataset does not support the SetProjection() method." );
788 2 : return CE_Failure;
789 : }
790 :
791 : /************************************************************************/
792 : /* GDALSetProjection() */
793 : /************************************************************************/
794 :
795 : /**
796 : * \brief Set the projection reference string for this dataset.
797 : *
798 : * @see GDALDataset::SetProjection()
799 : */
800 :
801 567 : CPLErr CPL_STDCALL GDALSetProjection( GDALDatasetH hDS, const char * pszProjection )
802 :
803 : {
804 567 : VALIDATE_POINTER1( hDS, "GDALSetProjection", CE_Failure );
805 :
806 567 : return( ((GDALDataset *) hDS)->SetProjection(pszProjection) );
807 : }
808 :
809 : /************************************************************************/
810 : /* GetGeoTransform() */
811 : /************************************************************************/
812 :
813 : /**
814 : * \brief Fetch the affine transformation coefficients.
815 : *
816 : * Fetches the coefficients for transforming between pixel/line (P,L) raster
817 : * space, and projection coordinates (Xp,Yp) space.
818 : *
819 : * \code
820 : * Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2];
821 : * Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5];
822 : * \endcode
823 : *
824 : * In a north up image, padfTransform[1] is the pixel width, and
825 : * padfTransform[5] is the pixel height. The upper left corner of the
826 : * upper left pixel is at position (padfTransform[0],padfTransform[3]).
827 : *
828 : * The default transform is (0,1,0,0,0,1) and should be returned even when
829 : * a CE_Failure error is returned, such as for formats that don't support
830 : * transformation to projection coordinates.
831 : *
832 : * NOTE: GetGeoTransform() isn't expressive enough to handle the variety of
833 : * OGC Grid Coverages pixel/line to projection transformation schemes.
834 : * Eventually this method will be depreciated in favour of a more general
835 : * scheme.
836 : *
837 : * This method does the same thing as the C GDALGetGeoTransform() function.
838 : *
839 : * @param padfTransform an existing six double buffer into which the
840 : * transformation will be placed.
841 : *
842 : * @return CE_None on success, or CE_Failure if no transform can be fetched.
843 : */
844 :
845 2949 : CPLErr GDALDataset::GetGeoTransform( double * padfTransform )
846 :
847 : {
848 : CPLAssert( padfTransform != NULL );
849 :
850 2949 : padfTransform[0] = 0.0; /* X Origin (top left corner) */
851 2949 : padfTransform[1] = 1.0; /* X Pixel size */
852 2949 : padfTransform[2] = 0.0;
853 :
854 2949 : padfTransform[3] = 0.0; /* Y Origin (top left corner) */
855 2949 : padfTransform[4] = 0.0;
856 2949 : padfTransform[5] = 1.0; /* Y Pixel Size */
857 :
858 2949 : return( CE_Failure );
859 : }
860 :
861 : /************************************************************************/
862 : /* GDALGetGeoTransform() */
863 : /************************************************************************/
864 :
865 : /**
866 : * \brief Fetch the affine transformation coefficients.
867 : *
868 : * @see GDALDataset::GetGeoTransform()
869 : */
870 :
871 1269 : CPLErr CPL_STDCALL GDALGetGeoTransform( GDALDatasetH hDS, double * padfTransform )
872 :
873 : {
874 1269 : VALIDATE_POINTER1( hDS, "GDALGetGeoTransform", CE_Failure );
875 :
876 1269 : return( ((GDALDataset *) hDS)->GetGeoTransform(padfTransform) );
877 : }
878 :
879 : /************************************************************************/
880 : /* SetGeoTransform() */
881 : /************************************************************************/
882 :
883 : /**
884 : * \brief Set the affine transformation coefficients.
885 : *
886 : * See GetGeoTransform() for details on the meaning of the padfTransform
887 : * coefficients.
888 : *
889 : * This method does the same thing as the C GDALSetGeoTransform() function.
890 : *
891 : * @param padfTransform a six double buffer containing the transformation
892 : * coefficients to be written with the dataset.
893 : *
894 : * @return CE_None on success, or CE_Failure if this transform cannot be
895 : * written.
896 : */
897 :
898 2 : CPLErr GDALDataset::SetGeoTransform( double * )
899 :
900 : {
901 2 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
902 : CPLError( CE_Failure, CPLE_NotSupported,
903 0 : "SetGeoTransform() not supported for this dataset." );
904 :
905 2 : return( CE_Failure );
906 : }
907 :
908 : /************************************************************************/
909 : /* GDALSetGeoTransform() */
910 : /************************************************************************/
911 :
912 : /**
913 : * \brief Set the affine transformation coefficients.
914 : *
915 : * @see GDALDataset::SetGeoTransform()
916 : */
917 :
918 : CPLErr CPL_STDCALL
919 613 : GDALSetGeoTransform( GDALDatasetH hDS, double * padfTransform )
920 :
921 : {
922 613 : VALIDATE_POINTER1( hDS, "GDALSetGeoTransform", CE_Failure );
923 :
924 613 : return( ((GDALDataset *) hDS)->SetGeoTransform(padfTransform) );
925 : }
926 :
927 : /************************************************************************/
928 : /* GetInternalHandle() */
929 : /************************************************************************/
930 :
931 : /**
932 : * \brief Fetch a format specific internally meaningful handle.
933 : *
934 : * This method is the same as the C GDALGetInternalHandle() method.
935 : *
936 : * @param pszHandleName the handle name desired. The meaningful names
937 : * will be specific to the file format.
938 : *
939 : * @return the desired handle value, or NULL if not recognised/supported.
940 : */
941 :
942 0 : void *GDALDataset::GetInternalHandle( const char * )
943 :
944 : {
945 0 : return( NULL );
946 : }
947 :
948 : /************************************************************************/
949 : /* GDALGetInternalHandle() */
950 : /************************************************************************/
951 :
952 : /**
953 : * \brief Fetch a format specific internally meaningful handle.
954 : *
955 : * @see GDALDataset::GetInternalHandle()
956 : */
957 :
958 : void * CPL_STDCALL
959 0 : GDALGetInternalHandle( GDALDatasetH hDS, const char * pszRequest )
960 :
961 : {
962 0 : VALIDATE_POINTER1( hDS, "GDALGetInternalHandle", NULL );
963 :
964 0 : return( ((GDALDataset *) hDS)->GetInternalHandle(pszRequest) );
965 : }
966 :
967 : /************************************************************************/
968 : /* GetDriver() */
969 : /************************************************************************/
970 :
971 : /**
972 : * \brief Fetch the driver to which this dataset relates.
973 : *
974 : * This method is the same as the C GDALGetDatasetDriver() function.
975 : *
976 : * @return the driver on which the dataset was created with GDALOpen() or
977 : * GDALCreate().
978 : */
979 :
980 416 : GDALDriver * GDALDataset::GetDriver()
981 :
982 : {
983 416 : return poDriver;
984 : }
985 :
986 : /************************************************************************/
987 : /* GDALGetDatasetDriver() */
988 : /************************************************************************/
989 :
990 : /**
991 : * \brief Fetch the driver to which this dataset relates.
992 : *
993 : * @see GDALDataset::GetDriver()
994 : */
995 :
996 392 : GDALDriverH CPL_STDCALL GDALGetDatasetDriver( GDALDatasetH hDataset )
997 :
998 : {
999 392 : VALIDATE_POINTER1( hDataset, "GDALGetDatasetDriver", NULL );
1000 :
1001 392 : return (GDALDriverH) ((GDALDataset *) hDataset)->GetDriver();
1002 : }
1003 :
1004 : /************************************************************************/
1005 : /* Reference() */
1006 : /************************************************************************/
1007 :
1008 : /**
1009 : * \brief Add one to dataset reference count.
1010 : *
1011 : * The reference is one after instantiation.
1012 : *
1013 : * This method is the same as the C GDALReferenceDataset() function.
1014 : *
1015 : * @return the post-increment reference count.
1016 : */
1017 :
1018 5202 : int GDALDataset::Reference()
1019 :
1020 : {
1021 5202 : return ++nRefCount;
1022 : }
1023 :
1024 : /************************************************************************/
1025 : /* GDALReferenceDataset() */
1026 : /************************************************************************/
1027 :
1028 : /**
1029 : * \brief Add one to dataset reference count.
1030 : *
1031 : * @see GDALDataset::Reference()
1032 : */
1033 :
1034 42 : int CPL_STDCALL GDALReferenceDataset( GDALDatasetH hDataset )
1035 :
1036 : {
1037 42 : VALIDATE_POINTER1( hDataset, "GDALReferenceDataset", 0 );
1038 :
1039 42 : return ((GDALDataset *) hDataset)->Reference();
1040 : }
1041 :
1042 : /************************************************************************/
1043 : /* Dereference() */
1044 : /************************************************************************/
1045 :
1046 : /**
1047 : * \brief Subtract one from dataset reference count.
1048 : *
1049 : * The reference is one after instantiation. Generally when the reference
1050 : * count has dropped to zero the dataset may be safely deleted (closed).
1051 : *
1052 : * This method is the same as the C GDALDereferenceDataset() function.
1053 : *
1054 : * @return the post-decrement reference count.
1055 : */
1056 :
1057 14003 : int GDALDataset::Dereference()
1058 :
1059 : {
1060 14003 : return --nRefCount;
1061 : }
1062 :
1063 : /************************************************************************/
1064 : /* GDALDereferenceDataset() */
1065 : /************************************************************************/
1066 :
1067 : /**
1068 : * \brief Subtract one from dataset reference count.
1069 : *
1070 : * @see GDALDataset::Dereference()
1071 : */
1072 :
1073 13613 : int CPL_STDCALL GDALDereferenceDataset( GDALDatasetH hDataset )
1074 :
1075 : {
1076 13613 : VALIDATE_POINTER1( hDataset, "GDALDereferenceDataset", 0 );
1077 :
1078 13613 : return ((GDALDataset *) hDataset)->Dereference();
1079 : }
1080 :
1081 : /************************************************************************/
1082 : /* GetShared() */
1083 : /************************************************************************/
1084 :
1085 : /**
1086 : * \brief Returns shared flag.
1087 : *
1088 : * @return TRUE if the GDALDataset is available for sharing, or FALSE if not.
1089 : */
1090 :
1091 11349 : int GDALDataset::GetShared()
1092 :
1093 : {
1094 11349 : return bShared;
1095 : }
1096 :
1097 : /************************************************************************/
1098 : /* MarkAsShared() */
1099 : /************************************************************************/
1100 :
1101 : /**
1102 : * \brief Mark this dataset as available for sharing.
1103 : */
1104 :
1105 139 : void GDALDataset::MarkAsShared()
1106 :
1107 : {
1108 : CPLAssert( !bShared );
1109 :
1110 139 : bShared = TRUE;
1111 :
1112 139 : GIntBig nPID = GDALGetResponsiblePIDForCurrentThread();
1113 : SharedDatasetCtxt* psStruct;
1114 :
1115 : /* Insert the dataset in the set of shared opened datasets */
1116 139 : CPLMutexHolderD( &hDLMutex );
1117 139 : if (phSharedDatasetSet == NULL)
1118 86 : phSharedDatasetSet = CPLHashSetNew(GDALSharedDatasetHashFunc, GDALSharedDatasetEqualFunc, GDALSharedDatasetFreeFunc);
1119 :
1120 139 : psStruct = (SharedDatasetCtxt*)CPLMalloc(sizeof(SharedDatasetCtxt));
1121 139 : psStruct->poDS = this;
1122 139 : psStruct->nPID = nPID;
1123 139 : psStruct->eAccess = eAccess;
1124 139 : psStruct->pszDescription = CPLStrdup(GetDescription());
1125 139 : if(CPLHashSetLookup(phSharedDatasetSet, psStruct) != NULL)
1126 : {
1127 0 : CPLFree(psStruct);
1128 : CPLError(CE_Failure, CPLE_AppDefined,
1129 0 : "An existing shared dataset has already this description. This should not happen");
1130 : }
1131 : else
1132 : {
1133 139 : CPLHashSetInsert(phSharedDatasetSet, psStruct);
1134 :
1135 : DatasetCtxt sStruct;
1136 139 : sStruct.poDS = this;
1137 139 : DatasetCtxt* psStruct = (DatasetCtxt*) CPLHashSetLookup(phAllDatasetSet, &sStruct);
1138 139 : psStruct->nPIDCreatorForShared = nPID;
1139 139 : }
1140 139 : }
1141 :
1142 : /************************************************************************/
1143 : /* GetGCPCount() */
1144 : /************************************************************************/
1145 :
1146 : /**
1147 : * \brief Get number of GCPs.
1148 : *
1149 : * This method is the same as the C function GDALGetGCPCount().
1150 : *
1151 : * @return number of GCPs for this dataset. Zero if there are none.
1152 : */
1153 :
1154 44 : int GDALDataset::GetGCPCount()
1155 :
1156 : {
1157 44 : return 0;
1158 : }
1159 :
1160 : /************************************************************************/
1161 : /* GDALGetGCPCount() */
1162 : /************************************************************************/
1163 :
1164 : /**
1165 : * \brief Get number of GCPs.
1166 : *
1167 : * @see GDALDataset::GetGCPCount()
1168 : */
1169 :
1170 121 : int CPL_STDCALL GDALGetGCPCount( GDALDatasetH hDS )
1171 :
1172 : {
1173 121 : VALIDATE_POINTER1( hDS, "GDALGetGCPCount", 0 );
1174 :
1175 121 : return ((GDALDataset *) hDS)->GetGCPCount();
1176 : }
1177 :
1178 : /************************************************************************/
1179 : /* GetGCPProjection() */
1180 : /************************************************************************/
1181 :
1182 : /**
1183 : * \brief Get output projection for GCPs.
1184 : *
1185 : * This method is the same as the C function GDALGetGCPProjection().
1186 : *
1187 : * The projection string follows the normal rules from GetProjectionRef().
1188 : *
1189 : * @return internal projection string or "" if there are no GCPs.
1190 : */
1191 :
1192 0 : const char *GDALDataset::GetGCPProjection()
1193 :
1194 : {
1195 0 : return "";
1196 : }
1197 :
1198 : /************************************************************************/
1199 : /* GDALGetGCPProjection() */
1200 : /************************************************************************/
1201 :
1202 : /**
1203 : * \brief Get output projection for GCPs.
1204 : *
1205 : * @see GDALDataset::GetGCPProjection()
1206 : */
1207 :
1208 81 : const char * CPL_STDCALL GDALGetGCPProjection( GDALDatasetH hDS )
1209 :
1210 : {
1211 81 : VALIDATE_POINTER1( hDS, "GDALGetGCPProjection", NULL );
1212 :
1213 81 : return ((GDALDataset *) hDS)->GetGCPProjection();
1214 : }
1215 :
1216 : /************************************************************************/
1217 : /* GetGCPs() */
1218 : /************************************************************************/
1219 :
1220 : /**
1221 : * \brief Fetch GCPs.
1222 : *
1223 : * This method is the same as the C function GDALGetGCPs().
1224 : *
1225 : * @return pointer to internal GCP structure list. It should not be modified,
1226 : * and may change on the next GDAL call.
1227 : */
1228 :
1229 1 : const GDAL_GCP *GDALDataset::GetGCPs()
1230 :
1231 : {
1232 1 : return NULL;
1233 : }
1234 :
1235 : /************************************************************************/
1236 : /* GDALGetGCPs() */
1237 : /************************************************************************/
1238 :
1239 : /**
1240 : * \brief Fetch GCPs.
1241 : *
1242 : * @see GDALDataset::GetGCPs()
1243 : */
1244 :
1245 52 : const GDAL_GCP * CPL_STDCALL GDALGetGCPs( GDALDatasetH hDS )
1246 :
1247 : {
1248 52 : VALIDATE_POINTER1( hDS, "GDALGetGCPs", NULL );
1249 :
1250 52 : return ((GDALDataset *) hDS)->GetGCPs();
1251 : }
1252 :
1253 :
1254 : /************************************************************************/
1255 : /* SetGCPs() */
1256 : /************************************************************************/
1257 :
1258 : /**
1259 : * \brief Assign GCPs.
1260 : *
1261 : * This method is the same as the C function GDALSetGCPs().
1262 : *
1263 : * This method assigns the passed set of GCPs to this dataset, as well as
1264 : * setting their coordinate system. Internally copies are made of the
1265 : * coordinate system and list of points, so the caller remains resposible for
1266 : * deallocating these arguments if appropriate.
1267 : *
1268 : * Most formats do not support setting of GCPs, even foramts that can
1269 : * handle GCPs. These formats will return CE_Failure.
1270 : *
1271 : * @param nGCPCount number of GCPs being assigned.
1272 : *
1273 : * @param pasGCPList array of GCP structures being assign (nGCPCount in array).
1274 : *
1275 : * @param pszGCPProjection the new OGC WKT coordinate system to assign for the
1276 : * GCP output coordinates. This parameter should be "" if no output coordinate
1277 : * system is known.
1278 : *
1279 : * @return CE_None on success, CE_Failure on failure (including if action is
1280 : * not supported for this format).
1281 : */
1282 :
1283 0 : CPLErr GDALDataset::SetGCPs( int nGCPCount,
1284 : const GDAL_GCP *pasGCPList,
1285 : const char * pszGCPProjection )
1286 :
1287 : {
1288 : (void) nGCPCount;
1289 : (void) pasGCPList;
1290 : (void) pszGCPProjection;
1291 :
1292 0 : if( !(GetMOFlags() & GMO_IGNORE_UNIMPLEMENTED) )
1293 : CPLError( CE_Failure, CPLE_NotSupported,
1294 0 : "Dataset does not support the SetGCPs() method." );
1295 :
1296 0 : return CE_Failure;
1297 : }
1298 :
1299 : /************************************************************************/
1300 : /* GDALSetGCPs() */
1301 : /************************************************************************/
1302 :
1303 : /**
1304 : * \brief Assign GCPs.
1305 : *
1306 : * @see GDALDataset::SetGCPs()
1307 : */
1308 :
1309 1 : CPLErr CPL_STDCALL GDALSetGCPs( GDALDatasetH hDS, int nGCPCount,
1310 : const GDAL_GCP *pasGCPList,
1311 : const char *pszGCPProjection )
1312 :
1313 : {
1314 1 : VALIDATE_POINTER1( hDS, "GDALSetGCPs", CE_Failure );
1315 :
1316 : return ((GDALDataset *) hDS)->SetGCPs( nGCPCount, pasGCPList,
1317 1 : pszGCPProjection );
1318 : }
1319 :
1320 : /************************************************************************/
1321 : /* BuildOverviews() */
1322 : /************************************************************************/
1323 :
1324 : /**
1325 : * \brief Build raster overview(s)
1326 : *
1327 : * If the operation is unsupported for the indicated dataset, then
1328 : * CE_Failure is returned, and CPLGetLastErrorNo() will return
1329 : * CPLE_NotSupported.
1330 : *
1331 : * This method is the same as the C function GDALBuildOverviews().
1332 : *
1333 : * @param pszResampling one of "NEAREST", "GAUSS", "CUBIC", "AVERAGE", "MODE",
1334 : * "AVERAGE_MAGPHASE" or "NONE" controlling the downsampling method applied.
1335 : * @param nOverviews number of overviews to build.
1336 : * @param panOverviewList the list of overview decimation factors to build.
1337 : * @param nBand number of bands to build overviews for in panBandList. Build
1338 : * for all bands if this is 0.
1339 : * @param panBandList list of band numbers.
1340 : * @param pfnProgress a function to call to report progress, or NULL.
1341 : * @param pProgressData application data to pass to the progress function.
1342 : *
1343 : * @return CE_None on success or CE_Failure if the operation doesn't work.
1344 : *
1345 : * For example, to build overview level 2, 4 and 8 on all bands the following
1346 : * call could be made:
1347 : * <pre>
1348 : * int anOverviewList[3] = { 2, 4, 8 };
1349 : *
1350 : * poDataset->BuildOverviews( "NEAREST", 3, anOverviewList, 0, NULL,
1351 : * GDALDummyProgress, NULL );
1352 : * </pre>
1353 : *
1354 : * @see GDALRegenerateOverviews()
1355 : */
1356 :
1357 104 : CPLErr GDALDataset::BuildOverviews( const char *pszResampling,
1358 : int nOverviews, int *panOverviewList,
1359 : int nListBands, int *panBandList,
1360 : GDALProgressFunc pfnProgress,
1361 : void * pProgressData )
1362 :
1363 : {
1364 : CPLErr eErr;
1365 104 : int *panAllBandList = NULL;
1366 :
1367 104 : if( nListBands == 0 )
1368 : {
1369 102 : nListBands = GetRasterCount();
1370 102 : panAllBandList = (int *) CPLMalloc(sizeof(int) * nListBands);
1371 261 : for( int i = 0; i < nListBands; i++ )
1372 159 : panAllBandList[i] = i+1;
1373 :
1374 102 : panBandList = panAllBandList;
1375 : }
1376 :
1377 104 : if( pfnProgress == NULL )
1378 97 : pfnProgress = GDALDummyProgress;
1379 :
1380 : eErr = IBuildOverviews( pszResampling, nOverviews, panOverviewList,
1381 104 : nListBands, panBandList, pfnProgress, pProgressData );
1382 :
1383 104 : if( panAllBandList != NULL )
1384 102 : CPLFree( panAllBandList );
1385 :
1386 104 : return eErr;
1387 : }
1388 :
1389 : /************************************************************************/
1390 : /* GDALBuildOverviews() */
1391 : /************************************************************************/
1392 :
1393 : /**
1394 : * \brief Build raster overview(s)
1395 : *
1396 : * @see GDALDataset::BuildOverviews()
1397 : */
1398 :
1399 100 : CPLErr CPL_STDCALL GDALBuildOverviews( GDALDatasetH hDataset,
1400 : const char *pszResampling,
1401 : int nOverviews, int *panOverviewList,
1402 : int nListBands, int *panBandList,
1403 : GDALProgressFunc pfnProgress,
1404 : void * pProgressData )
1405 :
1406 : {
1407 100 : VALIDATE_POINTER1( hDataset, "GDALBuildOverviews", CE_Failure );
1408 :
1409 : return ((GDALDataset *) hDataset)->BuildOverviews(
1410 : pszResampling, nOverviews, panOverviewList, nListBands, panBandList,
1411 100 : pfnProgress, pProgressData );
1412 : }
1413 :
1414 : /************************************************************************/
1415 : /* IBuildOverviews() */
1416 : /* */
1417 : /* Default implementation. */
1418 : /************************************************************************/
1419 :
1420 36 : CPLErr GDALDataset::IBuildOverviews( const char *pszResampling,
1421 : int nOverviews, int *panOverviewList,
1422 : int nListBands, int *panBandList,
1423 : GDALProgressFunc pfnProgress,
1424 : void * pProgressData )
1425 :
1426 : {
1427 36 : if( oOvManager.IsInitialized() )
1428 : return oOvManager.BuildOverviews( NULL, pszResampling,
1429 : nOverviews, panOverviewList,
1430 : nListBands, panBandList,
1431 36 : pfnProgress, pProgressData );
1432 : else
1433 : {
1434 : CPLError( CE_Failure, CPLE_NotSupported,
1435 0 : "BuildOverviews() not supported for this dataset." );
1436 :
1437 0 : return( CE_Failure );
1438 : }
1439 : }
1440 :
1441 : /************************************************************************/
1442 : /* IRasterIO() */
1443 : /* */
1444 : /* The default implementation of IRasterIO() is to pass the */
1445 : /* request off to each band objects rasterio methods with */
1446 : /* appropriate arguments. */
1447 : /************************************************************************/
1448 :
1449 346805 : CPLErr GDALDataset::IRasterIO( GDALRWFlag eRWFlag,
1450 : int nXOff, int nYOff, int nXSize, int nYSize,
1451 : void * pData, int nBufXSize, int nBufYSize,
1452 : GDALDataType eBufType,
1453 : int nBandCount, int *panBandMap,
1454 : int nPixelSpace, int nLineSpace, int nBandSpace)
1455 :
1456 : {
1457 : int iBandIndex;
1458 346805 : CPLErr eErr = CE_None;
1459 346805 : const char* pszInterleave = NULL;
1460 :
1461 : CPLAssert( NULL != pData );
1462 :
1463 362564 : if (nXSize == nBufXSize && nYSize == nBufYSize &&
1464 15759 : (pszInterleave = GetMetadataItem("INTERLEAVE", "IMAGE_STRUCTURE")) != NULL &&
1465 : EQUAL(pszInterleave, "PIXEL"))
1466 : {
1467 : return BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1468 : pData, nBufXSize, nBufYSize,
1469 : eBufType, nBandCount, panBandMap,
1470 712 : nPixelSpace, nLineSpace, nBandSpace );
1471 : }
1472 :
1473 708534 : for( iBandIndex = 0;
1474 : iBandIndex < nBandCount && eErr == CE_None;
1475 : iBandIndex++ )
1476 : {
1477 362441 : GDALRasterBand *poBand = GetRasterBand(panBandMap[iBandIndex]);
1478 : GByte *pabyBandData;
1479 :
1480 362441 : pabyBandData = ((GByte *) pData) + iBandIndex * nBandSpace;
1481 :
1482 : eErr = poBand->IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1483 : (void *) pabyBandData, nBufXSize, nBufYSize,
1484 362441 : eBufType, nPixelSpace, nLineSpace );
1485 : }
1486 :
1487 346093 : return eErr;
1488 : }
1489 :
1490 :
1491 : /************************************************************************/
1492 : /* RasterIO() */
1493 : /************************************************************************/
1494 :
1495 : /**
1496 : * \brief Read/write a region of image data from multiple bands.
1497 : *
1498 : * This method allows reading a region of one or more GDALRasterBands from
1499 : * this dataset into a buffer, or writing data from a buffer into a region
1500 : * of the GDALRasterBands. It automatically takes care of data type
1501 : * translation if the data type (eBufType) of the buffer is different than
1502 : * that of the GDALRasterBand.
1503 : * The method also takes care of image decimation / replication if the
1504 : * buffer size (nBufXSize x nBufYSize) is different than the size of the
1505 : * region being accessed (nXSize x nYSize).
1506 : *
1507 : * The nPixelSpace, nLineSpace and nBandSpace parameters allow reading into or
1508 : * writing from various organization of buffers.
1509 : *
1510 : * For highest performance full resolution data access, read and write
1511 : * on "block boundaries" as returned by GetBlockSize(), or use the
1512 : * ReadBlock() and WriteBlock() methods.
1513 : *
1514 : * This method is the same as the C GDALDatasetRasterIO() function.
1515 : *
1516 : * @param eRWFlag Either GF_Read to read a region of data, or GF_Write to
1517 : * write a region of data.
1518 : *
1519 : * @param nXOff The pixel offset to the top left corner of the region
1520 : * of the band to be accessed. This would be zero to start from the left side.
1521 : *
1522 : * @param nYOff The line offset to the top left corner of the region
1523 : * of the band to be accessed. This would be zero to start from the top.
1524 : *
1525 : * @param nXSize The width of the region of the band to be accessed in pixels.
1526 : *
1527 : * @param nYSize The height of the region of the band to be accessed in lines.
1528 : *
1529 : * @param pData The buffer into which the data should be read, or from which
1530 : * it should be written. This buffer must contain at least
1531 : * nBufXSize * nBufYSize * nBandCount words of type eBufType. It is organized
1532 : * in left to right,top to bottom pixel order. Spacing is controlled by the
1533 : * nPixelSpace, and nLineSpace parameters.
1534 : *
1535 : * @param nBufXSize the width of the buffer image into which the desired region
1536 : * is to be read, or from which it is to be written.
1537 : *
1538 : * @param nBufYSize the height of the buffer image into which the desired
1539 : * region is to be read, or from which it is to be written.
1540 : *
1541 : * @param eBufType the type of the pixel values in the pData data buffer. The
1542 : * pixel values will automatically be translated to/from the GDALRasterBand
1543 : * data type as needed.
1544 : *
1545 : * @param nBandCount the number of bands being read or written.
1546 : *
1547 : * @param panBandMap the list of nBandCount band numbers being read/written.
1548 : * Note band numbers are 1 based. This may be NULL to select the first
1549 : * nBandCount bands.
1550 : *
1551 : * @param nPixelSpace The byte offset from the start of one pixel value in
1552 : * pData to the start of the next pixel value within a scanline. If defaulted
1553 : * (0) the size of the datatype eBufType is used.
1554 : *
1555 : * @param nLineSpace The byte offset from the start of one scanline in
1556 : * pData to the start of the next. If defaulted (0) the size of the datatype
1557 : * eBufType * nBufXSize is used.
1558 : *
1559 : * @param nBandSpace the byte offset from the start of one bands data to the
1560 : * start of the next. If defaulted (0) the value will be
1561 : * nLineSpace * nBufYSize implying band sequential organization
1562 : * of the data buffer.
1563 : *
1564 : * @return CE_Failure if the access fails, otherwise CE_None.
1565 : */
1566 :
1567 347378 : CPLErr GDALDataset::RasterIO( GDALRWFlag eRWFlag,
1568 : int nXOff, int nYOff, int nXSize, int nYSize,
1569 : void * pData, int nBufXSize, int nBufYSize,
1570 : GDALDataType eBufType,
1571 : int nBandCount, int *panBandMap,
1572 : int nPixelSpace, int nLineSpace, int nBandSpace )
1573 :
1574 : {
1575 347378 : int i = 0;
1576 347378 : int bNeedToFreeBandMap = FALSE;
1577 347378 : CPLErr eErr = CE_None;
1578 :
1579 347378 : if( NULL == pData )
1580 : {
1581 : CPLError( CE_Failure, CPLE_AppDefined,
1582 0 : "The buffer into which the data should be read is null" );
1583 0 : return CE_Failure;
1584 : }
1585 :
1586 : /* -------------------------------------------------------------------- */
1587 : /* Some size values are "noop". Lets just return to avoid */
1588 : /* stressing lower level functions. */
1589 : /* -------------------------------------------------------------------- */
1590 347378 : if( nXSize < 1 || nYSize < 1 || nBufXSize < 1 || nBufYSize < 1 )
1591 : {
1592 : CPLDebug( "GDAL",
1593 : "RasterIO() skipped for odd window or buffer size.\n"
1594 : " Window = (%d,%d)x%dx%d\n"
1595 : " Buffer = %dx%d\n",
1596 : nXOff, nYOff, nXSize, nYSize,
1597 0 : nBufXSize, nBufYSize );
1598 :
1599 0 : return CE_None;
1600 : }
1601 :
1602 : /* -------------------------------------------------------------------- */
1603 : /* If pixel and line spaceing are defaulted assign reasonable */
1604 : /* value assuming a packed buffer. */
1605 : /* -------------------------------------------------------------------- */
1606 347378 : if( nPixelSpace == 0 )
1607 338515 : nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
1608 :
1609 347378 : if( nLineSpace == 0 )
1610 : {
1611 346203 : if (nPixelSpace > INT_MAX / nBufXSize)
1612 : {
1613 : CPLError( CE_Failure, CPLE_AppDefined,
1614 0 : "Int overflow : %d x %d", nPixelSpace, nBufXSize );
1615 0 : return CE_Failure;
1616 : }
1617 346203 : nLineSpace = nPixelSpace * nBufXSize;
1618 : }
1619 :
1620 347378 : if( nBandSpace == 0 )
1621 : {
1622 338570 : if (nLineSpace > INT_MAX / nBufYSize)
1623 : {
1624 : CPLError( CE_Failure, CPLE_AppDefined,
1625 0 : "Int overflow : %d x %d", nLineSpace, nBufYSize );
1626 0 : return CE_Failure;
1627 : }
1628 338570 : nBandSpace = nLineSpace * nBufYSize;
1629 : }
1630 :
1631 347378 : if( panBandMap == NULL )
1632 : {
1633 8492 : if (nBandCount > GetRasterCount())
1634 : {
1635 : CPLError( CE_Failure, CPLE_IllegalArg,
1636 : "nBandCount cannot be greater than %d",
1637 0 : GetRasterCount() );
1638 0 : return CE_Failure;
1639 : }
1640 8492 : panBandMap = (int *) VSIMalloc2(sizeof(int), nBandCount);
1641 8492 : if (panBandMap == NULL)
1642 : {
1643 : CPLError( CE_Failure, CPLE_OutOfMemory,
1644 0 : "Out of memory while allocating band map array" );
1645 0 : return CE_Failure;
1646 : }
1647 32532 : for( i = 0; i < nBandCount; i++ )
1648 24040 : panBandMap[i] = i+1;
1649 :
1650 8492 : bNeedToFreeBandMap = TRUE;
1651 : }
1652 :
1653 : /* -------------------------------------------------------------------- */
1654 : /* Do some validation of parameters. */
1655 : /* -------------------------------------------------------------------- */
1656 347378 : if( nXOff < 0 || nXOff > INT_MAX - nXSize || nXOff + nXSize > nRasterXSize
1657 : || nYOff < 0 || nYOff > INT_MAX - nYSize || nYOff + nYSize > nRasterYSize )
1658 : {
1659 : CPLError( CE_Failure, CPLE_IllegalArg,
1660 : "Access window out of range in RasterIO(). Requested\n"
1661 : "(%d,%d) of size %dx%d on raster of %dx%d.",
1662 0 : nXOff, nYOff, nXSize, nYSize, nRasterXSize, nRasterYSize );
1663 0 : eErr = CE_Failure;
1664 : }
1665 :
1666 347378 : if( eRWFlag != GF_Read && eRWFlag != GF_Write )
1667 : {
1668 : CPLError( CE_Failure, CPLE_IllegalArg,
1669 : "eRWFlag = %d, only GF_Read (0) and GF_Write (1) are legal.",
1670 0 : eRWFlag );
1671 0 : eErr = CE_Failure;
1672 : }
1673 :
1674 713560 : for( i = 0; i < nBandCount && eErr == CE_None; i++ )
1675 : {
1676 366182 : if( panBandMap[i] < 1 || panBandMap[i] > GetRasterCount() )
1677 : {
1678 : CPLError( CE_Failure, CPLE_IllegalArg,
1679 : "panBandMap[%d] = %d, this band does not exist on dataset.",
1680 0 : i, panBandMap[i] );
1681 0 : eErr = CE_Failure;
1682 : }
1683 :
1684 366182 : if( eErr == CE_None && GetRasterBand( panBandMap[i] ) == NULL )
1685 : {
1686 : CPLError( CE_Failure, CPLE_IllegalArg,
1687 : "panBandMap[%d]=%d, this band should exist but is NULL!",
1688 0 : i, panBandMap[i] );
1689 0 : eErr = CE_Failure;
1690 : }
1691 : }
1692 :
1693 : /* -------------------------------------------------------------------- */
1694 : /* We are being forced to use cached IO instead of a driver */
1695 : /* specific implementation. */
1696 : /* -------------------------------------------------------------------- */
1697 347378 : if( bForceCachedIO )
1698 : {
1699 : eErr =
1700 : BlockBasedRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1701 : pData, nBufXSize, nBufYSize, eBufType,
1702 : nBandCount, panBandMap,
1703 6 : nPixelSpace, nLineSpace, nBandSpace );
1704 : }
1705 :
1706 : /* -------------------------------------------------------------------- */
1707 : /* Call the format specific function. */
1708 : /* -------------------------------------------------------------------- */
1709 347372 : else if( eErr == CE_None )
1710 : {
1711 : eErr =
1712 : IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1713 : pData, nBufXSize, nBufYSize, eBufType,
1714 : nBandCount, panBandMap,
1715 347372 : nPixelSpace, nLineSpace, nBandSpace );
1716 : }
1717 :
1718 : /* -------------------------------------------------------------------- */
1719 : /* Cleanup */
1720 : /* -------------------------------------------------------------------- */
1721 347378 : if( bNeedToFreeBandMap )
1722 8492 : CPLFree( panBandMap );
1723 :
1724 347378 : return eErr;
1725 : }
1726 :
1727 : /************************************************************************/
1728 : /* GDALDatasetRasterIO() */
1729 : /************************************************************************/
1730 :
1731 : /**
1732 : * \brief Read/write a region of image data from multiple bands.
1733 : *
1734 : * @see GDALDataset::RasterIO()
1735 : */
1736 :
1737 : CPLErr CPL_STDCALL
1738 337158 : GDALDatasetRasterIO( GDALDatasetH hDS, GDALRWFlag eRWFlag,
1739 : int nXOff, int nYOff, int nXSize, int nYSize,
1740 : void * pData, int nBufXSize, int nBufYSize,
1741 : GDALDataType eBufType,
1742 : int nBandCount, int *panBandMap,
1743 : int nPixelSpace, int nLineSpace, int nBandSpace )
1744 :
1745 : {
1746 337158 : VALIDATE_POINTER1( hDS, "GDALDatasetRasterIO", CE_Failure );
1747 :
1748 337158 : GDALDataset *poDS = (GDALDataset *) hDS;
1749 :
1750 : return( poDS->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
1751 : pData, nBufXSize, nBufYSize, eBufType,
1752 : nBandCount, panBandMap,
1753 337158 : nPixelSpace, nLineSpace, nBandSpace ) );
1754 : }
1755 :
1756 : /************************************************************************/
1757 : /* GetOpenDatasets() */
1758 : /************************************************************************/
1759 :
1760 0 : static int GDALGetOpenDatasetsForeach(void* elt, void* user_data)
1761 : {
1762 0 : int* pnIndex = (int*) user_data;
1763 0 : ppDatasets[*pnIndex] = (GDALDataset*) elt;
1764 :
1765 0 : (*pnIndex) ++;
1766 :
1767 0 : return TRUE;
1768 : }
1769 :
1770 : /**
1771 : * \brief Fetch all open GDAL dataset handles.
1772 : *
1773 : * This method is the same as the C function GDALGetOpenDatasets().
1774 : *
1775 : * NOTE: This method is not thread safe. The returned list may changed
1776 : * at any time.
1777 : *
1778 : * @param pnCount integer into which to place the count of dataset pointers
1779 : * being returned.
1780 : *
1781 : * @return a pointer to an array of dataset handles.
1782 : */
1783 :
1784 0 : GDALDataset **GDALDataset::GetOpenDatasets( int *pnCount )
1785 :
1786 : {
1787 0 : CPLMutexHolderD( &hDLMutex );
1788 :
1789 0 : if (phAllDatasetSet != NULL)
1790 : {
1791 0 : int nIndex = 0;
1792 0 : *pnCount = CPLHashSetSize(phAllDatasetSet);
1793 0 : ppDatasets = (GDALDataset**) CPLRealloc(ppDatasets, (*pnCount) * sizeof(GDALDataset*));
1794 0 : CPLHashSetForeach(phAllDatasetSet, GDALGetOpenDatasetsForeach, &nIndex);
1795 0 : return ppDatasets;
1796 : }
1797 : else
1798 : {
1799 0 : *pnCount = 0;
1800 0 : return NULL;
1801 0 : }
1802 : }
1803 :
1804 : /************************************************************************/
1805 : /* GDALGetOpenDatasets() */
1806 : /************************************************************************/
1807 :
1808 : /**
1809 : * \brief Fetch all open GDAL dataset handles.
1810 : *
1811 : * @see GDALDataset::GetOpenDatasets()
1812 : */
1813 :
1814 0 : void CPL_STDCALL GDALGetOpenDatasets( GDALDatasetH **ppahDSList, int *pnCount )
1815 :
1816 : {
1817 0 : VALIDATE_POINTER0( ppahDSList, "GDALGetOpenDatasets" );
1818 0 : VALIDATE_POINTER0( pnCount, "GDALGetOpenDatasets" );
1819 :
1820 0 : *ppahDSList = (GDALDatasetH *) GDALDataset::GetOpenDatasets( pnCount);
1821 : }
1822 :
1823 : /************************************************************************/
1824 : /* GDALGetAccess() */
1825 : /************************************************************************/
1826 :
1827 : /**
1828 : * \brief Return access flag
1829 : *
1830 : * @see GDALDataset::GetAccess()
1831 : */
1832 :
1833 0 : int CPL_STDCALL GDALGetAccess( GDALDatasetH hDS )
1834 : {
1835 0 : VALIDATE_POINTER1( hDS, "GDALGetAccess", 0 );
1836 :
1837 0 : return ((GDALDataset *) hDS)->GetAccess();
1838 : }
1839 :
1840 : /************************************************************************/
1841 : /* AdviseRead() */
1842 : /************************************************************************/
1843 :
1844 : /**
1845 : * \brief Advise driver of upcoming read requests.
1846 : *
1847 : * Some GDAL drivers operate more efficiently if they know in advance what
1848 : * set of upcoming read requests will be made. The AdviseRead() method allows
1849 : * an application to notify the driver of the region and bands of interest,
1850 : * and at what resolution the region will be read.
1851 : *
1852 : * Many drivers just ignore the AdviseRead() call, but it can dramatically
1853 : * accelerate access via some drivers.
1854 : *
1855 : * @param nXOff The pixel offset to the top left corner of the region
1856 : * of the band to be accessed. This would be zero to start from the left side.
1857 : *
1858 : * @param nYOff The line offset to the top left corner of the region
1859 : * of the band to be accessed. This would be zero to start from the top.
1860 : *
1861 : * @param nXSize The width of the region of the band to be accessed in pixels.
1862 : *
1863 : * @param nYSize The height of the region of the band to be accessed in lines.
1864 : *
1865 : * @param nBufXSize the width of the buffer image into which the desired region
1866 : * is to be read, or from which it is to be written.
1867 : *
1868 : * @param nBufYSize the height of the buffer image into which the desired
1869 : * region is to be read, or from which it is to be written.
1870 : *
1871 : * @param eBufType the type of the pixel values in the pData data buffer. The
1872 : * pixel values will automatically be translated to/from the GDALRasterBand
1873 : * data type as needed.
1874 : *
1875 : * @param nBandCount the number of bands being read or written.
1876 : *
1877 : * @param panBandMap the list of nBandCount band numbers being read/written.
1878 : * Note band numbers are 1 based. This may be NULL to select the first
1879 : * nBandCount bands.
1880 : *
1881 : * @param papszOptions a list of name=value strings with special control
1882 : * options. Normally this is NULL.
1883 : *
1884 : * @return CE_Failure if the request is invalid and CE_None if it works or
1885 : * is ignored.
1886 : */
1887 :
1888 0 : CPLErr GDALDataset::AdviseRead( int nXOff, int nYOff, int nXSize, int nYSize,
1889 : int nBufXSize, int nBufYSize,
1890 : GDALDataType eDT,
1891 : int nBandCount, int *panBandMap,
1892 : char **papszOptions )
1893 :
1894 : {
1895 : int iBand;
1896 :
1897 0 : for( iBand = 0; iBand < nBandCount; iBand++ )
1898 : {
1899 : CPLErr eErr;
1900 : GDALRasterBand *poBand;
1901 :
1902 0 : if( panBandMap == NULL )
1903 0 : poBand = GetRasterBand(iBand+1);
1904 : else
1905 0 : poBand = GetRasterBand(panBandMap[iBand]);
1906 :
1907 : eErr = poBand->AdviseRead( nXOff, nYOff, nXSize, nYSize,
1908 0 : nBufXSize, nBufYSize, eDT, papszOptions );
1909 :
1910 0 : if( eErr != CE_None )
1911 0 : return eErr;
1912 : }
1913 :
1914 0 : return CE_None;
1915 : }
1916 :
1917 : /************************************************************************/
1918 : /* GDALDatasetAdviseRead() */
1919 : /************************************************************************/
1920 :
1921 : /**
1922 : * \brief Advise driver of upcoming read requests.
1923 : *
1924 : * @see GDALDataset::AdviseRead()
1925 : */
1926 : CPLErr CPL_STDCALL
1927 0 : GDALDatasetAdviseRead( GDALDatasetH hDS,
1928 : int nXOff, int nYOff, int nXSize, int nYSize,
1929 : int nBufXSize, int nBufYSize, GDALDataType eDT,
1930 : int nBandCount, int *panBandMap,char **papszOptions )
1931 :
1932 : {
1933 0 : VALIDATE_POINTER1( hDS, "GDALDatasetAdviseRead", CE_Failure );
1934 :
1935 : return ((GDALDataset *) hDS)->AdviseRead( nXOff, nYOff, nXSize, nYSize,
1936 : nBufXSize, nBufYSize, eDT,
1937 : nBandCount, panBandMap,
1938 0 : papszOptions );
1939 : }
1940 :
1941 : /************************************************************************/
1942 : /* GetFileList() */
1943 : /************************************************************************/
1944 :
1945 : /**
1946 : * \brief Fetch files forming dataset.
1947 : *
1948 : * Returns a list of files believed to be part of this dataset. If it returns
1949 : * an empty list of files it means there is believed to be no local file
1950 : * system files associated with the dataset (for instance a virtual dataset).
1951 : * The returned file list is owned by the caller and should be deallocated
1952 : * with CSLDestroy().
1953 : *
1954 : * The returned filenames will normally be relative or absolute paths
1955 : * depending on the path used to originally open the dataset.
1956 : *
1957 : * This method is the same as the C GDALGetFileList() function.
1958 : *
1959 : * @return NULL or a NULL terminated array of file names.
1960 : */
1961 :
1962 1130 : char **GDALDataset::GetFileList()
1963 :
1964 : {
1965 1130 : CPLString osMainFilename = GetDescription();
1966 : int bMainFileReal;
1967 : VSIStatBufL sStat;
1968 :
1969 : /* -------------------------------------------------------------------- */
1970 : /* Is the main filename even a real filesystem object? */
1971 : /* -------------------------------------------------------------------- */
1972 1130 : bMainFileReal = VSIStatL( osMainFilename, &sStat ) == 0;
1973 :
1974 : /* -------------------------------------------------------------------- */
1975 : /* Form new list. */
1976 : /* -------------------------------------------------------------------- */
1977 1130 : char **papszList = NULL;
1978 :
1979 1130 : if( bMainFileReal )
1980 1025 : papszList = CSLAddString( papszList, osMainFilename );
1981 :
1982 : /* -------------------------------------------------------------------- */
1983 : /* Do we have a known overview file? */
1984 : /* -------------------------------------------------------------------- */
1985 1130 : if( oOvManager.IsInitialized() && oOvManager.poODS != NULL )
1986 : {
1987 24 : char **papszOvrList = oOvManager.poODS->GetFileList();
1988 24 : papszList = CSLInsertStrings( papszList, -1, papszOvrList );
1989 24 : CSLDestroy( papszOvrList );
1990 : }
1991 :
1992 : /* -------------------------------------------------------------------- */
1993 : /* Do we have a known overview file? */
1994 : /* -------------------------------------------------------------------- */
1995 1130 : if( oOvManager.HaveMaskFile() )
1996 : {
1997 3 : char **papszMskList = oOvManager.poMaskDS->GetFileList();
1998 3 : papszList = CSLInsertStrings( papszList, -1, papszMskList );
1999 3 : CSLDestroy( papszMskList );
2000 : }
2001 :
2002 : /* -------------------------------------------------------------------- */
2003 : /* Do we have a world file? */
2004 : /* -------------------------------------------------------------------- */
2005 1130 : if( bMainFileReal )
2006 : {
2007 1025 : const char* pszExtension = CPLGetExtension( osMainFilename );
2008 1025 : if( strlen(pszExtension) > 2 )
2009 : {
2010 : // first + last + 'w'
2011 : char szDerivedExtension[4];
2012 1015 : szDerivedExtension[0] = pszExtension[0];
2013 1015 : szDerivedExtension[1] = pszExtension[strlen(pszExtension)-1];
2014 1015 : szDerivedExtension[2] = 'w';
2015 1015 : szDerivedExtension[3] = '\0';
2016 1015 : CPLString osWorldFilename = CPLResetExtension( osMainFilename, szDerivedExtension );
2017 :
2018 1015 : if( VSIStatL( osWorldFilename, &sStat ) == 0 )
2019 2 : papszList = CSLAddString( papszList, osWorldFilename );
2020 : }
2021 : }
2022 :
2023 1130 : return papszList;
2024 : }
2025 :
2026 : /************************************************************************/
2027 : /* GDALGetFileList() */
2028 : /************************************************************************/
2029 :
2030 : /**
2031 : * \brief Fetch files forming dataset.
2032 : *
2033 : * @see GDALDataset::GetFileList()
2034 : */
2035 :
2036 1094 : char ** CPL_STDCALL GDALGetFileList( GDALDatasetH hDS )
2037 :
2038 : {
2039 1094 : VALIDATE_POINTER1( hDS, "GDALGetFileList", NULL );
2040 :
2041 1094 : return ((GDALDataset *) hDS)->GetFileList();
2042 : }
2043 :
2044 : /************************************************************************/
2045 : /* CreateMaskBand() */
2046 : /************************************************************************/
2047 :
2048 : /**
2049 : * \brief Adds a mask band to the dataset
2050 : *
2051 : * The default implementation of the CreateMaskBand() method is implemented
2052 : * based on similar rules to the .ovr handling implemented using the
2053 : * GDALDefaultOverviews object. A TIFF file with the extension .msk will
2054 : * be created with the same basename as the original file, and it will have
2055 : * one band.
2056 : * The mask images will be deflate compressed tiled images with the same
2057 : * block size as the original image if possible.
2058 : *
2059 : * @since GDAL 1.5.0
2060 : *
2061 : * @param nFlags ignored. GMF_PER_DATASET will be assumed.
2062 : * @return CE_None on success or CE_Failure on an error.
2063 : *
2064 : * @see http://trac.osgeo.org/gdal/wiki/rfc15_nodatabitmask
2065 : *
2066 : */
2067 2 : CPLErr GDALDataset::CreateMaskBand( int nFlags )
2068 :
2069 : {
2070 2 : if( oOvManager.IsInitialized() )
2071 2 : return oOvManager.CreateMaskBand( nFlags, -1 );
2072 :
2073 : CPLError( CE_Failure, CPLE_NotSupported,
2074 0 : "CreateMaskBand() not supported for this dataset." );
2075 :
2076 0 : return( CE_Failure );
2077 : }
2078 :
2079 : /************************************************************************/
2080 : /* GDALCreateDatasetMaskBand() */
2081 : /************************************************************************/
2082 :
2083 : /**
2084 : * \brief Adds a mask band to the dataset
2085 : * @see GDALDataset::CreateMaskBand()
2086 : */
2087 6 : CPLErr CPL_STDCALL GDALCreateDatasetMaskBand( GDALDatasetH hDS, int nFlags )
2088 :
2089 : {
2090 6 : VALIDATE_POINTER1( hDS, "GDALCreateDatasetMaskBand", CE_Failure );
2091 :
2092 6 : return ((GDALDataset *) hDS)->CreateMaskBand( nFlags );
2093 : }
2094 :
2095 : /************************************************************************/
2096 : /* GDALOpen() */
2097 : /************************************************************************/
2098 :
2099 : /**
2100 : * \brief Open a raster file as a GDALDataset.
2101 : *
2102 : * This function will try to open the passed file, or virtual dataset
2103 : * name by invoking the Open method of each registered GDALDriver in turn.
2104 : * The first successful open will result in a returned dataset. If all
2105 : * drivers fail then NULL is returned.
2106 : *
2107 : * Several recommandations :
2108 : * <ul>
2109 : * <li>If you open a dataset object with GA_Update access, it is not recommanded
2110 : * to open a new dataset on the same underlying file.</li>
2111 : * <li>The returned dataset should only be accessed by one thread at a time. If you
2112 : * want to use it from different threads, you must add all necessary code (mutexes, etc.)
2113 : * to avoid concurrent use of the object. (Some drivers, such as GeoTIFF, maintain internal
2114 : * state variables that are updated each time a new block is read, thus preventing concurrent
2115 : * use.) </li>
2116 : * </ul>
2117 : *
2118 : * \sa GDALOpenShared()
2119 : *
2120 : * @param pszFilename the name of the file to access. In the case of
2121 : * exotic drivers this may not refer to a physical file, but instead contain
2122 : * information for the driver on how to access a dataset.
2123 : *
2124 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
2125 : * drivers support only read only access.
2126 : *
2127 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
2128 : * this handle can be cast to a GDALDataset *.
2129 : */
2130 :
2131 : GDALDatasetH CPL_STDCALL
2132 5609 : GDALOpen( const char * pszFilename, GDALAccess eAccess )
2133 :
2134 : {
2135 5609 : VALIDATE_POINTER1( pszFilename, "GDALOpen", NULL );
2136 :
2137 : int iDriver;
2138 5609 : GDALDriverManager *poDM = GetGDALDriverManager();
2139 5609 : GDALOpenInfo oOpenInfo( pszFilename, eAccess );
2140 5609 : CPLLocaleC oLocaleForcer;
2141 :
2142 5609 : CPLErrorReset();
2143 : CPLAssert( NULL != poDM );
2144 :
2145 144805 : for( iDriver = 0; iDriver < poDM->GetDriverCount(); iDriver++ )
2146 : {
2147 144257 : GDALDriver *poDriver = poDM->GetDriver( iDriver );
2148 : GDALDataset *poDS;
2149 :
2150 144257 : if ( poDriver->pfnOpen == NULL )
2151 0 : continue;
2152 :
2153 144257 : poDS = poDriver->pfnOpen( &oOpenInfo );
2154 144257 : if( poDS != NULL )
2155 : {
2156 5046 : if( strlen(poDS->GetDescription()) == 0 )
2157 388 : poDS->SetDescription( pszFilename );
2158 :
2159 5046 : if( poDS->poDriver == NULL )
2160 4480 : poDS->poDriver = poDriver;
2161 :
2162 :
2163 5046 : if( CPLGetPID() != GDALGetResponsiblePIDForCurrentThread() )
2164 : CPLDebug( "GDAL", "GDALOpen(%s, this=%p) succeeds as %s (pid=%d, responsiblePID=%d).",
2165 0 : pszFilename, poDS, poDriver->GetDescription(),
2166 0 : (int)CPLGetPID(), (int)GDALGetResponsiblePIDForCurrentThread() );
2167 : else
2168 : CPLDebug( "GDAL", "GDALOpen(%s, this=%p) succeeds as %s.",
2169 5046 : pszFilename, poDS, poDriver->GetDescription() );
2170 :
2171 5046 : return (GDALDatasetH) poDS;
2172 : }
2173 :
2174 139211 : if( CPLGetLastErrorNo() != 0 )
2175 15 : return NULL;
2176 : }
2177 :
2178 548 : if( oOpenInfo.bStatOK )
2179 : CPLError( CE_Failure, CPLE_OpenFailed,
2180 : "`%s' not recognised as a supported file format.\n",
2181 43 : pszFilename );
2182 : else
2183 : CPLError( CE_Failure, CPLE_OpenFailed,
2184 : "`%s' does not exist in the file system,\n"
2185 : "and is not recognised as a supported dataset name.\n",
2186 505 : pszFilename );
2187 :
2188 548 : return NULL;
2189 : }
2190 :
2191 : /************************************************************************/
2192 : /* GDALOpenShared() */
2193 : /************************************************************************/
2194 :
2195 : /**
2196 : * \brief Open a raster file as a GDALDataset.
2197 : *
2198 : * This function works the same as GDALOpen(), but allows the sharing of
2199 : * GDALDataset handles for a dataset with other callers to GDALOpenShared().
2200 : *
2201 : * In particular, GDALOpenShared() will first consult it's list of currently
2202 : * open and shared GDALDataset's, and if the GetDescription() name for one
2203 : * exactly matches the pszFilename passed to GDALOpenShared() it will be
2204 : * referenced and returned.
2205 : *
2206 : * Starting with GDAL 1.6.0, if GDALOpenShared() is called on the same pszFilename
2207 : * from two different threads, a different GDALDataset object will be returned as
2208 : * it is not safe to use the same dataset from different threads, unless the user
2209 : * does explicitely use mutexes in its code.
2210 : *
2211 : * \sa GDALOpen()
2212 : *
2213 : * @param pszFilename the name of the file to access. In the case of
2214 : * exotic drivers this may not refer to a physical file, but instead contain
2215 : * information for the driver on how to access a dataset.
2216 : *
2217 : * @param eAccess the desired access, either GA_Update or GA_ReadOnly. Many
2218 : * drivers support only read only access.
2219 : *
2220 : * @return A GDALDatasetH handle or NULL on failure. For C++ applications
2221 : * this handle can be cast to a GDALDataset *.
2222 : */
2223 :
2224 : GDALDatasetH CPL_STDCALL
2225 5190 : GDALOpenShared( const char *pszFilename, GDALAccess eAccess )
2226 :
2227 : {
2228 5190 : VALIDATE_POINTER1( pszFilename, "GDALOpenShared", NULL );
2229 :
2230 : /* -------------------------------------------------------------------- */
2231 : /* First scan the existing list to see if it could already */
2232 : /* contain the requested dataset. */
2233 : /* -------------------------------------------------------------------- */
2234 : {
2235 5190 : CPLMutexHolderD( &hDLMutex );
2236 :
2237 5190 : if (phSharedDatasetSet != NULL)
2238 : {
2239 5095 : GIntBig nThisPID = GDALGetResponsiblePIDForCurrentThread();
2240 : SharedDatasetCtxt* psStruct;
2241 : SharedDatasetCtxt sStruct;
2242 :
2243 5095 : sStruct.nPID = nThisPID;
2244 5095 : sStruct.pszDescription = (char*) pszFilename;
2245 5095 : sStruct.eAccess = eAccess;
2246 5095 : psStruct = (SharedDatasetCtxt*) CPLHashSetLookup(phSharedDatasetSet, &sStruct);
2247 5095 : if (psStruct == NULL && eAccess == GA_ReadOnly)
2248 : {
2249 47 : sStruct.eAccess = GA_Update;
2250 47 : psStruct = (SharedDatasetCtxt*) CPLHashSetLookup(phSharedDatasetSet, &sStruct);
2251 : }
2252 5095 : if (psStruct)
2253 : {
2254 5048 : psStruct->poDS->Reference();
2255 5048 : return psStruct->poDS;
2256 : }
2257 0 : }
2258 : }
2259 :
2260 : /* -------------------------------------------------------------------- */
2261 : /* Try opening the the requested dataset. */
2262 : /* -------------------------------------------------------------------- */
2263 : GDALDataset *poDataset;
2264 :
2265 142 : poDataset = (GDALDataset *) GDALOpen( pszFilename, eAccess );
2266 142 : if( poDataset != NULL )
2267 : {
2268 141 : if (strcmp(pszFilename, poDataset->GetDescription()) != 0)
2269 : {
2270 : CPLError(CE_Warning, CPLE_NotSupported,
2271 : "A dataset opened by GDALOpenShared should have the same filename (%s) "
2272 : "and description (%s)",
2273 2 : pszFilename, poDataset->GetDescription());
2274 : }
2275 : else
2276 : {
2277 139 : poDataset->MarkAsShared();
2278 : }
2279 : }
2280 :
2281 142 : return (GDALDatasetH) poDataset;
2282 : }
2283 :
2284 : /************************************************************************/
2285 : /* GDALClose() */
2286 : /************************************************************************/
2287 :
2288 : /**
2289 : * \brief Close GDAL dataset.
2290 : *
2291 : * For non-shared datasets (opened with GDALOpen()) the dataset is closed
2292 : * using the C++ "delete" operator, recovering all dataset related resources.
2293 : * For shared datasets (opened with GDALOpenShared()) the dataset is
2294 : * dereferenced, and closed only if the referenced count has dropped below 1.
2295 : *
2296 : * @param hDS The dataset to close. May be cast from a "GDALDataset *".
2297 : */
2298 :
2299 11051 : void CPL_STDCALL GDALClose( GDALDatasetH hDS )
2300 :
2301 : {
2302 11051 : VALIDATE_POINTER0( hDS, "GDALClose" );
2303 :
2304 11051 : GDALDataset *poDS = (GDALDataset *) hDS;
2305 11051 : CPLMutexHolderD( &hDLMutex );
2306 11051 : CPLLocaleC oLocaleForcer;
2307 :
2308 11051 : if (poDS->GetShared())
2309 : {
2310 : /* -------------------------------------------------------------------- */
2311 : /* If this file is in the shared dataset list then dereference */
2312 : /* it, and only delete/remote it if the reference count has */
2313 : /* dropped to zero. */
2314 : /* -------------------------------------------------------------------- */
2315 354 : if( poDS->Dereference() > 0 )
2316 : return;
2317 :
2318 269 : delete poDS;
2319 : return;
2320 : }
2321 :
2322 : /* -------------------------------------------------------------------- */
2323 : /* This is not shared dataset, so directly delete it. */
2324 : /* -------------------------------------------------------------------- */
2325 10697 : delete poDS;
2326 : }
2327 :
2328 : /************************************************************************/
2329 : /* GDALDumpOpenDataset() */
2330 : /************************************************************************/
2331 :
2332 0 : static int GDALDumpOpenSharedDatasetsForeach(void* elt, void* user_data)
2333 : {
2334 0 : SharedDatasetCtxt* psStruct = (SharedDatasetCtxt*) elt;
2335 0 : FILE *fp = (FILE*) user_data;
2336 : const char *pszDriverName;
2337 0 : GDALDataset *poDS = psStruct->poDS;
2338 :
2339 0 : if( poDS->GetDriver() == NULL )
2340 0 : pszDriverName = "DriverIsNULL";
2341 : else
2342 0 : pszDriverName = poDS->GetDriver()->GetDescription();
2343 :
2344 0 : poDS->Reference();
2345 : VSIFPrintf( fp, " %d %c %-6s %7d %dx%dx%d %s\n",
2346 : poDS->Dereference(),
2347 : poDS->GetShared() ? 'S' : 'N',
2348 : pszDriverName,
2349 : (int)psStruct->nPID,
2350 : poDS->GetRasterXSize(),
2351 : poDS->GetRasterYSize(),
2352 : poDS->GetRasterCount(),
2353 0 : poDS->GetDescription() );
2354 :
2355 0 : return TRUE;
2356 : }
2357 :
2358 :
2359 0 : static int GDALDumpOpenDatasetsForeach(void* elt, void* user_data)
2360 : {
2361 0 : DatasetCtxt* psStruct = (DatasetCtxt*) elt;
2362 0 : FILE *fp = (FILE*) user_data;
2363 : const char *pszDriverName;
2364 0 : GDALDataset *poDS = psStruct->poDS;
2365 :
2366 : /* Don't list shared datasets. They have already been listed by */
2367 : /* GDALDumpOpenSharedDatasetsForeach */
2368 0 : if (poDS->GetShared())
2369 0 : return TRUE;
2370 :
2371 0 : if( poDS->GetDriver() == NULL )
2372 0 : pszDriverName = "DriverIsNULL";
2373 : else
2374 0 : pszDriverName = poDS->GetDriver()->GetDescription();
2375 :
2376 0 : poDS->Reference();
2377 : VSIFPrintf( fp, " %d %c %-6s %7d %dx%dx%d %s\n",
2378 : poDS->Dereference(),
2379 : poDS->GetShared() ? 'S' : 'N',
2380 : pszDriverName,
2381 : -1,
2382 : poDS->GetRasterXSize(),
2383 : poDS->GetRasterYSize(),
2384 : poDS->GetRasterCount(),
2385 0 : poDS->GetDescription() );
2386 :
2387 0 : return TRUE;
2388 : }
2389 :
2390 : /**
2391 : * \brief List open datasets.
2392 : *
2393 : * Dumps a list of all open datasets (shared or not) to the indicated
2394 : * text file (may be stdout or stderr). This function is primariliy intended
2395 : * to assist in debugging "dataset leaks" and reference counting issues.
2396 : * The information reported includes the dataset name, referenced count,
2397 : * shared status, driver name, size, and band count.
2398 : */
2399 :
2400 300 : int CPL_STDCALL GDALDumpOpenDatasets( FILE *fp )
2401 :
2402 : {
2403 300 : VALIDATE_POINTER1( fp, "GDALDumpOpenDatasets", 0 );
2404 :
2405 300 : CPLMutexHolderD( &hDLMutex );
2406 :
2407 300 : if (phAllDatasetSet != NULL)
2408 : {
2409 0 : VSIFPrintf( fp, "Open GDAL Datasets:\n" );
2410 0 : CPLHashSetForeach(phAllDatasetSet, GDALDumpOpenDatasetsForeach, fp);
2411 0 : if (phSharedDatasetSet != NULL)
2412 : {
2413 0 : CPLHashSetForeach(phSharedDatasetSet, GDALDumpOpenSharedDatasetsForeach, fp);
2414 : }
2415 0 : return CPLHashSetSize(phAllDatasetSet);
2416 : }
2417 : else
2418 : {
2419 300 : return 0;
2420 0 : }
2421 : }
2422 :
|