LTP GCOV extension - code coverage report
Current view: directory - frmts/gtiff - gt_overview.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 287
Code covered: 83.3 % Executed lines: 239

       1                 : /******************************************************************************
       2                 :  * $Id: gt_overview.cpp 19892 2010-06-19 08:54:44Z rouault $
       3                 :  *
       4                 :  * Project:  GeoTIFF Driver
       5                 :  * Purpose:  Code to build overviews of external databases as a TIFF file. 
       6                 :  *           Only used by the GDALDefaultOverviews::BuildOverviews() method.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2000, Frank Warmerdam
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "gdal_priv.h"
      32                 : #define CPL_SERV_H_INCLUDED
      33                 : 
      34                 : #include "tiffio.h"
      35                 : #include "xtiffio.h"
      36                 : #include "geotiff.h"
      37                 : #include "gt_overview.h"
      38                 : 
      39                 : CPL_CVSID("$Id: gt_overview.cpp 19892 2010-06-19 08:54:44Z rouault $");
      40                 : 
      41                 : #define TIFFTAG_GDAL_METADATA  42112
      42                 : 
      43                 : #if !defined(PREDICTOR_NONE)
      44                 : #define PREDICTOR_NONE 1
      45                 : #endif
      46                 : 
      47                 : CPL_C_START
      48                 : void    GTiffOneTimeInit();
      49                 : void    GTIFFGetOverviewBlockSize(int* pnBlockXSize, int* pnBlockYSize);
      50                 : CPL_C_END
      51                 : 
      52                 : /************************************************************************/
      53                 : /*                         GTIFFWriteDirectory()                        */
      54                 : /*                                                                      */
      55                 : /*      Create a new directory, without any image data for an overview  */
      56                 : /*      or a mask                                                       */
      57                 : /*      Returns offset of newly created directory, but the              */
      58                 : /*      current directory is reset to be the one in used when this      */
      59                 : /*      function is called.                                             */
      60                 : /************************************************************************/
      61                 : 
      62                 : toff_t GTIFFWriteDirectory(TIFF *hTIFF, int nSubfileType, int nXSize, int nYSize,
      63                 :                            int nBitsPerPixel, int nPlanarConfig, int nSamples, 
      64                 :                            int nBlockXSize, int nBlockYSize,
      65                 :                            int bTiled, int nCompressFlag, int nPhotometric,
      66                 :                            int nSampleFormat, 
      67                 :                            int nPredictor,
      68                 :                            unsigned short *panRed,
      69                 :                            unsigned short *panGreen,
      70                 :                            unsigned short *panBlue,
      71                 :                            int nExtraSamples,
      72                 :                            unsigned short *panExtraSampleValues,
      73             171 :                            const char *pszMetadata )
      74                 : 
      75                 : {
      76                 :     toff_t  nBaseDirOffset;
      77                 :     toff_t  nOffset;
      78                 : 
      79             171 :     nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );
      80                 : 
      81                 : #if defined(TIFFLIB_VERSION) && TIFFLIB_VERSION >= 20051201 /* 3.8.0 */
      82             171 :     TIFFFreeDirectory( hTIFF );
      83                 : #endif
      84                 : 
      85             171 :     TIFFCreateDirectory( hTIFF );
      86                 :     
      87                 : /* -------------------------------------------------------------------- */
      88                 : /*      Setup TIFF fields.                                              */
      89                 : /* -------------------------------------------------------------------- */
      90             171 :     TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
      91             171 :     TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
      92             171 :     if( nSamples == 1 )
      93             119 :         TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
      94                 :     else
      95              52 :         TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, nPlanarConfig );
      96                 : 
      97             171 :     TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, nBitsPerPixel );
      98             171 :     TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nSamples );
      99             171 :     TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompressFlag );
     100             171 :     TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, nPhotometric );
     101             171 :     TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, nSampleFormat );
     102                 : 
     103             171 :     if( bTiled )
     104                 :     {
     105             166 :         TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize );
     106             166 :         TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize );
     107                 :     }
     108                 :     else
     109               5 :         TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nBlockYSize );
     110                 : 
     111             171 :     TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, nSubfileType );
     112                 : 
     113             171 :     if (panExtraSampleValues != NULL)
     114                 :     {
     115              16 :         TIFFSetField(hTIFF, TIFFTAG_EXTRASAMPLES, nExtraSamples, panExtraSampleValues );
     116                 :     }
     117                 : 
     118             171 :     if ( nCompressFlag == COMPRESSION_LZW ||
     119                 :          nCompressFlag == COMPRESSION_ADOBE_DEFLATE )
     120              14 :         TIFFSetField( hTIFF, TIFFTAG_PREDICTOR, nPredictor );
     121                 : 
     122                 : /* -------------------------------------------------------------------- */
     123                 : /*  Write color table if one is present.        */
     124                 : /* -------------------------------------------------------------------- */
     125             171 :     if( panRed != NULL )
     126                 :     {
     127              11 :         TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue );
     128                 :     }
     129                 : 
     130                 : /* -------------------------------------------------------------------- */
     131                 : /*      Write metadata if we have some.                                 */
     132                 : /* -------------------------------------------------------------------- */
     133             171 :     if( pszMetadata && strlen(pszMetadata) > 0 )
     134              16 :         TIFFSetField( hTIFF, TIFFTAG_GDAL_METADATA, pszMetadata );
     135                 : 
     136                 : /* -------------------------------------------------------------------- */
     137                 : /*      Write directory, and return byte offset.                        */
     138                 : /* -------------------------------------------------------------------- */
     139             171 :     if( TIFFWriteCheck( hTIFF, bTiled, "GTIFFWriteDirectory" ) == 0 )
     140                 :     {
     141               0 :         TIFFSetSubDirectory( hTIFF, nBaseDirOffset );
     142               0 :         return 0;
     143                 :     }
     144                 : 
     145             171 :     TIFFWriteDirectory( hTIFF );
     146             171 :     TIFFSetDirectory( hTIFF, (tdir_t) (TIFFNumberOfDirectories(hTIFF)-1) );
     147                 : 
     148             171 :     nOffset = TIFFCurrentDirOffset( hTIFF );
     149                 : 
     150             171 :     TIFFSetSubDirectory( hTIFF, nBaseDirOffset );
     151                 : 
     152             171 :     return nOffset;
     153                 : }
     154                 : 
     155                 : /************************************************************************/
     156                 : /*                     GTIFFBuildOverviewMetadata()                     */
     157                 : /************************************************************************/
     158                 : 
     159                 : void GTIFFBuildOverviewMetadata( const char *pszResampling,
     160                 :                                  GDALDataset *poBaseDS, 
     161             127 :                                  CPLString &osMetadata )
     162                 : 
     163                 : {
     164             127 :     osMetadata = "<GDALMetadata>";
     165                 : 
     166             254 :     if( pszResampling && EQUALN(pszResampling,"AVERAGE_BIT2",12) )
     167               4 :         osMetadata += "<Item name=\"RESAMPLING\" sample=\"0\">AVERAGE_BIT2GRAYSCALE</Item>";
     168                 : 
     169             127 :     if( poBaseDS->GetMetadataItem( "INTERNAL_MASK_FLAGS_1" ) )
     170                 :     {
     171                 :         int iBand;
     172                 : 
     173             201 :         for( iBand = 0; iBand < 200; iBand++ )
     174                 :         {
     175             200 :             CPLString osItem;
     176             200 :             CPLString osName;
     177                 : 
     178             200 :             osName.Printf( "INTERNAL_MASK_FLAGS_%d", iBand+1 );
     179             200 :             if( poBaseDS->GetMetadataItem( osName ) )
     180                 :             {
     181                 :                 osItem.Printf( "<Item name=\"%s\">%s</Item>", 
     182                 :                                osName.c_str(), 
     183               3 :                                poBaseDS->GetMetadataItem( osName ) );
     184               3 :                 osMetadata += osItem;
     185                 :             }
     186                 :         }
     187                 :     }
     188                 : 
     189             127 :     const char* pszNoDataValues = poBaseDS->GetMetadataItem("NODATA_VALUES");
     190             127 :     if (pszNoDataValues)
     191                 :     {
     192               6 :         CPLString osItem;
     193               6 :         osItem.Printf( "<Item name=\"NODATA_VALUES\">%s</Item>", pszNoDataValues );
     194               6 :         osMetadata += osItem;
     195                 :     }
     196                 : 
     197             127 :     if( !EQUAL(osMetadata,"<GDALMetadata>") )
     198              11 :         osMetadata += "</GDALMetadata>";
     199                 :     else
     200             116 :         osMetadata = "";
     201             127 : }
     202                 : 
     203                 : /************************************************************************/
     204                 : /*                        GTIFFBuildOverviews()                         */
     205                 : /************************************************************************/
     206                 : 
     207                 : CPLErr 
     208                 : GTIFFBuildOverviews( const char * pszFilename,
     209                 :                      int nBands, GDALRasterBand **papoBandList, 
     210                 :                      int nOverviews, int * panOverviewList,
     211                 :                      const char * pszResampling, 
     212              70 :                      GDALProgressFunc pfnProgress, void * pProgressData )
     213                 : 
     214                 : {
     215                 :     TIFF    *hOTIFF;
     216              70 :     int     nBitsPerPixel=0, nCompression=COMPRESSION_NONE, nPhotometric=0;
     217              70 :     int     nSampleFormat=0, nPlanarConfig, iOverview, iBand;
     218              70 :     int     nXSize=0, nYSize=0;
     219                 : 
     220              70 :     if( nBands == 0 || nOverviews == 0 )
     221               0 :         return CE_None;
     222                 : 
     223              70 :     GTiffOneTimeInit();
     224                 : 
     225                 : /* -------------------------------------------------------------------- */
     226                 : /*      Verify that the list of bands is suitable for emitting in       */
     227                 : /*      TIFF file.                                                      */
     228                 : /* -------------------------------------------------------------------- */
     229             171 :     for( iBand = 0; iBand < nBands; iBand++ )
     230                 :     {
     231                 :         int     nBandBits, nBandFormat;
     232             101 :         GDALRasterBand *hBand = papoBandList[iBand];
     233                 : 
     234             101 :         switch( hBand->GetRasterDataType() )
     235                 :         {
     236                 :           case GDT_Byte:
     237              55 :             nBandBits = 8;
     238              55 :             nBandFormat = SAMPLEFORMAT_UINT;
     239              55 :             break;
     240                 : 
     241                 :           case GDT_UInt16:
     242               4 :             nBandBits = 16;
     243               4 :             nBandFormat = SAMPLEFORMAT_UINT;
     244               4 :             break;
     245                 : 
     246                 :           case GDT_Int16:
     247               4 :             nBandBits = 16;
     248               4 :             nBandFormat = SAMPLEFORMAT_INT;
     249               4 :             break;
     250                 : 
     251                 :           case GDT_UInt32:
     252               2 :             nBandBits = 32;
     253               2 :             nBandFormat = SAMPLEFORMAT_UINT;
     254               2 :             break;
     255                 : 
     256                 :           case GDT_Int32:
     257               3 :             nBandBits = 32;
     258               3 :             nBandFormat = SAMPLEFORMAT_INT;
     259               3 :             break;
     260                 : 
     261                 :           case GDT_Float32:
     262              23 :             nBandBits = 32;
     263              23 :             nBandFormat = SAMPLEFORMAT_IEEEFP;
     264              23 :             break;
     265                 : 
     266                 :           case GDT_Float64:
     267               2 :             nBandBits = 64;
     268               2 :             nBandFormat = SAMPLEFORMAT_IEEEFP;
     269               2 :             break;
     270                 : 
     271                 :           case GDT_CInt16:
     272               2 :             nBandBits = 32;
     273               2 :             nBandFormat = SAMPLEFORMAT_COMPLEXINT;
     274               2 :             break;
     275                 : 
     276                 :           case GDT_CInt32:
     277               2 :             nBandBits = 64;
     278               2 :             nBandFormat = SAMPLEFORMAT_COMPLEXINT;
     279               2 :             break;
     280                 : 
     281                 :           case GDT_CFloat32:
     282               2 :             nBandBits = 64;
     283               2 :             nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
     284               2 :             break;
     285                 : 
     286                 :           case GDT_CFloat64:
     287               2 :             nBandBits = 128;
     288               2 :             nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
     289               2 :             break;
     290                 : 
     291                 :           default:
     292               0 :             CPLAssert( FALSE );
     293               0 :             return CE_Failure;
     294                 :         }
     295                 : 
     296             101 :         if( hBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) )
     297                 :         {
     298                 :             nBandBits = 
     299               8 :                 atoi(hBand->GetMetadataItem("NBITS","IMAGE_STRUCTURE"));
     300                 : 
     301               8 :             if( nBandBits == 1 
     302                 :                 && EQUALN(pszResampling,"AVERAGE_BIT2",12) )
     303               4 :                 nBandBits = 8;
     304                 :         }
     305                 : 
     306             101 :         if( iBand == 0 )
     307                 :         {
     308              70 :             nBitsPerPixel = nBandBits;
     309              70 :             nSampleFormat = nBandFormat;
     310              70 :             nXSize = hBand->GetXSize();
     311              70 :             nYSize = hBand->GetYSize();
     312                 :         }
     313              31 :         else if( nBitsPerPixel != nBandBits || nSampleFormat != nBandFormat )
     314                 :         {
     315                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     316                 :                       "GTIFFBuildOverviews() doesn't support a mixture of band"
     317               0 :                       " data types." );
     318               0 :             return CE_Failure;
     319                 :         }
     320              31 :         else if( hBand->GetColorTable() != NULL )
     321                 :         {
     322                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     323                 :                       "GTIFFBuildOverviews() doesn't support building"
     324               0 :                       " overviews of multiple colormapped bands." );
     325               0 :             return CE_Failure;
     326                 :         }
     327              31 :         else if( hBand->GetXSize() != nXSize 
     328                 :                  || hBand->GetYSize() != nYSize )
     329                 :         {
     330                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     331                 :                       "GTIFFBuildOverviews() doesn't support building"
     332               0 :                       " overviews of different sized bands." );
     333               0 :             return CE_Failure;
     334                 :         }
     335                 :     }
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Use specified compression method.                               */
     339                 : /* -------------------------------------------------------------------- */
     340              70 :     const char *pszCompress = CPLGetConfigOption( "COMPRESS_OVERVIEW", NULL );
     341                 : 
     342              70 :     if( pszCompress != NULL && pszCompress[0] != '\0' )
     343                 :     {
     344               9 :         if( EQUAL( pszCompress, "JPEG" ) )
     345               5 :             nCompression = COMPRESSION_JPEG;
     346               4 :         else if( EQUAL( pszCompress, "LZW" ) )
     347               2 :             nCompression = COMPRESSION_LZW;
     348               2 :         else if( EQUAL( pszCompress, "PACKBITS" ))
     349               0 :             nCompression = COMPRESSION_PACKBITS;
     350               4 :         else if( EQUAL( pszCompress, "DEFLATE" ) || EQUAL( pszCompress, "ZIP" ))
     351               2 :             nCompression = COMPRESSION_ADOBE_DEFLATE;
     352                 :         else
     353                 :             CPLError( CE_Warning, CPLE_IllegalArg, 
     354                 :                       "COMPRESS_OVERVIEW=%s value not recognised, ignoring.",
     355               0 :                       pszCompress );
     356                 :     }
     357                 :     
     358              70 :     if( nCompression == COMPRESSION_JPEG && nBitsPerPixel == 16 )
     359               2 :         nBitsPerPixel = 12;
     360                 : 
     361                 : /* -------------------------------------------------------------------- */
     362                 : /*      Figure out the planar configuration to use.                     */
     363                 : /* -------------------------------------------------------------------- */
     364              70 :     if( nBands == 1 )
     365              53 :         nPlanarConfig = PLANARCONFIG_CONTIG;
     366                 :     else
     367              17 :         nPlanarConfig = PLANARCONFIG_SEPARATE;
     368                 : 
     369              70 :     const char* pszInterleave = CPLGetConfigOption( "INTERLEAVE_OVERVIEW", NULL );
     370              70 :     if (pszInterleave != NULL && pszInterleave[0] != '\0')
     371                 :     {
     372               0 :         if( EQUAL( pszInterleave, "PIXEL" ) )
     373               0 :             nPlanarConfig = PLANARCONFIG_CONTIG;
     374               0 :         else if( EQUAL( pszInterleave, "BAND" ) )
     375               0 :             nPlanarConfig = PLANARCONFIG_SEPARATE;
     376                 :         else
     377                 :         {
     378                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     379                 :                       "INTERLEAVE_OVERVIEW=%s unsupported, value must be PIXEL or BAND. ignoring",
     380               0 :                       pszInterleave );
     381                 :         }
     382                 :     }
     383                 : 
     384                 : /* -------------------------------------------------------------------- */
     385                 : /*      Figure out the photometric interpretation to use.               */
     386                 : /* -------------------------------------------------------------------- */
     387              70 :     if( nBands == 3 )
     388              12 :         nPhotometric = PHOTOMETRIC_RGB;
     389              58 :     else if( papoBandList[0]->GetColorTable() != NULL 
     390                 :              && !EQUALN(pszResampling,"AVERAGE_BIT2",12) )
     391                 :     {
     392               2 :         nPhotometric = PHOTOMETRIC_PALETTE;
     393                 :         /* should set the colormap up at this point too! */
     394                 :     }
     395                 :     else
     396              56 :         nPhotometric = PHOTOMETRIC_MINISBLACK;
     397                 : 
     398              70 :     const char* pszPhotometric = CPLGetConfigOption( "PHOTOMETRIC_OVERVIEW", NULL );
     399              70 :     if (pszPhotometric != NULL && pszPhotometric[0] != '\0')
     400                 :     {
     401               2 :         if( EQUAL( pszPhotometric, "MINISBLACK" ) )
     402               0 :             nPhotometric = PHOTOMETRIC_MINISBLACK;
     403               2 :         else if( EQUAL( pszPhotometric, "MINISWHITE" ) )
     404               0 :             nPhotometric = PHOTOMETRIC_MINISWHITE;
     405               2 :         else if( EQUAL( pszPhotometric, "RGB" ))
     406                 :         {
     407               0 :             nPhotometric = PHOTOMETRIC_RGB;
     408                 :         }
     409               2 :         else if( EQUAL( pszPhotometric, "CMYK" ))
     410                 :         {
     411               0 :             nPhotometric = PHOTOMETRIC_SEPARATED;
     412                 :         }
     413               2 :         else if( EQUAL( pszPhotometric, "YCBCR" ))
     414                 :         {
     415               2 :             nPhotometric = PHOTOMETRIC_YCBCR;
     416                 : 
     417                 :             /* Because of subsampling, setting YCBCR without JPEG compression leads */
     418                 :             /* to a crash currently. Would need to make GTiffRasterBand::IWriteBlock() */
     419                 :             /* aware of subsampling so that it doesn't overrun buffer size returned */
     420                 :             /* by libtiff */
     421               2 :             if ( nCompression != COMPRESSION_JPEG )
     422                 :             {
     423                 :                 CPLError(CE_Failure, CPLE_NotSupported,
     424               0 :                          "Currently, PHOTOMETRIC_OVERVIEW=YCBCR requires COMPRESS_OVERVIEW=JPEG");
     425               0 :                 return CE_Failure;
     426                 :             }
     427                 : 
     428               2 :             if (pszInterleave != NULL && pszInterleave[0] != '\0' && nPlanarConfig == PLANARCONFIG_SEPARATE)
     429                 :             {
     430                 :                 CPLError(CE_Failure, CPLE_NotSupported,
     431               0 :                          "PHOTOMETRIC_OVERVIEW=YCBCR requires INTERLEAVE_OVERVIEW=PIXEL");
     432               0 :                 return CE_Failure;
     433                 :             }
     434                 :             else
     435                 :             {
     436               2 :                 nPlanarConfig = PLANARCONFIG_CONTIG;
     437                 :             }
     438                 : 
     439                 :             /* YCBCR strictly requires 3 bands. Not less, not more */
     440                 :             /* Issue an explicit error message as libtiff one is a bit cryptic : */
     441                 :             /* JPEGLib:Bogus input colorspace */
     442               2 :             if ( nBands != 3 )
     443                 :             {
     444                 :                 CPLError(CE_Failure, CPLE_NotSupported,
     445               0 :                          "PHOTOMETRIC_OVERVIEW=YCBCR requires a source raster with only 3 bands (RGB)");
     446               0 :                 return CE_Failure;
     447                 :             }
     448                 :         }
     449               0 :         else if( EQUAL( pszPhotometric, "CIELAB" ))
     450                 :         {
     451               0 :             nPhotometric = PHOTOMETRIC_CIELAB;
     452                 :         }
     453               0 :         else if( EQUAL( pszPhotometric, "ICCLAB" ))
     454                 :         {
     455               0 :             nPhotometric = PHOTOMETRIC_ICCLAB;
     456                 :         }
     457               0 :         else if( EQUAL( pszPhotometric, "ITULAB" ))
     458                 :         {
     459               0 :             nPhotometric = PHOTOMETRIC_ITULAB;
     460                 :         }
     461                 :         else
     462                 :         {
     463                 :             CPLError( CE_Warning, CPLE_IllegalArg, 
     464                 :                       "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.\n",
     465               0 :                       pszPhotometric );
     466                 :         }
     467                 :     }
     468                 : 
     469                 : /* -------------------------------------------------------------------- */
     470                 : /*      Figure out the predictor value to use.                          */
     471                 : /* -------------------------------------------------------------------- */
     472              70 :     int nPredictor = PREDICTOR_NONE;
     473              70 :     if ( nCompression == COMPRESSION_LZW ||
     474                 :          nCompression == COMPRESSION_ADOBE_DEFLATE )
     475                 :     {
     476               4 :         const char* pszPredictor = CPLGetConfigOption( "PREDICTOR_OVERVIEW", NULL );
     477               4 :         if( pszPredictor  != NULL )
     478                 :         {
     479               2 :             nPredictor =  atoi( pszPredictor );
     480                 :         }
     481                 :     }
     482                 : 
     483                 : /* -------------------------------------------------------------------- */
     484                 : /*      Create the file, if it does not already exist.                  */
     485                 : /* -------------------------------------------------------------------- */
     486                 :     VSIStatBufL  sStatBuf;
     487                 : 
     488              70 :     if( VSIStatL( pszFilename, &sStatBuf ) != 0 )
     489                 :     {
     490                 :     /* -------------------------------------------------------------------- */
     491                 :     /*      Compute the uncompressed size.                                  */
     492                 :     /* -------------------------------------------------------------------- */
     493              70 :         double  dfUncompressedOverviewSize = 0;
     494              70 :         int nDataTypeSize = GDALGetDataTypeSize(papoBandList[0]->GetRasterDataType())/8;
     495                 : 
     496             157 :         for( iOverview = 0; iOverview < nOverviews; iOverview++ )
     497                 :         {
     498                 :             int    nOXSize, nOYSize;
     499                 : 
     500                 :             nOXSize = (nXSize + panOverviewList[iOverview] - 1) 
     501              87 :                 / panOverviewList[iOverview];
     502                 :             nOYSize = (nYSize + panOverviewList[iOverview] - 1) 
     503              87 :                 / panOverviewList[iOverview];
     504                 : 
     505                 :             dfUncompressedOverviewSize += 
     506              87 :                 nOXSize * ((double)nOYSize) * nBands * nDataTypeSize;
     507                 :         }
     508                 : 
     509                 :         if( nCompression == COMPRESSION_NONE 
     510                 :             && dfUncompressedOverviewSize > 4200000000.0 )
     511                 :         {
     512                 :     #ifndef BIGTIFF_SUPPORT
     513                 :             CPLError( CE_Failure, CPLE_NotSupported, 
     514                 :                     "The overview file would be larger than 4GB\n"
     515                 :                     "but this is the largest size a TIFF can be, and BigTIFF is unavailable.\n"
     516                 :                     "Creation failed." );
     517                 :             return CE_Failure;
     518                 :     #endif
     519                 :         }
     520                 :     /* -------------------------------------------------------------------- */
     521                 :     /*      Should the file be created as a bigtiff file?                   */
     522                 :     /* -------------------------------------------------------------------- */
     523              70 :         const char *pszBIGTIFF = CPLGetConfigOption( "BIGTIFF_OVERVIEW", NULL );
     524                 : 
     525              70 :         if( pszBIGTIFF == NULL )
     526              10 :             pszBIGTIFF = "IF_NEEDED";
     527                 : 
     528              70 :         int bCreateBigTIFF = FALSE;
     529              70 :         if( EQUAL(pszBIGTIFF,"IF_NEEDED") )
     530                 :         {
     531              62 :             if( nCompression == COMPRESSION_NONE 
     532                 :                 && dfUncompressedOverviewSize > 4200000000.0 )
     533               2 :                 bCreateBigTIFF = TRUE;
     534                 :         }
     535               8 :         else if( EQUAL(pszBIGTIFF,"IF_SAFER") )
     536                 :         {
     537                 :             /* Look at the size of the base image and suppose that */
     538                 :             /* the added overview levels won't be more than 1/2 of */
     539                 :             /* the size of the base image. The theory says 1/3 of the */
     540                 :             /* base image size if the overview levels are 2, 4, 8, 16... */
     541                 :             /* Thus take 1/2 as the security margin for 1/3 */
     542                 :             double dfUncompressedImageSize =
     543               2 :                         nXSize * ((double)nYSize) * nBands * nDataTypeSize;
     544               2 :             if( dfUncompressedImageSize * .5 > 4200000000.0 )
     545               2 :                 bCreateBigTIFF = TRUE;
     546                 :         }
     547                 :         else
     548                 :         {
     549               6 :             bCreateBigTIFF = CSLTestBoolean( pszBIGTIFF );
     550               6 :             if (!bCreateBigTIFF && nCompression == COMPRESSION_NONE 
     551                 :                 && dfUncompressedOverviewSize > 4200000000.0 )
     552                 :             {
     553                 :                 CPLError( CE_Failure, CPLE_NotSupported, 
     554                 :                     "The overview file will be larger than 4GB, so BigTIFF is necessary.\n"
     555               2 :                     "Creation failed.");
     556               2 :                 return CE_Failure;
     557                 :             }
     558                 :         }
     559                 : 
     560                 :     #ifndef BIGTIFF_SUPPORT
     561                 :         if( bCreateBigTIFF )
     562                 :         {
     563                 :             CPLError( CE_Warning, CPLE_NotSupported,
     564                 :                     "BigTIFF requested, but GDAL built without BigTIFF\n"
     565                 :                     "enabled libtiff, request ignored." );
     566                 :             bCreateBigTIFF = FALSE;
     567                 :         }
     568                 :     #endif
     569                 : 
     570              68 :         if( bCreateBigTIFF )
     571               6 :             CPLDebug( "GTiff", "File being created as a BigTIFF." );
     572                 : 
     573              68 :         hOTIFF = XTIFFOpen( pszFilename, (bCreateBigTIFF) ? "w+8" : "w+" );
     574              68 :         if( hOTIFF == NULL )
     575                 :         {
     576               0 :             if( CPLGetLastErrorNo() == 0 )
     577                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     578                 :                           "Attempt to create new tiff file `%s'\n"
     579                 :                           "failed in XTIFFOpen().\n",
     580               0 :                           pszFilename );
     581                 : 
     582               0 :             return CE_Failure;
     583                 :         }
     584                 :     }
     585                 : /* -------------------------------------------------------------------- */
     586                 : /*      Otherwise just open it for update access.                       */
     587                 : /* -------------------------------------------------------------------- */
     588                 :     else 
     589                 :     {
     590               0 :         hOTIFF = XTIFFOpen( pszFilename, "r+" );
     591               0 :         if( hOTIFF == NULL )
     592                 :         {
     593               0 :             if( CPLGetLastErrorNo() == 0 )
     594                 :                 CPLError( CE_Failure, CPLE_OpenFailed,
     595                 :                           "Attempt to create new tiff file `%s'\n"
     596                 :                           "failed in XTIFFOpen().\n",
     597               0 :                           pszFilename );
     598                 : 
     599               0 :             return CE_Failure;
     600                 :         }
     601                 :     }
     602                 : 
     603                 : /* -------------------------------------------------------------------- */
     604                 : /*      Do we have a palette?  If so, create a TIFF compatible version. */
     605                 : /* -------------------------------------------------------------------- */
     606              68 :     unsigned short      *panRed=NULL, *panGreen=NULL, *panBlue=NULL;
     607                 : 
     608              68 :     if( nPhotometric == PHOTOMETRIC_PALETTE )
     609                 :     {
     610               2 :         GDALColorTable *poCT = papoBandList[0]->GetColorTable();
     611                 :         int nColorCount;
     612                 : 
     613               2 :         if( nBitsPerPixel <= 8 )
     614               2 :             nColorCount = 256;
     615                 :         else
     616               0 :             nColorCount = 65536;
     617                 : 
     618                 :         panRed   = (unsigned short *) 
     619               2 :             CPLCalloc(nColorCount,sizeof(unsigned short));
     620                 :         panGreen = (unsigned short *) 
     621               2 :             CPLCalloc(nColorCount,sizeof(unsigned short));
     622                 :         panBlue  = (unsigned short *) 
     623               2 :             CPLCalloc(nColorCount,sizeof(unsigned short));
     624                 : 
     625             514 :         for( int iColor = 0; iColor < nColorCount; iColor++ )
     626                 :         {
     627                 :             GDALColorEntry  sRGB;
     628                 : 
     629             512 :             if( poCT->GetColorEntryAsRGB( iColor, &sRGB ) )
     630                 :             {
     631             512 :                 panRed[iColor] = (unsigned short) (257 * sRGB.c1);
     632             512 :                 panGreen[iColor] = (unsigned short) (257 * sRGB.c2);
     633             512 :                 panBlue[iColor] = (unsigned short) (257 * sRGB.c3);
     634                 :             }
     635                 :         }
     636                 :     }
     637                 : 
     638                 : /* -------------------------------------------------------------------- */
     639                 : /*      Do we need some metadata for the overviews?                     */
     640                 : /* -------------------------------------------------------------------- */
     641              68 :     CPLString osMetadata;
     642              68 :     GDALDataset *poBaseDS = papoBandList[0]->GetDataset();
     643                 : 
     644              68 :     GTIFFBuildOverviewMetadata( pszResampling, poBaseDS, osMetadata );
     645                 : 
     646                 : /* -------------------------------------------------------------------- */
     647                 : /*      Loop, creating overviews.                                       */
     648                 : /* -------------------------------------------------------------------- */
     649                 :     int nOvrBlockXSize, nOvrBlockYSize;
     650              68 :     GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize);
     651             153 :     for( iOverview = 0; iOverview < nOverviews; iOverview++ )
     652                 :     {
     653                 :         int    nOXSize, nOYSize;
     654                 : 
     655                 :         nOXSize = (nXSize + panOverviewList[iOverview] - 1) 
     656              85 :             / panOverviewList[iOverview];
     657                 :         nOYSize = (nYSize + panOverviewList[iOverview] - 1) 
     658              85 :             / panOverviewList[iOverview];
     659                 : 
     660                 :         GTIFFWriteDirectory(hOTIFF, FILETYPE_REDUCEDIMAGE,
     661                 :                             nOXSize, nOYSize, nBitsPerPixel, 
     662                 :                             nPlanarConfig, nBands,
     663                 :                             nOvrBlockXSize, nOvrBlockYSize, TRUE, nCompression,
     664                 :                             nPhotometric, nSampleFormat, nPredictor,
     665                 :                             panRed, panGreen, panBlue,
     666                 :                             0, NULL, /* FIXME? how can we fetch extrasamples */
     667              85 :                             osMetadata );
     668                 :     }
     669                 : 
     670              68 :     if (panRed)
     671                 :     {
     672               2 :         CPLFree(panRed);
     673               2 :         CPLFree(panGreen);
     674               2 :         CPLFree(panBlue);
     675               2 :         panRed = panGreen = panBlue = NULL;
     676                 :     }
     677                 : 
     678              68 :     XTIFFClose( hOTIFF );
     679                 : 
     680                 : /* -------------------------------------------------------------------- */
     681                 : /*      Open the overview dataset so that we can get at the overview    */
     682                 : /*      bands.                                                          */
     683                 : /* -------------------------------------------------------------------- */
     684                 :     GDALDataset *hODS;
     685              68 :     CPLErr eErr = CE_None;
     686                 : 
     687              68 :     hODS = (GDALDataset *) GDALOpen( pszFilename, GA_Update );
     688              68 :     if( hODS == NULL )
     689              68 :         return CE_Failure;
     690                 :     
     691                 : /* -------------------------------------------------------------------- */
     692                 : /*      Do we need to set the jpeg quality?                             */
     693                 : /* -------------------------------------------------------------------- */
     694              68 :     TIFF *hTIFF = (TIFF*) hODS->GetInternalHandle(NULL);
     695                 : 
     696              68 :     if( nCompression == COMPRESSION_JPEG 
     697                 :         && CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL )
     698                 :     {
     699                 :         TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, 
     700               1 :                       atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75")) );
     701                 :     }
     702                 : 
     703                 : /* -------------------------------------------------------------------- */
     704                 : /*      Loop writing overview data.                                     */
     705                 : /* -------------------------------------------------------------------- */
     706                 : 
     707              68 :     if (nCompression != COMPRESSION_NONE &&
     708                 :         nPlanarConfig == PLANARCONFIG_CONTIG &&
     709                 :         GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) == FALSE &&
     710                 :         papoBandList[0]->GetColorTable() == NULL &&
     711                 :         (EQUALN(pszResampling, "NEAR", 4) || EQUAL(pszResampling, "AVERAGE") || EQUAL(pszResampling, "GAUSS")))
     712                 :     {
     713                 :         /* In the case of pixel interleaved compressed overviews, we want to generate */
     714                 :         /* the overviews for all the bands block by block, and not band after band, */
     715                 :         /* in order to write the block once and not loose space in the TIFF file */
     716                 :         GDALRasterBand ***papapoOverviewBands;
     717                 : 
     718               6 :         papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands);
     719              16 :         for( iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
     720                 :         {
     721              10 :             GDALRasterBand    *hDstBand = hODS->GetRasterBand( iBand+1 );
     722              10 :             papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews);
     723              10 :             papapoOverviewBands[iBand][0] = hDstBand;
     724              10 :             for( int i = 0; i < nOverviews-1 && eErr == CE_None; i++ )
     725                 :             {
     726               0 :                 papapoOverviewBands[iBand][i+1] = hDstBand->GetOverview(i);
     727               0 :                 if (papapoOverviewBands[iBand][i+1] == NULL)
     728               0 :                     eErr = CE_Failure;
     729                 :             }
     730                 :         }
     731                 : 
     732               6 :         if (eErr == CE_None)
     733                 :             eErr = GDALRegenerateOverviewsMultiBand(nBands, papoBandList,
     734                 :                                             nOverviews, papapoOverviewBands,
     735               6 :                                             pszResampling, pfnProgress, pProgressData );
     736                 : 
     737              16 :         for( iBand = 0; iBand < nBands; iBand++ )
     738                 :         {
     739              10 :             CPLFree(papapoOverviewBands[iBand]);
     740                 :         }
     741               6 :         CPLFree(papapoOverviewBands);
     742                 :     }
     743                 :     else
     744                 :     {
     745                 :         GDALRasterBand   **papoOverviews;
     746                 : 
     747              62 :         papoOverviews = (GDALRasterBand **) CPLCalloc(sizeof(void*),128);
     748                 : 
     749             151 :         for( iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
     750                 :         {
     751              89 :             GDALRasterBand    *hSrcBand = papoBandList[iBand];
     752                 :             GDALRasterBand    *hDstBand;
     753                 :             int               nDstOverviews;
     754                 : 
     755              89 :             hDstBand = hODS->GetRasterBand( iBand+1 );
     756                 : 
     757              89 :             papoOverviews[0] = hDstBand;
     758              89 :             nDstOverviews = hDstBand->GetOverviewCount() + 1;
     759              89 :             CPLAssert( nDstOverviews < 128 );
     760              89 :             nDstOverviews = MIN(128,nDstOverviews);
     761                 : 
     762             127 :             for( int i = 0; i < nDstOverviews-1 && eErr == CE_None; i++ )
     763                 :             {
     764              38 :                 papoOverviews[i+1] = hDstBand->GetOverview(i);
     765              38 :                 if (papoOverviews[i+1] == NULL)
     766               0 :                     eErr = CE_Failure;
     767                 :             }
     768                 : 
     769                 :             void         *pScaledProgressData;
     770                 : 
     771                 :             pScaledProgressData = 
     772                 :                 GDALCreateScaledProgress( iBand / (double) nBands, 
     773                 :                                         (iBand+1) / (double) nBands,
     774              89 :                                         pfnProgress, pProgressData );
     775                 : 
     776              89 :             if (eErr == CE_None)
     777                 :                 eErr = 
     778                 :                     GDALRegenerateOverviews( (GDALRasterBandH) hSrcBand, 
     779                 :                                         nDstOverviews, 
     780                 :                                         (GDALRasterBandH *) papoOverviews, 
     781                 :                                         pszResampling,
     782                 :                                         GDALScaledProgress, 
     783              89 :                                         pScaledProgressData);
     784                 : 
     785              89 :             GDALDestroyScaledProgress( pScaledProgressData );
     786                 :         }
     787                 : 
     788              62 :         CPLFree( papoOverviews );
     789                 :     }
     790                 : 
     791                 : /* -------------------------------------------------------------------- */
     792                 : /*      Cleanup                                                         */
     793                 : /* -------------------------------------------------------------------- */
     794              68 :     if (eErr == CE_None)
     795              68 :         hODS->FlushCache();
     796              68 :     delete hODS;
     797                 : 
     798              68 :     pfnProgress( 1.0, NULL, pProgressData );
     799                 : 
     800              68 :     return eErr;
     801                 : }
     802                 :     

Generated by: LTP GCOV extension version 1.5