52
49
/************************************************************************/
53
50
/* ==================================================================== */
55
52
/* ==================================================================== */
56
53
/************************************************************************/
58
55
class GIFRasterBand;
60
class GIFDataset : public GDALPamDataset
57
class GIFDataset : public GIFAbstractDataset
62
59
friend class GIFRasterBand;
66
GifFileType *hGifFile;
69
int bGeoTransformValid;
70
double adfGeoTransform[6];
79
virtual const char *GetProjectionRef();
80
virtual CPLErr GetGeoTransform( double * );
81
virtual int GetGCPCount();
82
virtual const char *GetGCPProjection();
83
virtual const GDAL_GCP *GetGCPs();
84
64
static GDALDataset *Open( GDALOpenInfo * );
85
static int Identify( GDALOpenInfo * );
66
static GDALDataset* CreateCopy( const char * pszFilename,
68
int bStrict, char ** papszOptions,
69
GDALProgressFunc pfnProgress,
70
void * pProgressData );
88
74
/************************************************************************/
291
290
/************************************************************************/
293
292
GIFDataset::GIFDataset()
299
pszProjection = NULL;
300
bGeoTransformValid = FALSE;
301
adfGeoTransform[0] = 0.0;
302
adfGeoTransform[1] = 1.0;
303
adfGeoTransform[2] = 0.0;
304
adfGeoTransform[3] = 0.0;
305
adfGeoTransform[4] = 0.0;
306
adfGeoTransform[5] = 1.0;
312
/************************************************************************/
314
/************************************************************************/
316
GIFDataset::~GIFDataset()
322
CPLFree( pszProjection );
326
GDALDeinitGCPs( nGCPCount, pasGCPList );
327
CPLFree( pasGCPList );
331
DGifCloseFile( hGifFile );
337
/************************************************************************/
338
/* GetProjectionRef() */
339
/************************************************************************/
341
const char *GIFDataset::GetProjectionRef()
344
if ( pszProjection && bGeoTransformValid )
345
return pszProjection;
347
return GDALPamDataset::GetProjectionRef();
350
/************************************************************************/
351
/* GetGeoTransform() */
352
/************************************************************************/
354
CPLErr GIFDataset::GetGeoTransform( double * padfTransform )
357
if( bGeoTransformValid )
359
memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
363
return GDALPamDataset::GetGeoTransform( padfTransform );
366
/************************************************************************/
368
/************************************************************************/
370
int GIFDataset::GetGCPCount()
376
return GDALPamDataset::GetGCPCount();
379
/************************************************************************/
380
/* GetGCPProjection() */
381
/************************************************************************/
383
const char *GIFDataset::GetGCPProjection()
386
if ( pszProjection && nGCPCount > 0 )
387
return pszProjection;
389
return GDALPamDataset::GetGCPProjection();
392
/************************************************************************/
394
/************************************************************************/
396
const GDAL_GCP *GIFDataset::GetGCPs()
402
return GDALPamDataset::GetGCPs();
405
/************************************************************************/
407
/************************************************************************/
409
int GIFDataset::Identify( GDALOpenInfo * poOpenInfo )
412
if( poOpenInfo->nHeaderBytes < 8 )
415
if( strncmp((const char *) poOpenInfo->pabyHeader, "GIF87a",5) != 0
416
&& strncmp((const char *) poOpenInfo->pabyHeader, "GIF89a",5) != 0 )
422
296
/************************************************************************/
471
345
while( DGifGetRecordType(hGifFile, &RecordType) != GIF_ERROR
472
346
&& RecordType != TERMINATE_RECORD_TYPE
473
&& RecordType != IMAGE_DESC_RECORD_TYPE ) {}
347
&& RecordType != IMAGE_DESC_RECORD_TYPE )
349
/* Skip extension records found before IMAGE_DESC_RECORD_TYPE */
350
if (RecordType == EXTENSION_RECORD_TYPE)
353
GifByteType *pExtData;
354
if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR)
356
while (pExtData != NULL)
358
if (DGifGetExtensionNext(hGifFile, &pExtData) == GIF_ERROR)
475
364
if( RecordType == IMAGE_DESC_RECORD_TYPE &&
476
365
DGifGetImageDesc(hGifFile) != GIF_ERROR)
564
453
/* -------------------------------------------------------------------- */
565
/* Check for world file. */
454
/* Check for georeferencing. */
566
455
/* -------------------------------------------------------------------- */
567
poDS->bGeoTransformValid =
568
GDALReadWorldFile( poOpenInfo->pszFilename, NULL,
569
poDS->adfGeoTransform );
570
if ( !poDS->bGeoTransformValid )
572
poDS->bGeoTransformValid =
573
GDALReadWorldFile( poOpenInfo->pszFilename, ".wld",
574
poDS->adfGeoTransform );
576
if ( !poDS->bGeoTransformValid )
579
GDALReadOziMapFile( poOpenInfo->pszFilename,
580
poDS->adfGeoTransform,
581
&poDS->pszProjection,
582
&poDS->nGCPCount, &poDS->pasGCPList );
584
if ( bOziFileOK && poDS->nGCPCount == 0 )
585
poDS->bGeoTransformValid = TRUE;
456
poDS->DetectGeoreferencing(poOpenInfo);
589
458
/* -------------------------------------------------------------------- */
590
459
/* Initialize any PAM information. */
603
472
/************************************************************************/
604
/* GIFCreateCopy() */
605
474
/************************************************************************/
608
GIFCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
477
GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
609
478
int bStrict, char ** papszOptions,
610
479
GDALProgressFunc pfnProgress, void * pProgressData )
655
524
/* Open the output file. */
656
525
/* -------------------------------------------------------------------- */
657
526
GifFileType *hGifFile;
660
fp = VSIFOpenL( pszFilename, "w" );
529
fp = VSIFOpenL( pszFilename, "wb" );
663
532
CPLError( CE_Failure, CPLE_OpenFailed,
851
/* This is a hack to write a GIF89a instead of GIF87a */
852
/* (we have to, since we are using graphical extension block) */
853
/* EGifSpew would write GIF89a when it detects an extension block if we were using it */
854
/* As we don't, we could have used EGifSetGifVersion instead, but the version of libungif */
855
/* in GDAL has a bug : it writes on read-only memory ! */
856
/* (this is a well-known problem. Just google for "EGifSetGifVersion segfault") */
857
/* Most readers don't even care if it is GIF87a or GIF89a, but it is */
858
/* better to write the right version */
860
VSIFSeekL(fp, 0, SEEK_SET);
861
if (VSIFWriteL("GIF89a", 1, 6, fp) != 6)
863
CPLError( CE_Failure, CPLE_AppDefined,
864
"Error writing gif file." );
868
720
VSIFCloseL( fp );
882
734
/* -------------------------------------------------------------------- */
883
735
/* Re-open dataset, and copy any auxilary pam information. */
884
736
/* -------------------------------------------------------------------- */
885
poDS = (GDALPamDataset *)
886
GDALOpen( pszFilename, GA_ReadOnly );
738
/* If outputing to stdout, we can't reopen it, so we'll return */
739
/* a fake dataset to make the caller happy */
740
CPLPushErrorHandler(CPLQuietErrorHandler);
741
poDS = (GDALPamDataset*) GDALOpen(pszFilename, GA_ReadOnly);
742
CPLPopErrorHandler();
889
745
poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
752
GIFDataset* poGIF_DS = new GIFDataset();
753
poGIF_DS->nRasterXSize = nXSize;
754
poGIF_DS->nRasterYSize = nYSize;
755
for(int i=0;i<nBands;i++)
756
poGIF_DS->SetBand( i+1, new GIFRasterBand( poGIF_DS, i+1, NULL, 0 ) );
924
791
const GifByteType *pabyBuffer, int nBytesToWrite )
927
return VSIFWriteL( (void *) pabyBuffer, 1, nBytesToWrite,
928
(FILE *) psGFile->UserData );
794
VSILFILE* fp = (VSILFILE *) psGFile->UserData;
795
if ( VSIFTellL(fp) == 0 && nBytesToWrite >= 6 &&
796
memcmp(pabyBuffer, "GIF87a", 6) == 0 )
798
/* This is a hack to write a GIF89a instead of GIF87a */
799
/* (we have to, since we are using graphical extension block) */
800
/* EGifSpew would write GIF89a when it detects an extension block if we were using it */
801
/* As we don't, we could have used EGifSetGifVersion instead, but the version of libungif */
802
/* in GDAL has a bug : it writes on read-only memory ! */
803
/* (this is a well-known problem. Just google for "EGifSetGifVersion segfault") */
804
/* Most readers don't even care if it is GIF87a or GIF89a, but it is */
805
/* better to write the right version */
807
int nRet = VSIFWriteL("GIF89a", 1, 6, fp);
808
nRet += VSIFWriteL( (char *) pabyBuffer + 6, 1, nBytesToWrite - 6, fp );
812
return VSIFWriteL( (void *) pabyBuffer, 1, nBytesToWrite, fp );
931
815
/************************************************************************/
960
844
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
962
846
poDriver->pfnOpen = GIFDataset::Open;
963
poDriver->pfnCreateCopy = GIFCreateCopy;
964
poDriver->pfnIdentify = GIFDataset::Identify;
847
poDriver->pfnCreateCopy = GIFDataset::CreateCopy;
848
poDriver->pfnIdentify = GIFAbstractDataset::Identify;
966
850
GetGDALDriverManager()->RegisterDriver( poDriver );