LCOV - code coverage report
Current view: directory - frmts/gif - biggifdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 150 121 80.7 %
Date: 2012-12-26 Functions: 18 10 55.6 %

       1                 : /******************************************************************************
       2                 :  * $Id: biggifdataset.cpp 24608 2012-06-24 21:55:29Z rouault $
       3                 :  *
       4                 :  * Project:  BIGGIF Driver
       5                 :  * Purpose:  Implement GDAL support for reading large GIF files in a 
       6                 :  *           streaming fashion rather than the slurp-into-memory approach
       7                 :  *           of the normal GIF driver.
       8                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       9                 :  *
      10                 :  ******************************************************************************
      11                 :  * Copyright (c) 2001-2008, Frank Warmerdam <warmerdam@pobox.com>
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "gdal_pam.h"
      33                 : #include "cpl_string.h"
      34                 : #include "gifabstractdataset.h"
      35                 : 
      36                 : CPL_CVSID("$Id: biggifdataset.cpp 24608 2012-06-24 21:55:29Z rouault $");
      37                 : 
      38                 : CPL_C_START
      39                 : void  GDALRegister_BIGGIF(void);
      40                 : CPL_C_END
      41                 : 
      42                 : static const int InterlacedOffset[] = { 0, 4, 2, 1 }; 
      43                 : static const int InterlacedJumps[] = { 8, 8, 4, 2 };  
      44                 : 
      45                 : static int VSIGIFReadFunc( GifFileType *, GifByteType *, int);
      46                 : 
      47                 : /************************************************************************/
      48                 : /* ==================================================================== */
      49                 : /*                          BIGGIFDataset                               */
      50                 : /* ==================================================================== */
      51                 : /************************************************************************/
      52                 : 
      53                 : class BIGGifRasterBand;
      54                 : 
      55                 : class BIGGIFDataset : public GIFAbstractDataset
      56                 : {
      57                 :     friend class BIGGifRasterBand;
      58                 : 
      59                 :     int         nLastLineRead;
      60                 : 
      61                 :     GDALDataset *poWorkDS;
      62                 : 
      63                 :     CPLErr       ReOpen();
      64                 : 
      65                 :   protected:
      66                 :     virtual int         CloseDependentDatasets();
      67                 : 
      68                 :   public:
      69                 :                  BIGGIFDataset();
      70                 :                  ~BIGGIFDataset();
      71                 : 
      72                 :     static GDALDataset *Open( GDALOpenInfo * );
      73                 : };
      74                 : 
      75                 : /************************************************************************/
      76                 : /* ==================================================================== */
      77                 : /*                            BIGGifRasterBand                          */
      78                 : /* ==================================================================== */
      79                 : /************************************************************************/
      80                 : 
      81                 : class BIGGifRasterBand : public GDALPamRasterBand
      82                 : {
      83                 :     friend class BIGGIFDataset;
      84                 : 
      85                 :     int   *panInterlaceMap;
      86                 :     
      87                 :     GDALColorTable *poColorTable;
      88                 : 
      89                 :   public:
      90                 : 
      91                 :                    BIGGifRasterBand( BIGGIFDataset *, int );
      92                 :     virtual       ~BIGGifRasterBand();
      93                 : 
      94                 :     virtual CPLErr IReadBlock( int, int, void * );
      95                 : 
      96                 :     virtual GDALColorInterp GetColorInterpretation();
      97                 :     virtual GDALColorTable *GetColorTable();
      98                 : };
      99                 : 
     100                 : /************************************************************************/
     101                 : /*                          BIGGifRasterBand()                          */
     102                 : /************************************************************************/
     103                 : 
     104               4 : BIGGifRasterBand::BIGGifRasterBand( BIGGIFDataset *poDS, int nBackground )
     105                 : 
     106                 : {
     107               4 :     SavedImage *psImage = poDS->hGifFile->SavedImages + 0;
     108                 : 
     109               4 :     this->poDS = poDS;
     110               4 :     this->nBand = 1;
     111                 : 
     112               4 :     eDataType = GDT_Byte;
     113                 : 
     114               4 :     nBlockXSize = poDS->nRasterXSize;
     115               4 :     nBlockYSize = 1;
     116                 : 
     117                 : /* -------------------------------------------------------------------- */
     118                 : /*      Setup interlacing map if required.                              */
     119                 : /* -------------------------------------------------------------------- */
     120               4 :     panInterlaceMap = NULL;
     121               4 :     if( psImage->ImageDesc.Interlace )
     122                 :     {
     123               4 :         int i, j, iLine = 0;
     124                 : 
     125               4 :         poDS->SetMetadataItem( "INTERLACED", "YES", "IMAGE_STRUCTURE" );
     126                 : 
     127               4 :         panInterlaceMap = (int *) CPLCalloc(poDS->nRasterYSize,sizeof(int));
     128                 : 
     129              20 :   for (i = 0; i < 4; i++)
     130                 :         {
     131          132684 :       for (j = InterlacedOffset[i]; 
     132                 :                  j < poDS->nRasterYSize;
     133           66334 :                  j += InterlacedJumps[i]) 
     134           66334 :                 panInterlaceMap[j] = iLine++;
     135                 :         }
     136                 :     }
     137                 :     else
     138               0 :         poDS->SetMetadataItem( "INTERLACED", "NO", "IMAGE_STRUCTURE" );
     139                 : 
     140                 : /* -------------------------------------------------------------------- */
     141                 : /*      Setup colormap.                                                 */
     142                 : /* -------------------------------------------------------------------- */
     143               4 :     ColorMapObject  *psGifCT = psImage->ImageDesc.ColorMap;
     144               4 :     if( psGifCT == NULL )
     145               4 :         psGifCT = poDS->hGifFile->SColorMap;
     146                 : 
     147               4 :     poColorTable = new GDALColorTable();
     148              68 :     for( int iColor = 0; iColor < psGifCT->ColorCount; iColor++ )
     149                 :     {
     150                 :         GDALColorEntry  oEntry;
     151                 : 
     152              64 :         oEntry.c1 = psGifCT->Colors[iColor].Red;
     153              64 :         oEntry.c2 = psGifCT->Colors[iColor].Green;
     154              64 :         oEntry.c3 = psGifCT->Colors[iColor].Blue;
     155              64 :         oEntry.c4 = 255;
     156                 : 
     157              64 :         poColorTable->SetColorEntry( iColor, &oEntry );
     158                 :     }
     159                 : 
     160                 : /* -------------------------------------------------------------------- */
     161                 : /*      If we have a background value, return it here.  Some            */
     162                 : /*      applications might want to treat this as transparent, but in    */
     163                 : /*      many uses this is inappropriate so we don't return it as        */
     164                 : /*      nodata or transparent.                                          */
     165                 : /* -------------------------------------------------------------------- */
     166               4 :     if( nBackground != 255 )
     167                 :     {
     168                 :         char szBackground[10];
     169                 :         
     170               4 :         sprintf( szBackground, "%d", nBackground );
     171               4 :         SetMetadataItem( "GIF_BACKGROUND", szBackground );
     172                 :     }
     173               4 : }
     174                 : 
     175                 : /************************************************************************/
     176                 : /*                           ~BIGGifRasterBand()                           */
     177                 : /************************************************************************/
     178                 : 
     179               4 : BIGGifRasterBand::~BIGGifRasterBand()
     180                 : 
     181                 : {
     182               4 :     if( poColorTable != NULL )
     183               4 :         delete poColorTable;
     184                 : 
     185               4 :     CPLFree( panInterlaceMap );
     186               4 : }
     187                 : 
     188                 : /************************************************************************/
     189                 : /*                             IReadBlock()                             */
     190                 : /************************************************************************/
     191                 : 
     192             400 : CPLErr BIGGifRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     193                 :                                   void * pImage )
     194                 : 
     195                 : {
     196             400 :     BIGGIFDataset *poGDS = (BIGGIFDataset *) poDS;
     197                 : 
     198             400 :     CPLAssert( nBlockXOff == 0 );
     199                 : 
     200             400 :     if( panInterlaceMap != NULL )
     201             400 :         nBlockYOff = panInterlaceMap[nBlockYOff];
     202                 : 
     203                 : /* -------------------------------------------------------------------- */
     204                 : /*      Do we already have this line in the work dataset?               */
     205                 : /* -------------------------------------------------------------------- */
     206             400 :     if( poGDS->poWorkDS != NULL && nBlockYOff <= poGDS->nLastLineRead )
     207                 :     {
     208                 :         return poGDS->poWorkDS->
     209                 :             RasterIO( GF_Read, 0, nBlockYOff, nBlockXSize, 1, 
     210                 :                       pImage, nBlockXSize, 1, GDT_Byte, 
     211             198 :                       1, NULL, 0, 0, 0 );
     212                 :     }
     213                 : 
     214                 : /* -------------------------------------------------------------------- */
     215                 : /*      Do we need to restart from the start of the image?              */
     216                 : /* -------------------------------------------------------------------- */
     217             202 :     if( nBlockYOff <= poGDS->nLastLineRead )
     218                 :     {
     219               1 :         if( poGDS->ReOpen() == CE_Failure )
     220               0 :             return CE_Failure;
     221                 :     }
     222                 : 
     223                 : /* -------------------------------------------------------------------- */
     224                 : /*      Read till we get our target line.                               */
     225                 : /* -------------------------------------------------------------------- */
     226            1005 :     while( poGDS->nLastLineRead < nBlockYOff )
     227                 :     {
     228             601 :         if( DGifGetLine( poGDS->hGifFile, (GifPixelType*)pImage, 
     229                 :                          nBlockXSize ) == GIF_ERROR )
     230                 :         {
     231                 :             CPLError( CE_Failure, CPLE_AppDefined,
     232               0 :                       "Failure decoding scanline of GIF file." );
     233               0 :             return CE_Failure;
     234                 :         }
     235                 : 
     236             601 :         poGDS->nLastLineRead++;
     237                 : 
     238             601 :         if( poGDS->poWorkDS != NULL )
     239                 :         {
     240                 :             poGDS->poWorkDS->RasterIO( GF_Write, 
     241                 :                                        0, poGDS->nLastLineRead, nBlockXSize, 1, 
     242                 :                                        pImage, nBlockXSize, 1, GDT_Byte, 
     243             400 :                                        1, NULL, 0, 0, 0 );
     244                 :         }
     245                 :     }
     246                 : 
     247             202 :     return CE_None;
     248                 : }
     249                 : 
     250                 : /************************************************************************/
     251                 : /*                       GetColorInterpretation()                       */
     252                 : /************************************************************************/
     253                 : 
     254               0 : GDALColorInterp BIGGifRasterBand::GetColorInterpretation()
     255                 : 
     256                 : {
     257               0 :     return GCI_PaletteIndex;
     258                 : }
     259                 : 
     260                 : /************************************************************************/
     261                 : /*                           GetColorTable()                            */
     262                 : /************************************************************************/
     263                 : 
     264               0 : GDALColorTable *BIGGifRasterBand::GetColorTable()
     265                 : 
     266                 : {
     267               0 :     return poColorTable;
     268                 : }
     269                 : 
     270                 : /************************************************************************/
     271                 : /* ==================================================================== */
     272                 : /*                             BIGGIFDataset                            */
     273                 : /* ==================================================================== */
     274                 : /************************************************************************/
     275                 : 
     276                 : 
     277                 : /************************************************************************/
     278                 : /*                            BIGGIFDataset()                            */
     279                 : /************************************************************************/
     280                 : 
     281               4 : BIGGIFDataset::BIGGIFDataset()
     282                 : 
     283                 : {
     284               4 :     nLastLineRead = -1;
     285               4 :     poWorkDS = NULL;
     286               4 : }
     287                 : 
     288                 : /************************************************************************/
     289                 : /*                           ~BIGGIFDataset()                            */
     290                 : /************************************************************************/
     291                 : 
     292               4 : BIGGIFDataset::~BIGGIFDataset()
     293                 : 
     294                 : {
     295               4 :     FlushCache();
     296                 : 
     297               4 :     CloseDependentDatasets();
     298               4 : }
     299                 : 
     300                 : /************************************************************************/
     301                 : /*                      CloseDependentDatasets()                        */
     302                 : /************************************************************************/
     303                 : 
     304               4 : int BIGGIFDataset::CloseDependentDatasets()
     305                 : {
     306               4 :     int bHasDroppedRef = GDALPamDataset::CloseDependentDatasets();
     307                 : 
     308               4 :     if( poWorkDS != NULL )
     309                 :     {
     310               1 :         bHasDroppedRef = TRUE;
     311                 : 
     312               1 :         CPLString osTempFilename = poWorkDS->GetDescription();
     313                 : 
     314               1 :         GDALClose( (GDALDatasetH) poWorkDS );
     315               1 :         poWorkDS = NULL;
     316                 : 
     317               1 :         GDALDriver *poGTiff = (GDALDriver *) GDALGetDriverByName( "GTiff" );
     318               1 :         poGTiff->Delete( osTempFilename );
     319                 : 
     320               1 :         poWorkDS = NULL;
     321                 :     }
     322                 : 
     323               4 :     return bHasDroppedRef;
     324                 : }
     325                 : 
     326                 : /************************************************************************/
     327                 : /*                               ReOpen()                               */
     328                 : /*                                                                      */
     329                 : /*      (Re)Open the gif file and process past the first image          */
     330                 : /*      descriptor.                                                     */
     331                 : /************************************************************************/
     332                 : 
     333               5 : CPLErr BIGGIFDataset::ReOpen()
     334                 : 
     335                 : {
     336                 : /* -------------------------------------------------------------------- */
     337                 : /*      If the file is already open, close it so we can restart.        */
     338                 : /* -------------------------------------------------------------------- */
     339               5 :     if( hGifFile != NULL )
     340               1 :         DGifCloseFile( hGifFile );
     341                 : 
     342                 : /* -------------------------------------------------------------------- */
     343                 : /*      If we are actually reopening, then we assume that access to     */
     344                 : /*      the image data is not strictly once through sequential, and     */
     345                 : /*      we will try to create a working database in a temporary         */
     346                 : /*      directory to hold the image as we read through it the second    */
     347                 : /*      time.                                                           */
     348                 : /* -------------------------------------------------------------------- */
     349               5 :     if( hGifFile != NULL )
     350                 :     {
     351               1 :         GDALDriver *poGTiffDriver = (GDALDriver*) GDALGetDriverByName("GTiff");
     352                 :         
     353               1 :         if( poGTiffDriver != NULL )
     354                 :         {
     355                 :             /* Create as a sparse file to avoid filling up the whole file */
     356                 :             /* while closing and then destroying this temporary dataset */
     357               1 :             const char* apszOptions[] = { "COMPRESS=LZW", "SPARSE_OK=YES", NULL };
     358               1 :             CPLString osTempFilename = CPLGenerateTempFilename("biggif");
     359                 : 
     360               1 :             osTempFilename += ".tif";
     361                 : 
     362                 :             poWorkDS = poGTiffDriver->Create( osTempFilename, 
     363                 :                                               nRasterXSize, nRasterYSize, 1, 
     364               1 :                                               GDT_Byte, const_cast<char**>(apszOptions));
     365                 :         }
     366                 :     }
     367                 : 
     368                 : /* -------------------------------------------------------------------- */
     369                 : /*      Open                                                            */
     370                 : /* -------------------------------------------------------------------- */
     371               5 :     VSIFSeekL( fp, 0, SEEK_SET );
     372                 : 
     373               5 :     nLastLineRead = -1;
     374                 : #if defined(GIFLIB_MAJOR) && GIFLIB_MAJOR >= 5
     375                 :     int nError;
     376                 :     hGifFile = DGifOpen( fp, VSIGIFReadFunc, &nError );
     377                 : #else
     378               5 :     hGifFile = DGifOpen( fp, VSIGIFReadFunc );
     379                 : #endif
     380               5 :     if( hGifFile == NULL )
     381                 :     {
     382                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     383               0 :                   "DGifOpen() failed.  Perhaps the gif file is corrupt?\n" );
     384                 : 
     385               0 :         return CE_Failure;
     386                 :     }
     387                 : 
     388                 : /* -------------------------------------------------------------------- */
     389                 : /*      Find the first image record.                                    */
     390                 : /* -------------------------------------------------------------------- */
     391               5 :     GifRecordType RecordType = TERMINATE_RECORD_TYPE;
     392                 : 
     393              10 :     while( DGifGetRecordType(hGifFile, &RecordType) != GIF_ERROR
     394                 :            && RecordType != TERMINATE_RECORD_TYPE
     395                 :            && RecordType != IMAGE_DESC_RECORD_TYPE )
     396                 :     {
     397                 :         /* Skip extension records found before IMAGE_DESC_RECORD_TYPE */
     398               0 :         if (RecordType == EXTENSION_RECORD_TYPE)
     399                 :         {
     400                 :             int nFunction;
     401                 :             GifByteType *pExtData;
     402               0 :             if (DGifGetExtension(hGifFile, &nFunction, &pExtData) == GIF_ERROR)
     403               0 :                 break;
     404               0 :             while (pExtData != NULL)
     405                 :             {
     406               0 :                 if (DGifGetExtensionNext(hGifFile, &pExtData) == GIF_ERROR)
     407               0 :                     break;
     408                 :             }
     409                 :         }
     410                 :     }
     411                 : 
     412               5 :     if( RecordType != IMAGE_DESC_RECORD_TYPE )
     413                 :     {
     414               0 :         DGifCloseFile( hGifFile );
     415               0 :         hGifFile = NULL;
     416                 : 
     417                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     418               0 :                   "Failed to find image description record in GIF file." );
     419               0 :         return CE_Failure;
     420                 :     }
     421                 :     
     422               5 :     if (DGifGetImageDesc(hGifFile) == GIF_ERROR)
     423                 :     {
     424               0 :         DGifCloseFile( hGifFile );
     425               0 :         hGifFile = NULL;
     426                 : 
     427                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     428               0 :                   "Image description reading failed in GIF file." );
     429               0 :         return CE_Failure;
     430                 :     }
     431                 :     
     432               5 :     return CE_None;
     433                 : }
     434                 : 
     435                 : 
     436                 : /************************************************************************/
     437                 : /*                                Open()                                */
     438                 : /************************************************************************/
     439                 : 
     440            2588 : GDALDataset *BIGGIFDataset::Open( GDALOpenInfo * poOpenInfo )
     441                 : 
     442                 : {
     443            2588 :     if( !Identify( poOpenInfo ) )
     444            2584 :         return NULL;
     445                 : 
     446               4 :     if( poOpenInfo->eAccess == GA_Update )
     447                 :     {
     448                 :         CPLError( CE_Failure, CPLE_NotSupported, 
     449                 :                   "The GIF driver does not support update access to existing"
     450               0 :                   " files.\n" );
     451               0 :         return NULL;
     452                 :     }
     453                 : 
     454                 : /* -------------------------------------------------------------------- */
     455                 : /*      Open the file.                                                  */
     456                 : /* -------------------------------------------------------------------- */
     457                 :     VSILFILE                *fp;
     458                 : 
     459               4 :     fp = VSIFOpenL( poOpenInfo->pszFilename, "r" );
     460               4 :     if( fp == NULL )
     461               0 :         return NULL;
     462                 : 
     463                 : /* -------------------------------------------------------------------- */
     464                 : /*      Create a corresponding GDALDataset.                             */
     465                 : /* -------------------------------------------------------------------- */
     466                 :     BIGGIFDataset   *poDS;
     467                 : 
     468               4 :     poDS = new BIGGIFDataset();
     469                 : 
     470               4 :     poDS->fp = fp;
     471               4 :     poDS->eAccess = GA_ReadOnly;
     472               4 :     if( poDS->ReOpen() == CE_Failure )
     473                 :     {
     474               0 :         delete poDS;
     475               0 :         return NULL;
     476                 :     }
     477                 : 
     478                 : /* -------------------------------------------------------------------- */
     479                 : /*      Capture some information from the file that is of interest.     */
     480                 : /* -------------------------------------------------------------------- */
     481                 :     
     482               4 :     poDS->nRasterXSize = poDS->hGifFile->SavedImages[0].ImageDesc.Width;
     483               4 :     poDS->nRasterYSize = poDS->hGifFile->SavedImages[0].ImageDesc.Height;
     484                 : 
     485                 : /* -------------------------------------------------------------------- */
     486                 : /*      Create band information objects.                                */
     487                 : /* -------------------------------------------------------------------- */
     488                 :     poDS->SetBand( 1, 
     489                 :                    new BIGGifRasterBand( poDS, 
     490               4 :                                          poDS->hGifFile->SBackGroundColor ));
     491                 : 
     492                 : /* -------------------------------------------------------------------- */
     493                 : /*      Check for georeferencing.                                       */
     494                 : /* -------------------------------------------------------------------- */
     495               4 :     poDS->DetectGeoreferencing(poOpenInfo);
     496                 : 
     497                 : /* -------------------------------------------------------------------- */
     498                 : /*      Initialize any PAM information.                                 */
     499                 : /* -------------------------------------------------------------------- */
     500               4 :     poDS->SetDescription( poOpenInfo->pszFilename );
     501               4 :     poDS->TryLoadXML();
     502                 : 
     503                 : /* -------------------------------------------------------------------- */
     504                 : /*      Support overviews.                                              */
     505                 : /* -------------------------------------------------------------------- */
     506               4 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
     507                 : 
     508               4 :     return poDS;
     509                 : }
     510                 : 
     511                 : /************************************************************************/
     512                 : /*                           VSIGIFReadFunc()                           */
     513                 : /*                                                                      */
     514                 : /*      Proxy function for reading from GIF file.                       */
     515                 : /************************************************************************/
     516                 : 
     517             222 : static int VSIGIFReadFunc( GifFileType *psGFile, GifByteType *pabyBuffer, 
     518                 :                            int nBytesToRead )
     519                 : 
     520                 : {
     521                 :     return VSIFReadL( pabyBuffer, 1, nBytesToRead, 
     522             222 :                       (VSILFILE *) psGFile->UserData );
     523                 : }
     524                 : 
     525                 : /************************************************************************/
     526                 : /*                        GDALRegister_BIGGIF()                         */
     527                 : /************************************************************************/
     528                 : 
     529             582 : void GDALRegister_BIGGIF()
     530                 : 
     531                 : {
     532                 :     GDALDriver  *poDriver;
     533                 : 
     534             582 :     if( GDALGetDriverByName( "BIGGIF" ) == NULL )
     535                 :     {
     536             561 :         poDriver = new GDALDriver();
     537                 :         
     538             561 :         poDriver->SetDescription( "BIGGIF" );
     539                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
     540             561 :                                    "Graphics Interchange Format (.gif)" );
     541                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, 
     542             561 :                                    "frmt_gif.html" );
     543             561 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "gif" );
     544             561 :         poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/gif" );
     545             561 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     546                 : 
     547             561 :         poDriver->pfnOpen = BIGGIFDataset::Open;
     548             561 :         poDriver->pfnIdentify = GIFAbstractDataset::Identify;
     549                 : 
     550             561 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     551                 :     }
     552             582 : }
     553                 : 

Generated by: LCOV version 1.7