LCOV - code coverage report
Current view: directory - frmts/gtiff - gt_overview.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 305 256 83.9 %
Date: 2012-12-26 Functions: 3 3 100.0 %

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

Generated by: LCOV version 1.7