00001 /****************************************************************************** 00002 * $Id: gdaldriver_cpp-source.html,v 1.10 2002/04/16 13:11:48 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.10 2002/04/16 13:11:48 warmerda 00030 * updated 00030 * 00031 * Revision 1.23 2001/12/15 15:47:54 warmerda 00032 * don't replace existing descriptions 00033 * 00034 * Revision 1.22 2001/12/15 15:42:27 warmerda 00035 * *** empty log message *** 00036 * 00037 * Revision 1.21 2001/10/05 20:35:26 warmerda 00038 * CreateCopy() won't try to write default geotransform 00039 * 00040 * Revision 1.20 2001/09/24 15:58:27 warmerda 00041 * improved progress reporting in createcopy 00042 * 00043 * Revision 1.19 2001/07/18 04:04:30 warmerda 00044 * added CPL_CVSID 00045 * 00046 * Revision 1.18 2001/02/15 16:30:34 warmerda 00047 * added create debug message 00048 * 00049 * Revision 1.17 2000/10/06 15:26:49 warmerda 00050 * make buffer size for copying image data the exact size, fixing bug with complex data 00051 * 00052 * Revision 1.16 2000/07/13 17:34:11 warmerda 00053 * Set description for CopyCreate() method. 00054 * 00055 * Revision 1.15 2000/07/13 17:27:48 warmerda 00056 * added SetDescription after create 00057 * 00058 * Revision 1.14 2000/06/27 16:47:28 warmerda 00059 * added cancel support for CopyCreate progress func 00060 * 00061 * Revision 1.13 2000/06/26 18:47:14 warmerda 00062 * Ensure pszHelpTopic is initialized 00063 * 00064 * Revision 1.12 2000/04/30 23:22:16 warmerda 00065 * added CreateCopy support 00066 * 00067 * Revision 1.11 2000/03/06 02:21:15 warmerda 00068 * Added help topic C function 00069 * 00070 * Revision 1.10 2000/01/31 16:24:01 warmerda 00071 * use failure, not fatal 00072 * 00073 * Revision 1.9 2000/01/31 15:00:25 warmerda 00074 * added some documentation 00075 * 00076 * Revision 1.8 2000/01/31 14:24:36 warmerda 00077 * implemented dataset delete 00078 * 00079 * Revision 1.7 2000/01/13 04:13:10 pgs 00080 * added initialization of pfnCreate = NULL to prevent run-time crash when format doesn't support creating a file 00081 * 00082 * Revision 1.6 1999/12/08 14:40:50 warmerda 00083 * Fixed error message. 00084 * 00085 * Revision 1.5 1999/10/21 13:22:10 warmerda 00086 * Added GDALGetDriverShort/LongName(). 00087 * 00088 * Revision 1.4 1999/01/11 15:36:50 warmerda 00089 * Added GDALCreate() 00090 * 00091 * Revision 1.3 1998/12/31 18:54:53 warmerda 00092 * Flesh out create method. 00093 * 00094 * Revision 1.2 1998/12/06 22:17:32 warmerda 00095 * Add stub Create() method 00096 * 00097 * Revision 1.1 1998/12/03 18:32:01 warmerda 00098 * New 00099 * 00100 */ 00101 00102 #include "gdal_priv.h" 00103 00104 CPL_CVSID("$Id: gdaldriver_cpp-source.html,v 1.10 2002/04/16 13:11:48 warmerda Exp $"); 00105 00106 /************************************************************************/ 00107 /* GDALDriver() */ 00108 /************************************************************************/ 00109 00110 GDALDriver::GDALDriver() 00111 00112 { 00113 pszShortName = NULL; 00114 pszLongName = NULL; 00115 pszHelpTopic = NULL; 00116 00117 pfnOpen = NULL; 00118 pfnCreate = NULL; 00119 pfnDelete = NULL; 00120 pfnCreateCopy = NULL; 00121 } 00122 00123 /************************************************************************/ 00124 /* ~GDALDriver() */ 00125 /************************************************************************/ 00126 00127 GDALDriver::~GDALDriver() 00128 00129 { 00130 } 00131 00132 /************************************************************************/ 00133 /* Create() */ 00134 /************************************************************************/ 00135 00154 GDALDataset * GDALDriver::Create( const char * pszFilename, 00155 int nXSize, int nYSize, int nBands, 00156 GDALDataType eType, char ** papszParmList ) 00157 00158 { 00159 /* notdef: should add a bunch of error checking here */ 00160 00161 if( pfnCreate == NULL ) 00162 { 00163 CPLError( CE_Failure, CPLE_NotSupported, 00164 "GDALDriver::Create() ... no create method implemented" 00165 " for this format.\n" ); 00166 00167 return NULL; 00168 } 00169 else 00170 { 00171 GDALDataset *poDS; 00172 00173 CPLDebug( "GDAL", "GDALDriver::Create(%s,%s,%d,%d,%d,%s,%p)", 00174 pszShortName, pszFilename, nXSize, nYSize, nBands, 00175 GDALGetDataTypeName( eType ), 00176 papszParmList ); 00177 00178 poDS = pfnCreate( pszFilename, nXSize, nYSize, nBands, eType, 00179 papszParmList ); 00180 00181 if( poDS != NULL ) 00182 { 00183 if( poDS->GetDescription() == NULL 00184 || strlen(poDS->GetDescription()) > 0 ) 00185 poDS->SetDescription( pszFilename ); 00186 00187 if( poDS->poDriver == NULL ) 00188 poDS->poDriver = this; 00189 } 00190 00191 return poDS; 00192 } 00193 } 00194 00195 /************************************************************************/ 00196 /* GDALCreate() */ 00197 /************************************************************************/ 00198 00199 GDALDatasetH CPL_DLL GDALCreate( GDALDriverH hDriver, 00200 const char * pszFilename, 00201 int nXSize, int nYSize, int nBands, 00202 GDALDataType eBandType, 00203 char ** papszOptions ) 00204 00205 { 00206 return( ((GDALDriver *) hDriver)->Create( pszFilename, 00207 nXSize, nYSize, nBands, 00208 eBandType, papszOptions ) ); 00209 } 00210 00211 /************************************************************************/ 00212 /* CreateCopy() */ 00213 /************************************************************************/ 00214 00248 GDALDataset *GDALDriver::CreateCopy( const char * pszFilename, 00249 GDALDataset * poSrcDS, 00250 int bStrict, char ** papszOptions, 00251 GDALProgressFunc pfnProgress, 00252 void * pProgressData ) 00253 00254 { 00255 if( pfnProgress == NULL ) 00256 pfnProgress = GDALDummyProgress; 00257 00258 /* -------------------------------------------------------------------- */ 00259 /* If the format provides a CreateCopy() method use that, */ 00260 /* otherwise fallback to the internal implementation using the */ 00261 /* Create() method. */ 00262 /* -------------------------------------------------------------------- */ 00263 if( pfnCreateCopy != NULL ) 00264 { 00265 GDALDataset *poDstDS; 00266 00267 poDstDS = pfnCreateCopy( pszFilename, poSrcDS, bStrict, papszOptions, 00268 pfnProgress, pProgressData ); 00269 if( poDstDS != NULL ) 00270 { 00271 if( poDstDS->GetDescription() == NULL 00272 || strlen(poDstDS->GetDescription()) > 0 ) 00273 poDstDS->SetDescription( pszFilename ); 00274 00275 if( poDstDS->poDriver == NULL ) 00276 poDstDS->poDriver = this; 00277 } 00278 00279 return poDstDS; 00280 } 00281 00282 /* -------------------------------------------------------------------- */ 00283 /* Create destination dataset. */ 00284 /* -------------------------------------------------------------------- */ 00285 GDALDataset *poDstDS; 00286 int nXSize = poSrcDS->GetRasterXSize(); 00287 int nYSize = poSrcDS->GetRasterYSize(); 00288 GDALDataType eType = poSrcDS->GetRasterBand(1)->GetRasterDataType(); 00289 CPLErr eErr; 00290 00291 CPLDebug( "GDAL", "Using default GDALDriver::CreateCopy implementation." ); 00292 00293 if( !pfnProgress( 0.0, NULL, pProgressData ) ) 00294 { 00295 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); 00296 return NULL; 00297 } 00298 00299 poDstDS = Create( pszFilename, nXSize, nYSize, 00300 poSrcDS->GetRasterCount(), eType, papszOptions ); 00301 00302 if( poDstDS == NULL ) 00303 return NULL; 00304 00305 /* -------------------------------------------------------------------- */ 00306 /* Try setting the projection and geotransform if it seems */ 00307 /* suitable. For now we don't try and copy GCPs, though I */ 00308 /* suppose we should. */ 00309 /* -------------------------------------------------------------------- */ 00310 double adfGeoTransform[6]; 00311 00312 if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None 00313 && (adfGeoTransform[0] != 0.0 00314 || adfGeoTransform[1] != 1.0 00315 || adfGeoTransform[2] != 0.0 00316 || adfGeoTransform[3] != 0.0 00317 || adfGeoTransform[4] != 0.0 00318 || adfGeoTransform[5] != 1.0) ) 00319 { 00320 poDstDS->SetGeoTransform( adfGeoTransform ); 00321 } 00322 00323 if( poSrcDS->GetProjectionRef() != NULL 00324 && strlen(poSrcDS->GetProjectionRef()) > 0 ) 00325 { 00326 poDstDS->SetProjection( poSrcDS->GetProjectionRef() ); 00327 } 00328 00329 /* -------------------------------------------------------------------- */ 00330 /* Loop copying bands. */ 00331 /* -------------------------------------------------------------------- */ 00332 for( int iBand = 0; iBand < poSrcDS->GetRasterCount(); iBand++ ) 00333 { 00334 GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( iBand+1 ); 00335 GDALRasterBand *poDstBand = poDstDS->GetRasterBand( iBand+1 ); 00336 00337 void *pData; 00338 00339 pData = CPLMalloc(nXSize * GDALGetDataTypeSize(eType) / 8); 00340 00341 for( int iLine = 0; iLine < nYSize; iLine++ ) 00342 { 00343 eErr = poSrcBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 00344 pData, nXSize, 1, eType, 0, 0 ); 00345 if( eErr != CE_None ) 00346 { 00347 return NULL; 00348 } 00349 00350 eErr = poDstBand->RasterIO( GF_Write, 0, iLine, nXSize, 1, 00351 pData, nXSize, 1, eType, 0, 0 ); 00352 00353 if( eErr != CE_None ) 00354 { 00355 return NULL; 00356 } 00357 00358 if( !pfnProgress( (iBand + (iLine+1) / (double) nYSize) 00359 / (double) poSrcDS->GetRasterCount(), 00360 NULL, pProgressData ) ) 00361 { 00362 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); 00363 delete poDstDS; 00364 Delete( pszFilename ); 00365 return NULL; 00366 } 00367 } 00368 00369 CPLFree( pData ); 00370 } 00371 00372 return poDstDS; 00373 } 00374 00375 /************************************************************************/ 00376 /* GDALCreateCopy() */ 00377 /************************************************************************/ 00378 00379 GDALDatasetH GDALCreateCopy( GDALDriverH hDriver, 00380 const char * pszFilename, 00381 GDALDatasetH hSrcDS, 00382 int bStrict, char ** papszOptions, 00383 GDALProgressFunc pfnProgress, 00384 void * pProgressData ) 00385 00386 { 00387 return (GDALDatasetH) ((GDALDriver *) hDriver)-> 00388 CreateCopy( pszFilename, (GDALDataset *) hSrcDS, bStrict, papszOptions, 00389 pfnProgress, pProgressData ); 00390 } 00391 00392 /************************************************************************/ 00393 /* Delete() */ 00394 /************************************************************************/ 00395 00415 CPLErr GDALDriver::Delete( const char * pszFilename ) 00416 00417 { 00418 if( pfnDelete != NULL ) 00419 return pfnDelete( pszFilename ); 00420 else 00421 { 00422 VSIStatBuf sStat; 00423 00424 if( VSIStat( pszFilename, &sStat ) == 0 && VSI_ISREG( sStat.st_mode ) ) 00425 { 00426 if( VSIUnlink( pszFilename ) == 0 ) 00427 return CE_None; 00428 else 00429 { 00430 CPLError( CE_Failure, CPLE_AppDefined, 00431 "%s: Attempt to unlink %s failed.\n", 00432 pszShortName, pszFilename ); 00433 return CE_Failure; 00434 } 00435 } 00436 else 00437 { 00438 CPLError( CE_Failure, CPLE_AppDefined, 00439 "%s: Unable to delete %s, not a file.\n", 00440 pszShortName, pszFilename ); 00441 return CE_Failure; 00442 } 00443 } 00444 } 00445 00446 /************************************************************************/ 00447 /* GDALDelete() */ 00448 /************************************************************************/ 00449 00450 CPLErr GDALDeleteDataset( GDALDriverH hDriver, const char * pszFilename ) 00451 00452 { 00453 return ((GDALDriver *) hDriver)->Delete( pszFilename ); 00454 } 00455 00456 /************************************************************************/ 00457 /* GDALGetDriverShortName() */ 00458 /************************************************************************/ 00459 00460 const char * GDALGetDriverShortName( GDALDriverH hDriver ) 00461 00462 { 00463 if( hDriver == NULL ) 00464 return NULL; 00465 else 00466 return ((GDALDriver *) hDriver)->pszShortName; 00467 } 00468 00469 /************************************************************************/ 00470 /* GDALGetDriverLongName() */ 00471 /************************************************************************/ 00472 00473 const char * GDALGetDriverLongName( GDALDriverH hDriver ) 00474 00475 { 00476 if( hDriver == NULL ) 00477 return NULL; 00478 else 00479 return ((GDALDriver *) hDriver)->pszLongName; 00480 } 00481 00482 /************************************************************************/ 00483 /* GDALGetDriverHelpTopic() */ 00484 /************************************************************************/ 00485 00486 const char * GDALGetDriverHelpTopic( GDALDriverH hDriver ) 00487 00488 { 00489 if( hDriver == NULL ) 00490 return NULL; 00491 else 00492 return ((GDALDriver *) hDriver)->pszHelpTopic; 00493 } 00494