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