LCOV - code coverage report
Current view: directory - frmts/webp - webpdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 216 155 71.8 %
Date: 2011-12-18 Functions: 18 12 66.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: webpdataset.cpp 22043 2011-03-26 12:14:11Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL WEBP Driver
       5                 :  * Purpose:  Implement GDAL WEBP Support based on libwebp
       6                 :  * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2011, Even Rouault
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "gdal_pam.h"
      31                 : #include "cpl_string.h"
      32                 : 
      33                 : #include "webp/decode.h"
      34                 : #include "webp/encode.h"
      35                 : 
      36                 : CPL_CVSID("$Id: webpdataset.cpp 22043 2011-03-26 12:14:11Z rouault $");
      37                 : 
      38                 : CPL_C_START
      39                 : void    GDALRegister_WEBP(void);
      40                 : CPL_C_END
      41                 : 
      42                 : /************************************************************************/
      43                 : /* ==================================================================== */
      44                 : /*                               WEBPDataset                            */
      45                 : /* ==================================================================== */
      46                 : /************************************************************************/
      47                 : 
      48                 : class WEBPRasterBand;
      49                 : 
      50                 : class WEBPDataset : public GDALPamDataset
      51                 : {
      52                 :     friend class WEBPRasterBand;
      53                 : 
      54                 :     VSILFILE*   fpImage;
      55                 :     GByte* pabyUncompressed;
      56                 :     int    bHasBeenUncompressed;
      57                 :     CPLErr Uncompress();
      58                 : 
      59                 :   public:
      60                 :                  WEBPDataset();
      61                 :                  ~WEBPDataset();
      62                 : 
      63                 :     virtual CPLErr      IRasterIO( GDALRWFlag, int, int, int, int,
      64                 :                                    void *, int, int, GDALDataType,
      65                 :                                    int, int *, int, int, int );
      66                 : 
      67                 :     static GDALDataset *Open( GDALOpenInfo * );
      68                 :     static int          Identify( GDALOpenInfo * );
      69                 :     static GDALDataset* CreateCopy( const char * pszFilename,
      70                 :                                     GDALDataset *poSrcDS,
      71                 :                                     int bStrict, char ** papszOptions,
      72                 :                                     GDALProgressFunc pfnProgress,
      73                 :                                     void * pProgressData );
      74                 : };
      75                 : 
      76                 : /************************************************************************/
      77                 : /* ==================================================================== */
      78                 : /*                            WEBPRasterBand                            */
      79                 : /* ==================================================================== */
      80                 : /************************************************************************/
      81                 : 
      82                 : class WEBPRasterBand : public GDALPamRasterBand
      83              15 : {
      84                 :     friend class WEBPDataset;
      85                 : 
      86                 :   public:
      87                 : 
      88                 :                    WEBPRasterBand( WEBPDataset *, int );
      89                 : 
      90                 :     virtual CPLErr IReadBlock( int, int, void * );
      91                 :     virtual GDALColorInterp GetColorInterpretation();
      92                 : };
      93                 : 
      94                 : /************************************************************************/
      95                 : /*                          WEBPRasterBand()                            */
      96                 : /************************************************************************/
      97                 : 
      98              15 : WEBPRasterBand::WEBPRasterBand( WEBPDataset *poDS, int nBand )
      99                 : 
     100                 : {
     101              15 :     this->poDS = poDS;
     102                 : 
     103              15 :     eDataType = GDT_Byte;
     104                 : 
     105              15 :     nBlockXSize = poDS->nRasterXSize;
     106              15 :     nBlockYSize = 1;
     107              15 : }
     108                 : 
     109                 : /************************************************************************/
     110                 : /*                             IReadBlock()                             */
     111                 : /************************************************************************/
     112                 : 
     113             150 : CPLErr WEBPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     114                 :                                   void * pImage )
     115                 : 
     116                 : {
     117             150 :     WEBPDataset* poGDS = (WEBPDataset*) poDS;
     118                 : 
     119             150 :     poGDS->Uncompress();
     120                 : 
     121                 :     int i;
     122                 :     GByte* pabyUncompressed =
     123             150 :         &poGDS->pabyUncompressed[nBlockYOff * nRasterXSize  * 3 + nBand - 1];
     124            7650 :     for(i=0;i<nRasterXSize;i++)
     125            7500 :         ((GByte*)pImage)[i] = pabyUncompressed[3 * i];
     126                 : 
     127             150 :     return CE_None;
     128                 : }
     129                 : 
     130                 : /************************************************************************/
     131                 : /*                       GetColorInterpretation()                       */
     132                 : /************************************************************************/
     133                 : 
     134               6 : GDALColorInterp WEBPRasterBand::GetColorInterpretation()
     135                 : 
     136                 : {
     137               6 :     if ( nBand == 1 )
     138               2 :         return GCI_RedBand;
     139                 : 
     140               4 :     else if( nBand == 2 )
     141               2 :         return GCI_GreenBand;
     142                 : 
     143               2 :     else if ( nBand == 3 )
     144               2 :         return GCI_BlueBand;
     145                 : 
     146                 :     else
     147               0 :         return GCI_AlphaBand;
     148                 : }
     149                 : 
     150                 : /************************************************************************/
     151                 : /* ==================================================================== */
     152                 : /*                             WEBPDataset                               */
     153                 : /* ==================================================================== */
     154                 : /************************************************************************/
     155                 : 
     156                 : 
     157                 : /************************************************************************/
     158                 : /*                            WEBPDataset()                              */
     159                 : /************************************************************************/
     160                 : 
     161               5 : WEBPDataset::WEBPDataset()
     162                 : 
     163                 : {
     164               5 :     fpImage = NULL;
     165               5 :     pabyUncompressed = NULL;
     166               5 :     bHasBeenUncompressed = FALSE;
     167               5 : }
     168                 : 
     169                 : /************************************************************************/
     170                 : /*                           ~WEBPDataset()                             */
     171                 : /************************************************************************/
     172                 : 
     173               5 : WEBPDataset::~WEBPDataset()
     174                 : 
     175                 : {
     176               5 :     FlushCache();
     177               5 :     if (fpImage)
     178               5 :         VSIFCloseL(fpImage);
     179               5 :     VSIFree(pabyUncompressed);
     180               5 : }
     181                 : 
     182                 : /************************************************************************/
     183                 : /*                            Uncompress()                              */
     184                 : /************************************************************************/
     185                 : 
     186             150 : CPLErr WEBPDataset::Uncompress()
     187                 : {
     188             150 :     if (bHasBeenUncompressed)
     189             147 :         return CE_None;
     190               3 :     bHasBeenUncompressed = TRUE;
     191                 : 
     192               3 :     VSIFSeekL(fpImage, 0, SEEK_END);
     193               3 :     vsi_l_offset nSize = VSIFTellL(fpImage);
     194               3 :     if (nSize != (vsi_l_offset)(uint32_t)nSize)
     195               0 :         return CE_Failure;
     196               3 :     VSIFSeekL(fpImage, 0, SEEK_SET);
     197               3 :     uint8_t* pabyCompressed = (uint8_t*)VSIMalloc(nSize);
     198               3 :     if (pabyCompressed == NULL)
     199               0 :         return CE_Failure;
     200               3 :     VSIFReadL(pabyCompressed, 1, nSize, fpImage);
     201                 :     uint8_t* pRet = WebPDecodeRGBInto(pabyCompressed, (uint32_t)nSize,
     202                 :                         (uint8_t*)pabyUncompressed, nRasterXSize * nRasterYSize * 3,
     203               3 :                         nRasterXSize * 3);
     204               3 :     VSIFree(pabyCompressed);
     205               3 :     if (pRet == NULL)
     206                 :     {
     207                 :         CPLError(CE_Failure, CPLE_AppDefined,
     208               0 :                     "WebPDecodeRGBInto() failed");
     209               0 :         return CE_Failure;
     210                 :     }
     211                 : 
     212               3 :     return CE_None;
     213                 : }
     214                 : 
     215                 : /************************************************************************/
     216                 : /*                             IRasterIO()                              */
     217                 : /************************************************************************/
     218                 : 
     219               0 : CPLErr WEBPDataset::IRasterIO( GDALRWFlag eRWFlag,
     220                 :                               int nXOff, int nYOff, int nXSize, int nYSize,
     221                 :                               void *pData, int nBufXSize, int nBufYSize,
     222                 :                               GDALDataType eBufType,
     223                 :                               int nBandCount, int *panBandMap,
     224                 :                               int nPixelSpace, int nLineSpace, int nBandSpace )
     225                 : 
     226                 : {
     227               0 :     if((eRWFlag == GF_Read) &&
     228                 :        (nBandCount == 3) &&
     229                 :        (nBands == 3) &&
     230                 :        (nXOff == 0) && (nXOff == 0) &&
     231                 :        (nXSize == nBufXSize) && (nXSize == nRasterXSize) &&
     232                 :        (nYSize == nBufYSize) && (nYSize == nRasterYSize) &&
     233                 :        (eBufType == GDT_Byte) && 
     234                 :        (nPixelSpace == 3) &&
     235                 :        (nLineSpace == (nPixelSpace*nXSize)) &&
     236                 :        (nBandSpace == 1) &&
     237                 :        (pData != NULL) &&
     238                 :        (panBandMap != NULL) &&
     239               0 :        (panBandMap[0] == 1) && (panBandMap[1] == 2) && (panBandMap[2] == 3))
     240                 :     {
     241               0 :         Uncompress();
     242               0 :         memcpy(pData, pabyUncompressed, 3 * nXSize * nYSize);
     243               0 :         return CE_None;
     244                 :     }
     245                 : 
     246                 :     return GDALPamDataset::IRasterIO(eRWFlag, nXOff, nYOff, nXSize, nYSize,
     247                 :                                      pData, nBufXSize, nBufYSize, eBufType,
     248                 :                                      nBandCount, panBandMap,
     249               0 :                                      nPixelSpace, nLineSpace, nBandSpace);
     250                 : }
     251                 : 
     252                 : /************************************************************************/
     253                 : /*                              Identify()                              */
     254                 : /************************************************************************/
     255                 : 
     256           10496 : int WEBPDataset::Identify( GDALOpenInfo * poOpenInfo )
     257                 : 
     258                 : {
     259           10496 :     GByte  *pabyHeader = NULL;
     260           10496 :     int    nHeaderBytes = poOpenInfo->nHeaderBytes;
     261                 : 
     262           10496 :     pabyHeader = poOpenInfo->pabyHeader;
     263                 : 
     264           10496 :     if( nHeaderBytes < 20 )
     265           10328 :         return FALSE;
     266                 : 
     267                 :     return memcmp(pabyHeader, "RIFF", 4) == 0 &&
     268                 :            memcmp(pabyHeader + 8, "WEBP", 4) == 0 &&
     269             168 :            memcmp(pabyHeader + 12, "VP8 ", 4) == 0;
     270                 : }
     271                 : 
     272                 : /************************************************************************/
     273                 : /*                                Open()                                */
     274                 : /************************************************************************/
     275                 : 
     276            1258 : GDALDataset *WEBPDataset::Open( GDALOpenInfo * poOpenInfo )
     277                 : 
     278                 : {
     279            1258 :     if( !Identify( poOpenInfo ) )
     280            1253 :         return NULL;
     281                 : 
     282                 :     int nWidth, nHeight;
     283               5 :     if (!WebPGetInfo((const uint8_t*)poOpenInfo->pabyHeader, (uint32_t)poOpenInfo->nHeaderBytes,
     284                 :                      &nWidth, &nHeight))
     285               0 :         return NULL;
     286                 : 
     287               5 :     if( poOpenInfo->eAccess == GA_Update )
     288                 :     {
     289                 :         CPLError( CE_Failure, CPLE_NotSupported,
     290                 :                   "The WEBP driver does not support update access to existing"
     291               0 :                   " datasets.\n" );
     292               0 :         return NULL;
     293                 :     }
     294                 : 
     295                 : /* -------------------------------------------------------------------- */
     296                 : /*      Open the file using the large file api.                         */
     297                 : /* -------------------------------------------------------------------- */
     298               5 :     VSILFILE* fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     299                 : 
     300               5 :     if( fpImage == NULL )
     301               0 :         return NULL;
     302                 : 
     303               5 :     GByte* pabyUncompressed = (GByte*)VSIMalloc3(nWidth, nHeight, 3);
     304               5 :     if (pabyUncompressed == NULL)
     305                 :     {
     306               0 :         VSIFCloseL(fpImage);
     307               0 :         return NULL;
     308                 :     }
     309                 : 
     310                 : /* -------------------------------------------------------------------- */
     311                 : /*      Create a corresponding GDALDataset.                             */
     312                 : /* -------------------------------------------------------------------- */
     313                 :     WEBPDataset  *poDS;
     314                 : 
     315               5 :     poDS = new WEBPDataset();
     316               5 :     poDS->nRasterXSize = nWidth;
     317               5 :     poDS->nRasterYSize = nHeight;
     318               5 :     poDS->fpImage = fpImage;
     319               5 :     poDS->pabyUncompressed = pabyUncompressed;
     320                 : 
     321                 : /* -------------------------------------------------------------------- */
     322                 : /*      Create band information objects.                                */
     323                 : /* -------------------------------------------------------------------- */
     324              40 :     for( int iBand = 0; iBand < 3; iBand++ )
     325              15 :         poDS->SetBand( iBand+1, new WEBPRasterBand( poDS, iBand+1 ) );
     326                 : 
     327                 : /* -------------------------------------------------------------------- */
     328                 : /*      Initialize any PAM information.                                 */
     329                 : /* -------------------------------------------------------------------- */
     330               5 :     poDS->SetDescription( poOpenInfo->pszFilename );
     331                 : 
     332               5 :     poDS->TryLoadXML( poOpenInfo->papszSiblingFiles );
     333                 : 
     334                 : /* -------------------------------------------------------------------- */
     335                 : /*      Open overviews.                                                 */
     336                 : /* -------------------------------------------------------------------- */
     337               5 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
     338                 : 
     339               5 :     return poDS;
     340                 : }
     341                 : 
     342                 : /************************************************************************/
     343                 : /*                         WEBPDatasetWriter()                          */
     344                 : /************************************************************************/
     345                 : 
     346               9 : int WEBPDatasetWriter(const uint8_t* data, size_t data_size,
     347                 :                       const WebPPicture* const picture)
     348                 : {
     349                 :     return VSIFWriteL(data, 1, data_size, (VSILFILE*)picture->custom_ptr)
     350               9 :             == data_size;
     351                 : }
     352                 : 
     353                 : /************************************************************************/
     354                 : /*                              CreateCopy()                            */
     355                 : /************************************************************************/
     356                 : 
     357                 : GDALDataset *
     358              19 : WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     359                 :                         int bStrict, char ** papszOptions,
     360                 :                         GDALProgressFunc pfnProgress, void * pProgressData )
     361                 : 
     362                 : {
     363              19 :     int  nBands = poSrcDS->GetRasterCount();
     364              19 :     int  nXSize = poSrcDS->GetRasterXSize();
     365              19 :     int  nYSize = poSrcDS->GetRasterYSize();
     366                 : 
     367                 : /* -------------------------------------------------------------------- */
     368                 : /*      WEBP library initialization                                     */
     369                 : /* -------------------------------------------------------------------- */
     370                 : 
     371                 :     WebPPicture sPicture;
     372              19 :     if (!WebPPictureInit(&sPicture))
     373                 :     {
     374               0 :         CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureInit() failed");
     375               0 :         return NULL;
     376                 :     }
     377                 : 
     378                 : /* -------------------------------------------------------------------- */
     379                 : /*      Some some rudimentary checks                                    */
     380                 : /* -------------------------------------------------------------------- */
     381                 : 
     382              19 :     if( nXSize > 16383 || nYSize > 16383 )
     383                 :     {
     384                 :         CPLError( CE_Failure, CPLE_NotSupported,
     385               0 :                   "WEBP maximum image dimensions are 16383 x 16383.");
     386                 : 
     387               0 :         return NULL;
     388                 :     }
     389                 : 
     390              19 :     if( nBands != 3 )
     391                 :     {
     392                 :         CPLError( CE_Failure, CPLE_NotSupported,
     393                 :                   "WEBP driver doesn't support %d bands. Must be 3 (RGB) bands.",
     394              15 :                   nBands );
     395                 : 
     396              15 :         return NULL;
     397                 :     }
     398                 : 
     399               4 :     GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     400                 : 
     401               4 :     if( eDT != GDT_Byte )
     402                 :     {
     403                 :         CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
     404                 :                   "WEBP driver doesn't support data type %s. "
     405                 :                   "Only eight bit byte bands supported.",
     406                 :                   GDALGetDataTypeName(
     407               0 :                       poSrcDS->GetRasterBand(1)->GetRasterDataType()) );
     408                 : 
     409               0 :         if (bStrict)
     410               0 :             return NULL;
     411                 :     }
     412                 : 
     413                 : /* -------------------------------------------------------------------- */
     414                 : /*      What options has the user selected?                             */
     415                 : /* -------------------------------------------------------------------- */
     416               4 :     float fQuality = 75.0f;
     417               4 :     const char* pszQUALITY = CSLFetchNameValue(papszOptions, "QUALITY"); 
     418               4 :     if( pszQUALITY != NULL )
     419                 :     {
     420               1 :         fQuality = (float) atof(pszQUALITY);
     421               1 :         if( fQuality < 0.0f || fQuality > 100.0f )
     422                 :         {
     423                 :             CPLError( CE_Failure, CPLE_IllegalArg,
     424               0 :                       "%s=%s is not a legal value.", "QUALITY", pszQUALITY);
     425               0 :             return NULL;
     426                 :         }
     427                 :     }
     428                 : 
     429               4 :     WebPPreset nPreset = WEBP_PRESET_DEFAULT;
     430               4 :     const char* pszPRESET = CSLFetchNameValueDef(papszOptions, "PRESET", "DEFAULT");
     431               4 :     if (EQUAL(pszPRESET, "DEFAULT"))
     432               4 :         nPreset = WEBP_PRESET_DEFAULT;
     433               0 :     else if (EQUAL(pszPRESET, "PICTURE"))
     434               0 :         nPreset = WEBP_PRESET_PICTURE;
     435               0 :     else if (EQUAL(pszPRESET, "PHOTO"))
     436               0 :         nPreset = WEBP_PRESET_PHOTO;
     437               0 :     else if (EQUAL(pszPRESET, "PICTURE"))
     438               0 :         nPreset = WEBP_PRESET_PICTURE;
     439               0 :     else if (EQUAL(pszPRESET, "DRAWING"))
     440               0 :         nPreset = WEBP_PRESET_DRAWING;
     441               0 :     else if (EQUAL(pszPRESET, "ICON"))
     442               0 :         nPreset = WEBP_PRESET_ICON;
     443               0 :     else if (EQUAL(pszPRESET, "TEXT"))
     444               0 :         nPreset = WEBP_PRESET_TEXT;
     445                 :     else
     446                 :     {
     447                 :         CPLError( CE_Failure, CPLE_IllegalArg,
     448               0 :                   "%s=%s is not a legal value.", "PRESET", pszPRESET );
     449               0 :         return NULL;
     450                 :     }
     451                 : 
     452                 :     WebPConfig sConfig;
     453               4 :     if (!WebPConfigInitInternal(&sConfig, nPreset, fQuality, WEBP_ENCODER_ABI_VERSION))
     454                 :     {
     455               0 :         CPLError(CE_Failure, CPLE_AppDefined, "WebPConfigInit() failed");
     456               0 :         return NULL;
     457                 :     }
     458                 : 
     459                 : 
     460                 : #define FETCH_AND_SET_OPTION_INT(name, fieldname, minval, maxval) \
     461                 : { \
     462                 :     const char* pszVal = CSLFetchNameValue(papszOptions, name); \
     463                 :     if (pszVal != NULL) \
     464                 :     { \
     465                 :         sConfig.fieldname = atoi(pszVal); \
     466                 :         if (sConfig.fieldname < minval || sConfig.fieldname > maxval) \
     467                 :         { \
     468                 :             CPLError( CE_Failure, CPLE_IllegalArg, \
     469                 :                       "%s=%s is not a legal value.", name, pszVal ); \
     470                 :             return NULL; \
     471                 :         } \
     472                 :     } \
     473                 : }
     474                 : 
     475               4 :     FETCH_AND_SET_OPTION_INT("TARGETSIZE", target_size, 0, INT_MAX);
     476                 : 
     477               4 :     const char* pszPSNR = CSLFetchNameValue(papszOptions, "PSNR");
     478               4 :     if (pszPSNR)
     479                 :     {
     480               0 :         sConfig.target_PSNR = atof(pszPSNR);
     481               0 :         if (sConfig.target_PSNR < 0)
     482                 :         {
     483                 :             CPLError( CE_Failure, CPLE_IllegalArg,
     484               0 :                       "PSNR=%s is not a legal value.", pszPSNR );
     485               0 :             return NULL;
     486                 :         }
     487                 :     }
     488                 : 
     489               4 :     FETCH_AND_SET_OPTION_INT("METHOD", method, 0, 6);
     490               4 :     FETCH_AND_SET_OPTION_INT("SEGMENTS", segments, 1, 4);
     491               4 :     FETCH_AND_SET_OPTION_INT("SNS_STRENGTH", sns_strength, 0, 100);
     492               4 :     FETCH_AND_SET_OPTION_INT("FILTER_STRENGTH", filter_strength, 0, 100);
     493               4 :     FETCH_AND_SET_OPTION_INT("FILTER_SHARPNESS", filter_sharpness, 0, 7);
     494               4 :     FETCH_AND_SET_OPTION_INT("FILTER_TYPE", filter_type, 0, 1);
     495               4 :     FETCH_AND_SET_OPTION_INT("AUTOFILTER", autofilter, 0, 1);
     496               4 :     FETCH_AND_SET_OPTION_INT("PASS", pass, 1, 10);
     497               4 :     FETCH_AND_SET_OPTION_INT("PREPROCESSING", preprocessing, 0, 1);
     498               4 :     FETCH_AND_SET_OPTION_INT("PARTITIONS", partitions, 0, 3);
     499                 : 
     500               4 :     if (!WebPValidateConfig(&sConfig))
     501                 :     {
     502               0 :         CPLError(CE_Failure, CPLE_AppDefined, "WebPValidateConfig() failed");
     503               0 :         return NULL;
     504                 :     }
     505                 : 
     506                 : /* -------------------------------------------------------------------- */
     507                 : /*      Allocate memory                                                 */
     508                 : /* -------------------------------------------------------------------- */
     509                 :     GByte   *pabyBuffer;
     510                 : 
     511               4 :     pabyBuffer = (GByte *) VSIMalloc( 3 * nXSize * nYSize );
     512               4 :     if (pabyBuffer == NULL)
     513                 :     {
     514               0 :         return NULL;
     515                 :     }
     516                 : 
     517                 : /* -------------------------------------------------------------------- */
     518                 : /*      Create the dataset.                                             */
     519                 : /* -------------------------------------------------------------------- */
     520                 :     VSILFILE    *fpImage;
     521                 : 
     522               4 :     fpImage = VSIFOpenL( pszFilename, "wb" );
     523               4 :     if( fpImage == NULL )
     524                 :     {
     525                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     526                 :                   "Unable to create WEBP file %s.\n",
     527               2 :                   pszFilename );
     528               2 :         VSIFree(pabyBuffer);
     529               2 :         return NULL;
     530                 :     }
     531                 : 
     532                 : /* -------------------------------------------------------------------- */
     533                 : /*      WEBP library settings                                           */
     534                 : /* -------------------------------------------------------------------- */
     535                 : 
     536               2 :     sPicture.colorspace = 0;
     537               2 :     sPicture.width = nXSize;
     538               2 :     sPicture.height = nYSize;
     539               2 :     sPicture.writer = WEBPDatasetWriter;
     540               2 :     sPicture.custom_ptr = fpImage;
     541               2 :     if (!WebPPictureAlloc(&sPicture))
     542                 :     {
     543               0 :         CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureAlloc() failed");
     544               0 :         VSIFree(pabyBuffer);
     545               0 :         VSIFCloseL( fpImage );
     546               0 :         return NULL;
     547                 :     }
     548                 : 
     549                 : /* -------------------------------------------------------------------- */
     550                 : /*      Acquire source imagery.                                         */
     551                 : /* -------------------------------------------------------------------- */
     552               2 :     CPLErr      eErr = CE_None;
     553                 : 
     554                 :     eErr = poSrcDS->RasterIO( GF_Read, 0, 0, nXSize, nYSize,
     555                 :                               pabyBuffer, nXSize, nYSize, GDT_Byte,
     556                 :                               3, NULL,
     557               2 :                               3, 3 * nXSize, 1 );
     558                 : 
     559                 : /* -------------------------------------------------------------------- */
     560                 : /*      Import and write to file                                        */
     561                 : /* -------------------------------------------------------------------- */
     562               2 :     if (eErr == CE_None &&
     563                 :         !WebPPictureImportRGB(&sPicture, pabyBuffer, 3 * nXSize))
     564                 :     {
     565               0 :         CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureImportRGB() failed");
     566               0 :         eErr = CE_Failure;
     567                 :     }
     568                 : 
     569               2 :     if (eErr == CE_None && !WebPEncode(&sConfig, &sPicture))
     570                 :     {
     571               0 :         CPLError(CE_Failure, CPLE_AppDefined, "WebPEncode() failed");
     572               0 :         eErr = CE_Failure;
     573                 :     }
     574                 : 
     575                 : /* -------------------------------------------------------------------- */
     576                 : /*      Cleanup and close.                                              */
     577                 : /* -------------------------------------------------------------------- */
     578               2 :     CPLFree( pabyBuffer );
     579                 : 
     580               2 :     WebPPictureFree(&sPicture);
     581                 : 
     582               2 :     VSIFCloseL( fpImage );
     583                 : 
     584               2 :     if( eErr != CE_None )
     585                 :     {
     586               0 :         VSIUnlink( pszFilename );
     587               0 :         return NULL;
     588                 :     }
     589                 : 
     590                 : /* -------------------------------------------------------------------- */
     591                 : /*      Re-open dataset, and copy any auxilary pam information.         */
     592                 : /* -------------------------------------------------------------------- */
     593               2 :     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
     594                 : 
     595                 :     /* If outputing to stdout, we can't reopen it, so we'll return */
     596                 :     /* a fake dataset to make the caller happy */
     597               2 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     598               2 :     WEBPDataset *poDS = (WEBPDataset*) WEBPDataset::Open( &oOpenInfo );
     599               2 :     CPLPopErrorHandler();
     600               2 :     if( poDS )
     601                 :     {
     602               2 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
     603               2 :         return poDS;
     604                 :     }
     605                 : 
     606               0 :     return NULL;
     607                 : }
     608                 : 
     609                 : /************************************************************************/
     610                 : /*                         GDALRegister_WEBP()                          */
     611                 : /************************************************************************/
     612                 : 
     613             558 : void GDALRegister_WEBP()
     614                 : 
     615                 : {
     616                 :     GDALDriver  *poDriver;
     617                 : 
     618             558 :     if( GDALGetDriverByName( "WEBP" ) == NULL )
     619                 :     {
     620             537 :         poDriver = new GDALDriver();
     621                 : 
     622             537 :         poDriver->SetDescription( "WEBP" );
     623                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
     624             537 :                                    "WEBP" );
     625                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
     626             537 :                                    "frmt_webp.html" );
     627             537 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "webp" );
     628             537 :         poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/webp" );
     629                 : 
     630                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
     631             537 :                                    "Byte" );
     632                 : 
     633                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
     634                 : "<CreationOptionList>\n"
     635                 : "   <Option name='QUALITY' type='float' description='good=100, bad=0' default='75'/>\n"
     636                 : "   <Option name='PRESET' type='string-select' description='kind of image' default='DEFAULT'>\n"
     637                 : "       <Value>DEFAULT</Value>\n"
     638                 : "       <Value>PICTURE</Value>\n"
     639                 : "       <Value>PHOTO</Value>\n"
     640                 : "       <Value>DRAWING</Value>\n"
     641                 : "       <Value>ICON</Value>\n"
     642                 : "       <Value>TEXT</Value>\n"
     643                 : "   </Option>\n"
     644                 : "   <Option name='TARGETSIZE' type='int' description='if non-zero, desired target size in bytes. Has precedence over QUALITY'/>\n"
     645                 : "   <Option name='PSNR' type='float' description='if non-zero, minimal distortion to to achieve. Has precedence over TARGETSIZE'/>\n"
     646                 : "   <Option name='METHOD' type='int' description='quality/speed trade-off. fast=0, slower-better=6' default='4'/>\n"
     647                 : "   <Option name='SEGMENTS' type='int' description='maximum number of segments [1-4]' default='4'/>\n"
     648                 : "   <Option name='SNS_STRENGTH' type='int' description='Spatial Noise Shaping. off=0, maximum=100' default='50'/>\n"
     649                 : "   <Option name='FILTER_STRENGTH' type='int' description='Filter strength. off=0, strongest=100' default='20'/>\n"
     650                 : "   <Option name='FILTER_SHARPNESS' type='int' description='Filter sharpness. off=0, least sharp=7' default='0'/>\n"
     651                 : "   <Option name='FILTER_TYPE' type='int' description='Filtering type. simple=0, strong=1' default='0'/>\n"
     652                 : "   <Option name='AUTOFILTER' type='int' description=\"Auto adjust filter's strength. off=0, on=1\" default='0'/>\n"
     653                 : "   <Option name='PASS' type='int' description='Number of entropy analysis passes [1-10]' default='1'/>\n"
     654                 : "   <Option name='PREPROCESSING' type='int' description='Preprocessing filter. none=0, segment-smooth=1' default='0'/>\n"
     655                 : "   <Option name='PARTITIONS' type='int' description='log2(number of token partitions) in [0..3]' default='0'/>\n"
     656             537 : "</CreationOptionList>\n" );
     657                 : 
     658             537 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     659                 : 
     660             537 :         poDriver->pfnIdentify = WEBPDataset::Identify;
     661             537 :         poDriver->pfnOpen = WEBPDataset::Open;
     662             537 :         poDriver->pfnCreateCopy = WEBPDataset::CreateCopy;
     663                 : 
     664             537 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     665                 :     }
     666             558 : }

Generated by: LCOV version 1.7