LCOV - code coverage report
Current view: directory - frmts/gtiff - gt_overview.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 282 189 67.0 %
Date: 2010-01-09 Functions: 3 3 100.0 %

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

Generated by: LCOV version 1.7