~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to frmts/gif/gifdataset.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
 
 * $Id: gifdataset.cpp 17689 2009-09-25 17:23:37Z rouault $
 
2
 * $Id: gifdataset.cpp 23621 2011-12-20 23:26:56Z rouault $
3
3
 *
4
4
 * Project:  GIF Driver
5
5
 * Purpose:  Implement GDAL GIF Support using libungif code.  
29
29
 
30
30
#include "gdal_pam.h"
31
31
#include "cpl_string.h"
32
 
 
33
 
CPL_CVSID("$Id: gifdataset.cpp 17689 2009-09-25 17:23:37Z rouault $");
34
 
 
35
 
CPL_C_START
36
 
#include "gif_lib.h"
37
 
CPL_C_END
 
32
#include "gifabstractdataset.h"
 
33
 
 
34
CPL_CVSID("$Id: gifdataset.cpp 23621 2011-12-20 23:26:56Z rouault $");
38
35
 
39
36
CPL_C_START
40
37
void    GDALRegister_GIF(void);
51
48
 
52
49
/************************************************************************/
53
50
/* ==================================================================== */
54
 
/*                              GIFDataset                              */
 
51
/*                                  GIFDataset                              */
55
52
/* ==================================================================== */
56
53
/************************************************************************/
57
54
 
58
55
class GIFRasterBand;
59
56
 
60
 
class GIFDataset : public GDALPamDataset
 
57
class GIFDataset : public GIFAbstractDataset
61
58
{
62
59
    friend class GIFRasterBand;
63
60
 
64
 
    FILE        *fp;
65
 
 
66
 
    GifFileType *hGifFile;
67
 
 
68
 
    char        *pszProjection;
69
 
    int         bGeoTransformValid;
70
 
    double      adfGeoTransform[6];
71
 
 
72
 
    int         nGCPCount;
73
 
    GDAL_GCP    *pasGCPList;
74
 
 
75
61
  public:
76
62
                 GIFDataset();
77
 
                 ~GIFDataset();
78
63
 
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 * );
 
65
 
 
66
    static GDALDataset* CreateCopy( const char * pszFilename,
 
67
                                    GDALDataset *poSrcDS,
 
68
                                    int bStrict, char ** papszOptions,
 
69
                                    GDALProgressFunc pfnProgress,
 
70
                                    void * pProgressData );
 
71
 
86
72
};
87
73
 
88
74
/************************************************************************/
133
119
 
134
120
    psImage = psSavedImage;
135
121
 
 
122
    poColorTable = NULL;
 
123
    panInterlaceMap = NULL;
 
124
    nTransparentColor = 0;
 
125
 
 
126
    if (psImage == NULL)
 
127
        return;
 
128
 
136
129
/* -------------------------------------------------------------------- */
137
130
/*      Setup interlacing map if required.                              */
138
131
/* -------------------------------------------------------------------- */
237
230
{
238
231
    CPLAssert( nBlockXOff == 0 );
239
232
 
 
233
    if (psImage == NULL)
 
234
    {
 
235
        memset(pImage, 0, nBlockXSize);
 
236
        return CE_None;
 
237
    }
 
238
 
240
239
    if( panInterlaceMap != NULL )
241
240
        nBlockYOff = panInterlaceMap[nBlockYOff];
242
241
 
291
290
/************************************************************************/
292
291
 
293
292
GIFDataset::GIFDataset()
294
 
 
295
 
{
296
 
    hGifFile = NULL;
297
 
    fp = NULL;
298
 
 
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;
307
 
 
308
 
    nGCPCount = 0;
309
 
    pasGCPList = NULL;
310
 
}
311
 
 
312
 
/************************************************************************/
313
 
/*                           ~GIFDataset()                            */
314
 
/************************************************************************/
315
 
 
316
 
GIFDataset::~GIFDataset()
317
 
 
318
 
{
319
 
    FlushCache();
320
 
 
321
 
    if ( pszProjection )
322
 
        CPLFree( pszProjection );
323
 
 
324
 
    if ( nGCPCount > 0 )
325
 
    {
326
 
        GDALDeinitGCPs( nGCPCount, pasGCPList );
327
 
        CPLFree( pasGCPList );
328
 
    }
329
 
 
330
 
    if( hGifFile )
331
 
        DGifCloseFile( hGifFile );
332
 
 
333
 
    if( fp != NULL )
334
 
        VSIFCloseL( fp );
335
 
}
336
 
 
337
 
/************************************************************************/
338
 
/*                        GetProjectionRef()                            */
339
 
/************************************************************************/
340
 
 
341
 
const char *GIFDataset::GetProjectionRef()
342
 
 
343
 
{
344
 
    if ( pszProjection && bGeoTransformValid )
345
 
        return pszProjection;
346
 
    else
347
 
        return GDALPamDataset::GetProjectionRef();
348
 
}
349
 
 
350
 
/************************************************************************/
351
 
/*                          GetGeoTransform()                           */
352
 
/************************************************************************/
353
 
 
354
 
CPLErr GIFDataset::GetGeoTransform( double * padfTransform )
355
 
 
356
 
{
357
 
    if( bGeoTransformValid )
358
 
    {
359
 
        memcpy( padfTransform, adfGeoTransform, sizeof(double)*6 );
360
 
        return CE_None;
361
 
    }
362
 
    else
363
 
        return GDALPamDataset::GetGeoTransform( padfTransform );
364
 
}
365
 
 
366
 
/************************************************************************/
367
 
/*                            GetGCPCount()                             */
368
 
/************************************************************************/
369
 
 
370
 
int GIFDataset::GetGCPCount()
371
 
 
372
 
{
373
 
    if (nGCPCount > 0)
374
 
        return nGCPCount;
375
 
    else
376
 
        return GDALPamDataset::GetGCPCount();
377
 
}
378
 
 
379
 
/************************************************************************/
380
 
/*                          GetGCPProjection()                          */
381
 
/************************************************************************/
382
 
 
383
 
const char *GIFDataset::GetGCPProjection()
384
 
 
385
 
{
386
 
    if ( pszProjection && nGCPCount > 0 )
387
 
        return pszProjection;
388
 
    else
389
 
        return GDALPamDataset::GetGCPProjection();
390
 
}
391
 
 
392
 
/************************************************************************/
393
 
/*                               GetGCPs()                              */
394
 
/************************************************************************/
395
 
 
396
 
const GDAL_GCP *GIFDataset::GetGCPs()
397
 
 
398
 
{
399
 
    if (nGCPCount > 0)
400
 
        return pasGCPList;
401
 
    else
402
 
        return GDALPamDataset::GetGCPs();
403
 
}
404
 
 
405
 
/************************************************************************/
406
 
/*                                Open()                                */
407
 
/************************************************************************/
408
 
 
409
 
int GIFDataset::Identify( GDALOpenInfo * poOpenInfo )
410
 
 
411
 
{
412
 
    if( poOpenInfo->nHeaderBytes < 8 )
413
 
        return FALSE;
414
 
 
415
 
    if( strncmp((const char *) poOpenInfo->pabyHeader, "GIF87a",5) != 0
416
 
        && strncmp((const char *) poOpenInfo->pabyHeader, "GIF89a",5) != 0 )
417
 
        return FALSE;
418
 
 
419
 
    return TRUE;
 
293
{
420
294
}
421
295
 
422
296
/************************************************************************/
441
315
/*      Open the file and ingest.                                       */
442
316
/* -------------------------------------------------------------------- */
443
317
    GifFileType         *hGifFile;
444
 
    FILE                *fp;
 
318
    VSILFILE                *fp;
445
319
    int                  nGifErr;
446
320
 
447
321
    fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
470
344
 
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 )
 
348
    {
 
349
        /* Skip extension records found before IMAGE_DESC_RECORD_TYPE */
 
350
        if (RecordType == EXTENSION_RECORD_TYPE)
 
351
        {
 
352
            int nFunction;
 
353
            GifByteType *pExtData;
 
354
            if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR)
 
355
                break;
 
356
            while (pExtData != NULL)
 
357
            {
 
358
                if (DGifGetExtensionNext(hGifFile, &pExtData) == GIF_ERROR)
 
359
                    break;
 
360
            }
 
361
        }
 
362
    }
474
363
 
475
364
    if( RecordType == IMAGE_DESC_RECORD_TYPE  &&
476
365
        DGifGetImageDesc(hGifFile) != GIF_ERROR)
505
394
 
506
395
    nGifErr = DGifSlurp( hGifFile );
507
396
 
508
 
    if( nGifErr != GIF_OK )
 
397
    if( nGifErr != GIF_OK || hGifFile->SavedImages == NULL )
509
398
    {
510
399
        VSIFCloseL( fp );
511
400
        DGifCloseFile(hGifFile);
562
451
    }
563
452
 
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 )
571
 
    {
572
 
        poDS->bGeoTransformValid =
573
 
            GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", 
574
 
                               poDS->adfGeoTransform );
575
 
 
576
 
        if ( !poDS->bGeoTransformValid )
577
 
        {
578
 
            int bOziFileOK = 
579
 
                GDALReadOziMapFile( poOpenInfo->pszFilename,
580
 
                                    poDS->adfGeoTransform, 
581
 
                                    &poDS->pszProjection,
582
 
                                    &poDS->nGCPCount, &poDS->pasGCPList );
583
 
 
584
 
            if ( bOziFileOK && poDS->nGCPCount == 0 )
585
 
                 poDS->bGeoTransformValid = TRUE;
586
 
        }
587
 
    }
 
456
    poDS->DetectGeoreferencing(poOpenInfo);
588
457
 
589
458
/* -------------------------------------------------------------------- */
590
459
/*      Initialize any PAM information.                                 */
601
470
}
602
471
 
603
472
/************************************************************************/
604
 
/*                           GIFCreateCopy()                            */
 
473
/*                             CreateCopy()                             */
605
474
/************************************************************************/
606
475
 
607
 
static GDALDataset *
608
 
GIFCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
 
476
GDALDataset *
 
477
GIFDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
609
478
               int bStrict, char ** papszOptions, 
610
479
               GDALProgressFunc pfnProgress, void * pProgressData )
611
480
 
655
524
/*      Open the output file.                                           */
656
525
/* -------------------------------------------------------------------- */
657
526
    GifFileType *hGifFile;
658
 
    FILE *fp;
 
527
    VSILFILE *fp;
659
528
 
660
 
    fp = VSIFOpenL( pszFilename, "w" );
 
529
    fp = VSIFOpenL( pszFilename, "wb" );
661
530
    if( fp == NULL )
662
531
    {
663
532
        CPLError( CE_Failure, CPLE_OpenFailed, 
848
717
    }
849
718
    hGifFile = NULL;
850
719
 
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 */
859
 
 
860
 
    VSIFSeekL(fp, 0, SEEK_SET);
861
 
    if (VSIFWriteL("GIF89a", 1, 6, fp) != 6)
862
 
    {
863
 
        CPLError( CE_Failure, CPLE_AppDefined, 
864
 
                  "Error writing gif file." );
865
 
        goto error;
866
 
    }
867
 
 
868
720
    VSIFCloseL( fp );
869
721
    fp = NULL;
870
722
 
882
734
/* -------------------------------------------------------------------- */
883
735
/*      Re-open dataset, and copy any auxilary pam information.         */
884
736
/* -------------------------------------------------------------------- */
885
 
    poDS = (GDALPamDataset *) 
886
 
        GDALOpen( pszFilename, GA_ReadOnly );
887
737
 
888
 
    if( poDS )
 
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();
 
743
    if (poDS)
 
744
    {
889
745
        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
 
746
        return poDS;
 
747
    }
 
748
    else
 
749
    {
 
750
        CPLErrorReset();
890
751
 
891
 
    return poDS;
 
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 ) );
 
757
        return poGIF_DS;
 
758
    }
892
759
 
893
760
error:
894
761
    if (hGifFile)
911
778
 
912
779
{
913
780
    return VSIFReadL( pabyBuffer, 1, nBytesToRead, 
914
 
                      (FILE *) psGFile->UserData );
 
781
                      (VSILFILE *) psGFile->UserData );
915
782
}
916
783
 
917
784
/************************************************************************/
924
791
                            const GifByteType *pabyBuffer, int nBytesToWrite )
925
792
 
926
793
{
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 )
 
797
    {
 
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 */
 
806
 
 
807
        int nRet = VSIFWriteL("GIF89a", 1, 6, fp);
 
808
        nRet += VSIFWriteL( (char *) pabyBuffer + 6, 1, nBytesToWrite - 6, fp );
 
809
        return nRet;
 
810
    }
 
811
    else
 
812
        return VSIFWriteL( (void *) pabyBuffer, 1, nBytesToWrite, fp );
929
813
}
930
814
 
931
815
/************************************************************************/
960
844
        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
961
845
 
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;
965
849
 
966
850
        GetGDALDriverManager()->RegisterDriver( poDriver );
967
851
    }