00001 /******************************************************************************
00002 * $Id: gdaldriver_cpp-source.html,v 1.13 2002/12/21 19:13:12 warmerda Exp $
00003 *
00004 * Project: GDAL Core
00005 * Purpose: Implementation of GDALDriver class (and C wrappers)
00006 * Author: Frank Warmerdam, warmerda@home.com
00007 *
00008 ******************************************************************************
00009 * Copyright (c) 1998, 2000, Frank Warmerdam
00010 *
00011 * Permission is hereby granted, free of charge, to any person obtaining a
00012 * copy of this software and associated documentation files (the "Software"),
00013 * to deal in the Software without restriction, including without limitation
00014 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00015 * and/or sell copies of the Software, and to permit persons to whom the
00016 * Software is furnished to do so, subject to the following conditions:
00017 *
00018 * The above copyright notice and this permission notice shall be included
00019 * in all copies or substantial portions of the Software.
00020 *
00021 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00022 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00023 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00024 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00025 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00026 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00027 * DEALINGS IN THE SOFTWARE.
00028 ******************************************************************************
00029 *
00030 * $Log: gdaldriver_cpp-source.html,v $
00030 * Revision 1.13 2002/12/21 19:13:12 warmerda
00030 * updated
00030 *
00031 * Revision 1.28 2002/09/11 14:17:23 warmerda
00032 * copy ct/metadata/description for bands in CreateCopy()
00033 *
00034 * Revision 1.27 2002/09/06 01:28:30 warmerda
00035 * fixed logic for setting descriptions in created files
00036 *
00037 * Revision 1.26 2002/09/04 06:52:05 warmerda
00038 * added unload driver support to GDALDriver
00039 *
00040 * Revision 1.25 2002/07/09 20:33:12 warmerda
00041 * expand tabs
00042 *
00043 * Revision 1.24 2002/06/12 21:13:27 warmerda
00044 * use metadata based driver info
00045 *
00046 * Revision 1.23 2001/12/15 15:47:54 warmerda
00047 * don't replace existing descriptions
00048 *
00049 * Revision 1.22 2001/12/15 15:42:27 warmerda
00050 * *** empty log message ***
00051 *
00052 * Revision 1.21 2001/10/05 20:35:26 warmerda
00053 * CreateCopy() won't try to write default geotransform
00054 *
00055 * Revision 1.20 2001/09/24 15:58:27 warmerda
00056 * improved progress reporting in createcopy
00057 *
00058 * Revision 1.19 2001/07/18 04:04:30 warmerda
00059 * added CPL_CVSID
00060 *
00061 * Revision 1.18 2001/02/15 16:30:34 warmerda
00062 * added create debug message
00063 *
00064 * Revision 1.17 2000/10/06 15:26:49 warmerda
00065 * make buffer size for copying image data the exact size, fixing bug with complex data
00066 *
00067 * Revision 1.16 2000/07/13 17:34:11 warmerda
00068 * Set description for CopyCreate() method.
00069 *
00070 * Revision 1.15 2000/07/13 17:27:48 warmerda
00071 * added SetDescription after create
00072 *
00073 * Revision 1.14 2000/06/27 16:47:28 warmerda
00074 * added cancel support for CopyCreate progress func
00075 *
00076 * Revision 1.13 2000/06/26 18:47:14 warmerda
00077 * Ensure pszHelpTopic is initialized
00078 *
00079 * Revision 1.12 2000/04/30 23:22:16 warmerda
00080 * added CreateCopy support
00081 *
00082 * Revision 1.11 2000/03/06 02:21:15 warmerda
00083 * Added help topic C function
00084 *
00085 * Revision 1.10 2000/01/31 16:24:01 warmerda
00086 * use failure, not fatal
00087 *
00088 * Revision 1.9 2000/01/31 15:00:25 warmerda
00089 * added some documentation
00090 *
00091 * Revision 1.8 2000/01/31 14:24:36 warmerda
00092 * implemented dataset delete
00093 *
00094 * Revision 1.7 2000/01/13 04:13:10 pgs
00095 * added initialization of pfnCreate = NULL to prevent run-time crash when format doesn't support creating a file
00096 *
00097 * Revision 1.6 1999/12/08 14:40:50 warmerda
00098 * Fixed error message.
00099 *
00100 * Revision 1.5 1999/10/21 13:22:10 warmerda
00101 * Added GDALGetDriverShort/LongName().
00102 *
00103 * Revision 1.4 1999/01/11 15:36:50 warmerda
00104 * Added GDALCreate()
00105 *
00106 * Revision 1.3 1998/12/31 18:54:53 warmerda
00107 * Flesh out create method.
00108 *
00109 * Revision 1.2 1998/12/06 22:17:32 warmerda
00110 * Add stub Create() method
00111 *
00112 * Revision 1.1 1998/12/03 18:32:01 warmerda
00113 * New
00114 *
00115 */
00116
00117 #include "gdal_priv.h"
00118
00119 CPL_CVSID("$Id: gdaldriver_cpp-source.html,v 1.13 2002/12/21 19:13:12 warmerda Exp $");
00120
00121 /************************************************************************/
00122 /* GDALDriver() */
00123 /************************************************************************/
00124
00125 GDALDriver::GDALDriver()
00126
00127 {
00128 pfnOpen = NULL;
00129 pfnCreate = NULL;
00130 pfnDelete = NULL;
00131 pfnCreateCopy = NULL;
00132 pfnUnloadDriver = NULL;
00133 pDriverData = NULL;
00134 }
00135
00136 /************************************************************************/
00137 /* ~GDALDriver() */
00138 /************************************************************************/
00139
00140 GDALDriver::~GDALDriver()
00141
00142 {
00143 if( pfnUnloadDriver != NULL )
00144 pfnUnloadDriver( this );
00145 }
00146
00147 /************************************************************************/
00148 /* Create() */
00149 /************************************************************************/
00150
00169 GDALDataset * GDALDriver::Create( const char * pszFilename,
00170 int nXSize, int nYSize, int nBands,
00171 GDALDataType eType, char ** papszParmList )
00172
00173 {
00174 /* notdef: should add a bunch of error checking here */
00175
00176 if( pfnCreate == NULL )
00177 {
00178 CPLError( CE_Failure, CPLE_NotSupported,
00179 "GDALDriver::Create() ... no create method implemented"
00180 " for this format.\n" );
00181
00182 return NULL;
00183 }
00184 else
00185 {
00186 GDALDataset *poDS;
00187
00188 CPLDebug( "GDAL", "GDALDriver::Create(%s,%s,%d,%d,%d,%s,%p)",
00189 GetDescription(), pszFilename, nXSize, nYSize, nBands,
00190 GDALGetDataTypeName( eType ),
00191 papszParmList );
00192
00193 poDS = pfnCreate( pszFilename, nXSize, nYSize, nBands, eType,
00194 papszParmList );
00195
00196 if( poDS != NULL )
00197 {
00198 if( poDS->GetDescription() == NULL
00199 || strlen(poDS->GetDescription()) == 0 )
00200 poDS->SetDescription( pszFilename );
00201
00202 if( poDS->poDriver == NULL )
00203 poDS->poDriver = this;
00204 }
00205
00206 return poDS;
00207 }
00208 }
00209
00210 /************************************************************************/
00211 /* GDALCreate() */
00212 /************************************************************************/
00213
00214 GDALDatasetH CPL_DLL GDALCreate( GDALDriverH hDriver,
00215 const char * pszFilename,
00216 int nXSize, int nYSize, int nBands,
00217 GDALDataType eBandType,
00218 char ** papszOptions )
00219
00220 {
00221 return( ((GDALDriver *) hDriver)->Create( pszFilename,
00222 nXSize, nYSize, nBands,
00223 eBandType, papszOptions ) );
00224 }
00225
00226 /************************************************************************/
00227 /* CreateCopy() */
00228 /************************************************************************/
00229
00263 GDALDataset *GDALDriver::CreateCopy( const char * pszFilename,
00264 GDALDataset * poSrcDS,
00265 int bStrict, char ** papszOptions,
00266 GDALProgressFunc pfnProgress,
00267 void * pProgressData )
00268
00269 {
00270 if( pfnProgress == NULL )
00271 pfnProgress = GDALDummyProgress;
00272
00273 /* -------------------------------------------------------------------- */
00274 /* If the format provides a CreateCopy() method use that, */
00275 /* otherwise fallback to the internal implementation using the */
00276 /* Create() method. */
00277 /* -------------------------------------------------------------------- */
00278 if( pfnCreateCopy != NULL )
00279 {
00280 GDALDataset *poDstDS;
00281
00282 poDstDS = pfnCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions,
00283 pfnProgress, pProgressData );
00284 if( poDstDS != NULL )
00285 {
00286 if( poDstDS->GetDescription() == NULL
00287 || strlen(poDstDS->GetDescription()) > 0 )
00288 poDstDS->SetDescription( pszFilename );
00289
00290 if( poDstDS->poDriver == NULL )
00291 poDstDS->poDriver = this;
00292 }
00293
00294 return poDstDS;
00295 }
00296
00297 /* -------------------------------------------------------------------- */
00298 /* Create destination dataset. */
00299 /* -------------------------------------------------------------------- */
00300 GDALDataset *poDstDS;
00301 int nXSize = poSrcDS->GetRasterXSize();
00302 int nYSize = poSrcDS->GetRasterYSize();
00303 GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
00304 CPLErr eErr;
00305
00306 CPLDebug( "GDAL", "Using default GDALDriver::CreateCopy implementation." );
00307
00308 if( !pfnProgress( 0.0, NULL, pProgressData ) )
00309 {
00310 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
00311 return NULL;
00312 }
00313
00314 poDstDS = Create( pszFilename, nXSize, nYSize,
00315 poSrcDS->GetRasterCount(), eType, papszOptions );
00316
00317 if( poDstDS == NULL )
00318 return NULL;
00319
00320 /* -------------------------------------------------------------------- */
00321 /* Try setting the projection and geotransform if it seems */
00322 /* suitable. For now we don't try and copy GCPs, though I */
00323 /* suppose we should. */
00324 /* -------------------------------------------------------------------- */
00325 double adfGeoTransform[6];
00326
00327 if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
00328 && (adfGeoTransform[0] != 0.0
00329 || adfGeoTransform[1] != 1.0
00330 || adfGeoTransform[2] != 0.0
00331 || adfGeoTransform[3] != 0.0
00332 || adfGeoTransform[4] != 0.0
00333 || adfGeoTransform[5] != 1.0) )
00334 {
00335 poDstDS->SetGeoTransform( adfGeoTransform );
00336 }
00337
00338 if( poSrcDS->GetProjectionRef() != NULL
00339 && strlen(poSrcDS->GetProjectionRef()) > 0 )
00340 {
00341 poDstDS->SetProjection( poSrcDS->GetProjectionRef() );
00342 }
00343
00344 /* -------------------------------------------------------------------- */
00345 /* Loop copying bands. */
00346 /* -------------------------------------------------------------------- */
00347 for( int iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ )
00348 {
00349 GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 );
00350 GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand+1 );
00351
00352 /* -------------------------------------------------------------------- */
00353 /* Do we need to copy a colortable or other metadata? */
00354 /* -------------------------------------------------------------------- */
00355 GDALColorTable *poCT;
00356
00357 poCT = poSrcBand->GetColorTable();
00358 if( poCT != NULL )
00359 poDstBand->SetColorTable( poCT );
00360
00361 if( strlen(poSrcBand->GetDescription()) > 0 )
00362 poDstBand->SetDescription( poSrcBand->GetDescription() );
00363
00364 poDstBand->SetMetadata( poSrcBand->GetMetadata() );
00365
00366 /* -------------------------------------------------------------------- */
00367 /* Copy image data. */
00368 /* -------------------------------------------------------------------- */
00369 void *pData;
00370
00371 pData = CPLMalloc(nXSize * GDALGetDataTypeSize(eType) / 8);
00372
00373 for( int iLine = 0; iLine < nYSize; iLine++ )
00374 {
00375 eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
00376 pData, nXSize, 1, eType, 0, 0 );
00377 if( eErr != CE_None )
00378 {
00379 return NULL;
00380 }
00381
00382 eErr = poDstBand->RasterIO( GF_Write, 0, iLine, nXSize, 1,
00383 pData, nXSize, 1, eType, 0, 0 );
00384
00385 if( eErr != CE_None )
00386 {
00387 return NULL;
00388 }
00389
00390 if( !pfnProgress( (iBand + (iLine+1) / (double) nYSize)
00391 / (double) poSrcDS->GetRasterCount(),
00392 NULL, pProgressData ) )
00393 {
00394 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
00395 delete poDstDS;
00396 Delete( pszFilename );
00397 return NULL;
00398 }
00399 }
00400
00401 CPLFree( pData );
00402 }
00403
00404 return poDstDS;
00405 }
00406
00407 /************************************************************************/
00408 /* GDALCreateCopy() */
00409 /************************************************************************/
00410
00411 GDALDatasetH GDALCreateCopy( GDALDriverH hDriver,
00412 const char * pszFilename,
00413 GDALDatasetH hSrcDS,
00414 int bStrict, char ** papszOptions,
00415 GDALProgressFunc pfnProgress,
00416 void * pProgressData )
00417
00418 {
00419 return (GDALDatasetH) ((GDALDriver *) hDriver)->
00420 CreateCopy( pszFilename, (GDALDataset *) hSrcDS, bStrict, papszOptions,
00421 pfnProgress, pProgressData );
00422 }
00423
00424 /************************************************************************/
00425 /* Delete() */
00426 /************************************************************************/
00427
00447 CPLErr GDALDriver::Delete( const char * pszFilename )
00448
00449 {
00450 if( pfnDelete != NULL )
00451 return pfnDelete( pszFilename );
00452 else
00453 {
00454 VSIStatBuf sStat;
00455
00456 if( VSIStat( pszFilename, &sStat ) == 0 && VSI_ISREG( sStat.st_mode ) )
00457 {
00458 if( VSIUnlink( pszFilename ) == 0 )
00459 return CE_None;
00460 else
00461 {
00462 CPLError( CE_Failure, CPLE_AppDefined,
00463 "%s: Attempt to unlink %s failed.\n",
00464 GetDescription(), pszFilename );
00465 return CE_Failure;
00466 }
00467 }
00468 else
00469 {
00470 CPLError( CE_Failure, CPLE_AppDefined,
00471 "%s: Unable to delete %s, not a file.\n",
00472 GetDescription(), pszFilename );
00473 return CE_Failure;
00474 }
00475 }
00476 }
00477
00478 /************************************************************************/
00479 /* GDALDelete() */
00480 /************************************************************************/
00481
00482 CPLErr GDALDeleteDataset( GDALDriverH hDriver, const char * pszFilename )
00483
00484 {
00485 return ((GDALDriver *) hDriver)->Delete( pszFilename );
00486 }
00487
00488 /************************************************************************/
00489 /* GDALGetDriverShortName() */
00490 /************************************************************************/
00491
00492 const char * GDALGetDriverShortName( GDALDriverH hDriver )
00493
00494 {
00495 if( hDriver == NULL )
00496 return NULL;
00497 else
00498 return ((GDALDriver *) hDriver)->GetDescription();
00499 }
00500
00501 /************************************************************************/
00502 /* GDALGetDriverLongName() */
00503 /************************************************************************/
00504
00505 const char * GDALGetDriverLongName( GDALDriverH hDriver )
00506
00507 {
00508 if( hDriver == NULL )
00509 return NULL;
00510
00511 const char *pszLongName =
00512 ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_LONGNAME );
00513
00514 if( pszLongName == NULL )
00515 return "";
00516 else
00517 return pszLongName;
00518 }
00519
00520 /************************************************************************/
00521 /* GDALGetDriverHelpTopic() */
00522 /************************************************************************/
00523
00524 const char * GDALGetDriverHelpTopic( GDALDriverH hDriver )
00525
00526 {
00527 if( hDriver == NULL )
00528 return NULL;
00529
00530 return ((GDALDriver *) hDriver)->GetMetadataItem( GDAL_DMD_HELPTOPIC );
00531 }
00532
1.2.3-20001105 written by Dimitri van Heesch,
© 1997-2000