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: 2012-04-28 Functions: 18 12 66.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: webpdataset.cpp 23691 2012-01-03 19:09:39Z 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 23691 2012-01-03 19:09:39Z 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              30 : {
      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              30 : WEBPRasterBand::WEBPRasterBand( WEBPDataset *poDS, int nBand )
      99                 : 
     100                 : {
     101              30 :     this->poDS = poDS;
     102                 : 
     103              30 :     eDataType = GDT_Byte;
     104                 : 
     105              30 :     nBlockXSize = poDS->nRasterXSize;
     106              30 :     nBlockYSize = 1;
     107              30 : }
     108                 : 
     109                 : /************************************************************************/
     110                 : /*                             IReadBlock()                             */
     111                 : /************************************************************************/
     112                 : 
     113             300 : CPLErr WEBPRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     114                 :                                   void * pImage )
     115                 : 
     116                 : {
     117             300 :     WEBPDataset* poGDS = (WEBPDataset*) poDS;
     118                 : 
     119             300 :     poGDS->Uncompress();
     120                 : 
     121                 :     int i;
     122                 :     GByte* pabyUncompressed =
     123             300 :         &poGDS->pabyUncompressed[nBlockYOff * nRasterXSize  * 3 + nBand - 1];
     124           15300 :     for(i=0;i<nRasterXSize;i++)
     125           15000 :         ((GByte*)pImage)[i] = pabyUncompressed[3 * i];
     126                 : 
     127             300 :     return CE_None;
     128                 : }
     129                 : 
     130                 : /************************************************************************/
     131                 : /*                       GetColorInterpretation()                       */
     132                 : /************************************************************************/
     133                 : 
     134              12 : GDALColorInterp WEBPRasterBand::GetColorInterpretation()
     135                 : 
     136                 : {
     137              12 :     if ( nBand == 1 )
     138               4 :         return GCI_RedBand;
     139                 : 
     140               8 :     else if( nBand == 2 )
     141               4 :         return GCI_GreenBand;
     142                 : 
     143               4 :     else if ( nBand == 3 )
     144               4 :         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              10 : WEBPDataset::WEBPDataset()
     162                 : 
     163                 : {
     164              10 :     fpImage = NULL;
     165              10 :     pabyUncompressed = NULL;
     166              10 :     bHasBeenUncompressed = FALSE;
     167              10 : }
     168                 : 
     169                 : /************************************************************************/
     170                 : /*                           ~WEBPDataset()                             */
     171                 : /************************************************************************/
     172                 : 
     173              10 : WEBPDataset::~WEBPDataset()
     174                 : 
     175                 : {
     176              10 :     FlushCache();
     177              10 :     if (fpImage)
     178              10 :         VSIFCloseL(fpImage);
     179              10 :     VSIFree(pabyUncompressed);
     180              10 : }
     181                 : 
     182                 : /************************************************************************/
     183                 : /*                            Uncompress()                              */
     184                 : /************************************************************************/
     185                 : 
     186             300 : CPLErr WEBPDataset::Uncompress()
     187                 : {
     188             300 :     if (bHasBeenUncompressed)
     189             294 :         return CE_None;
     190               6 :     bHasBeenUncompressed = TRUE;
     191                 : 
     192               6 :     VSIFSeekL(fpImage, 0, SEEK_END);
     193               6 :     vsi_l_offset nSize = VSIFTellL(fpImage);
     194               6 :     if (nSize != (vsi_l_offset)(uint32_t)nSize)
     195               0 :         return CE_Failure;
     196               6 :     VSIFSeekL(fpImage, 0, SEEK_SET);
     197               6 :     uint8_t* pabyCompressed = (uint8_t*)VSIMalloc(nSize);
     198               6 :     if (pabyCompressed == NULL)
     199               0 :         return CE_Failure;
     200               6 :     VSIFReadL(pabyCompressed, 1, nSize, fpImage);
     201                 :     uint8_t* pRet = WebPDecodeRGBInto(pabyCompressed, (uint32_t)nSize,
     202                 :                         (uint8_t*)pabyUncompressed, nRasterXSize * nRasterYSize * 3,
     203               6 :                         nRasterXSize * 3);
     204               6 :     VSIFree(pabyCompressed);
     205               6 :     if (pRet == NULL)
     206                 :     {
     207                 :         CPLError(CE_Failure, CPLE_AppDefined,
     208               0 :                     "WebPDecodeRGBInto() failed");
     209               0 :         return CE_Failure;
     210                 :     }
     211                 : 
     212               6 :     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           21494 : int WEBPDataset::Identify( GDALOpenInfo * poOpenInfo )
     257                 : 
     258                 : {
     259           21494 :     GByte  *pabyHeader = NULL;
     260           21494 :     int    nHeaderBytes = poOpenInfo->nHeaderBytes;
     261                 : 
     262           21494 :     pabyHeader = poOpenInfo->pabyHeader;
     263                 : 
     264           21494 :     if( nHeaderBytes < 20 )
     265           21138 :         return FALSE;
     266                 : 
     267                 :     return memcmp(pabyHeader, "RIFF", 4) == 0 &&
     268                 :            memcmp(pabyHeader + 8, "WEBP", 4) == 0 &&
     269             356 :            memcmp(pabyHeader + 12, "VP8 ", 4) == 0;
     270                 : }
     271                 : 
     272                 : /************************************************************************/
     273                 : /*                                Open()                                */
     274                 : /************************************************************************/
     275                 : 
     276            2600 : GDALDataset *WEBPDataset::Open( GDALOpenInfo * poOpenInfo )
     277                 : 
     278                 : {
     279            2600 :     if( !Identify( poOpenInfo ) )
     280            2590 :         return NULL;
     281                 : 
     282                 :     int nWidth, nHeight;
     283              10 :     if (!WebPGetInfo((const uint8_t*)poOpenInfo->pabyHeader, (uint32_t)poOpenInfo->nHeaderBytes,
     284                 :                      &nWidth, &nHeight))
     285               0 :         return NULL;
     286                 : 
     287              10 :     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              10 :     VSILFILE* fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
     299                 : 
     300              10 :     if( fpImage == NULL )
     301               0 :         return NULL;
     302                 : 
     303              10 :     GByte* pabyUncompressed = (GByte*)VSIMalloc3(nWidth, nHeight, 3);
     304              10 :     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              10 :     poDS = new WEBPDataset();
     316              10 :     poDS->nRasterXSize = nWidth;
     317              10 :     poDS->nRasterYSize = nHeight;
     318              10 :     poDS->fpImage = fpImage;
     319              10 :     poDS->pabyUncompressed = pabyUncompressed;
     320                 : 
     321                 : /* -------------------------------------------------------------------- */
     322                 : /*      Create band information objects.                                */
     323                 : /* -------------------------------------------------------------------- */
     324              80 :     for( int iBand = 0; iBand < 3; iBand++ )
     325              30 :         poDS->SetBand( iBand+1, new WEBPRasterBand( poDS, iBand+1 ) );
     326                 : 
     327                 : /* -------------------------------------------------------------------- */
     328                 : /*      Initialize any PAM information.                                 */
     329                 : /* -------------------------------------------------------------------- */
     330              10 :     poDS->SetDescription( poOpenInfo->pszFilename );
     331                 : 
     332              10 :     poDS->TryLoadXML( poOpenInfo->papszSiblingFiles );
     333                 : 
     334                 : /* -------------------------------------------------------------------- */
     335                 : /*      Open overviews.                                                 */
     336                 : /* -------------------------------------------------------------------- */
     337              10 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
     338                 : 
     339              10 :     return poDS;
     340                 : }
     341                 : 
     342                 : /************************************************************************/
     343                 : /*                         WEBPDatasetWriter()                          */
     344                 : /************************************************************************/
     345                 : 
     346              18 : 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              18 :             == data_size;
     351                 : }
     352                 : 
     353                 : /************************************************************************/
     354                 : /*                              CreateCopy()                            */
     355                 : /************************************************************************/
     356                 : 
     357                 : GDALDataset *
     358              38 : WEBPDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     359                 :                         int bStrict, char ** papszOptions,
     360                 :                         GDALProgressFunc pfnProgress, void * pProgressData )
     361                 : 
     362                 : {
     363              38 :     int  nBands = poSrcDS->GetRasterCount();
     364              38 :     int  nXSize = poSrcDS->GetRasterXSize();
     365              38 :     int  nYSize = poSrcDS->GetRasterYSize();
     366                 : 
     367                 : /* -------------------------------------------------------------------- */
     368                 : /*      WEBP library initialization                                     */
     369                 : /* -------------------------------------------------------------------- */
     370                 : 
     371                 :     WebPPicture sPicture;
     372              38 :     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              38 :     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              38 :     if( nBands != 3 )
     391                 :     {
     392                 :         CPLError( CE_Failure, CPLE_NotSupported,
     393                 :                   "WEBP driver doesn't support %d bands. Must be 3 (RGB) bands.",
     394              30 :                   nBands );
     395                 : 
     396              30 :         return NULL;
     397                 :     }
     398                 : 
     399               8 :     GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
     400                 : 
     401               8 :     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               8 :     float fQuality = 75.0f;
     417               8 :     const char* pszQUALITY = CSLFetchNameValue(papszOptions, "QUALITY"); 
     418               8 :     if( pszQUALITY != NULL )
     419                 :     {
     420               2 :         fQuality = (float) atof(pszQUALITY);
     421               2 :         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               8 :     WebPPreset nPreset = WEBP_PRESET_DEFAULT;
     430               8 :     const char* pszPRESET = CSLFetchNameValueDef(papszOptions, "PRESET", "DEFAULT");
     431               8 :     if (EQUAL(pszPRESET, "DEFAULT"))
     432               8 :         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               8 :     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               8 :     FETCH_AND_SET_OPTION_INT("TARGETSIZE", target_size, 0, INT_MAX);
     476                 : 
     477               8 :     const char* pszPSNR = CSLFetchNameValue(papszOptions, "PSNR");
     478               8 :     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               8 :     FETCH_AND_SET_OPTION_INT("METHOD", method, 0, 6);
     490               8 :     FETCH_AND_SET_OPTION_INT("SEGMENTS", segments, 1, 4);
     491               8 :     FETCH_AND_SET_OPTION_INT("SNS_STRENGTH", sns_strength, 0, 100);
     492               8 :     FETCH_AND_SET_OPTION_INT("FILTER_STRENGTH", filter_strength, 0, 100);
     493               8 :     FETCH_AND_SET_OPTION_INT("FILTER_SHARPNESS", filter_sharpness, 0, 7);
     494               8 :     FETCH_AND_SET_OPTION_INT("FILTER_TYPE", filter_type, 0, 1);
     495               8 :     FETCH_AND_SET_OPTION_INT("AUTOFILTER", autofilter, 0, 1);
     496               8 :     FETCH_AND_SET_OPTION_INT("PASS", pass, 1, 10);
     497               8 :     FETCH_AND_SET_OPTION_INT("PREPROCESSING", preprocessing, 0, 1);
     498               8 :     FETCH_AND_SET_OPTION_INT("PARTITIONS", partitions, 0, 3);
     499                 : 
     500               8 :     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               8 :     pabyBuffer = (GByte *) VSIMalloc( 3 * nXSize * nYSize );
     512               8 :     if (pabyBuffer == NULL)
     513                 :     {
     514               0 :         return NULL;
     515                 :     }
     516                 : 
     517                 : /* -------------------------------------------------------------------- */
     518                 : /*      Create the dataset.                                             */
     519                 : /* -------------------------------------------------------------------- */
     520                 :     VSILFILE    *fpImage;
     521                 : 
     522               8 :     fpImage = VSIFOpenL( pszFilename, "wb" );
     523               8 :     if( fpImage == NULL )
     524                 :     {
     525                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     526                 :                   "Unable to create WEBP file %s.\n",
     527               4 :                   pszFilename );
     528               4 :         VSIFree(pabyBuffer);
     529               4 :         return NULL;
     530                 :     }
     531                 : 
     532                 : /* -------------------------------------------------------------------- */
     533                 : /*      WEBP library settings                                           */
     534                 : /* -------------------------------------------------------------------- */
     535                 : 
     536                 : #if WEBP_ENCODER_ABI_VERSION >= 0x0002
     537               4 :     sPicture.colorspace = WEBP_YUV420;
     538                 : #else
     539                 :     sPicture.colorspace = 0;
     540                 : #endif
     541               4 :     sPicture.width = nXSize;
     542               4 :     sPicture.height = nYSize;
     543               4 :     sPicture.writer = WEBPDatasetWriter;
     544               4 :     sPicture.custom_ptr = fpImage;
     545               4 :     if (!WebPPictureAlloc(&sPicture))
     546                 :     {
     547               0 :         CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureAlloc() failed");
     548               0 :         VSIFree(pabyBuffer);
     549               0 :         VSIFCloseL( fpImage );
     550               0 :         return NULL;
     551                 :     }
     552                 : 
     553                 : /* -------------------------------------------------------------------- */
     554                 : /*      Acquire source imagery.                                         */
     555                 : /* -------------------------------------------------------------------- */
     556               4 :     CPLErr      eErr = CE_None;
     557                 : 
     558                 :     eErr = poSrcDS->RasterIO( GF_Read, 0, 0, nXSize, nYSize,
     559                 :                               pabyBuffer, nXSize, nYSize, GDT_Byte,
     560                 :                               3, NULL,
     561               4 :                               3, 3 * nXSize, 1 );
     562                 : 
     563                 : /* -------------------------------------------------------------------- */
     564                 : /*      Import and write to file                                        */
     565                 : /* -------------------------------------------------------------------- */
     566               4 :     if (eErr == CE_None &&
     567                 :         !WebPPictureImportRGB(&sPicture, pabyBuffer, 3 * nXSize))
     568                 :     {
     569               0 :         CPLError(CE_Failure, CPLE_AppDefined, "WebPPictureImportRGB() failed");
     570               0 :         eErr = CE_Failure;
     571                 :     }
     572                 : 
     573               4 :     if (eErr == CE_None && !WebPEncode(&sConfig, &sPicture))
     574                 :     {
     575               0 :         CPLError(CE_Failure, CPLE_AppDefined, "WebPEncode() failed");
     576               0 :         eErr = CE_Failure;
     577                 :     }
     578                 : 
     579                 : /* -------------------------------------------------------------------- */
     580                 : /*      Cleanup and close.                                              */
     581                 : /* -------------------------------------------------------------------- */
     582               4 :     CPLFree( pabyBuffer );
     583                 : 
     584               4 :     WebPPictureFree(&sPicture);
     585                 : 
     586               4 :     VSIFCloseL( fpImage );
     587                 : 
     588               4 :     if( eErr != CE_None )
     589                 :     {
     590               0 :         VSIUnlink( pszFilename );
     591               0 :         return NULL;
     592                 :     }
     593                 : 
     594                 : /* -------------------------------------------------------------------- */
     595                 : /*      Re-open dataset, and copy any auxilary pam information.         */
     596                 : /* -------------------------------------------------------------------- */
     597               4 :     GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
     598                 : 
     599                 :     /* If outputing to stdout, we can't reopen it, so we'll return */
     600                 :     /* a fake dataset to make the caller happy */
     601               4 :     CPLPushErrorHandler(CPLQuietErrorHandler);
     602               4 :     WEBPDataset *poDS = (WEBPDataset*) WEBPDataset::Open( &oOpenInfo );
     603               4 :     CPLPopErrorHandler();
     604               4 :     if( poDS )
     605                 :     {
     606               4 :         poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
     607               4 :         return poDS;
     608                 :     }
     609                 : 
     610               0 :     return NULL;
     611                 : }
     612                 : 
     613                 : /************************************************************************/
     614                 : /*                         GDALRegister_WEBP()                          */
     615                 : /************************************************************************/
     616                 : 
     617            1135 : void GDALRegister_WEBP()
     618                 : 
     619                 : {
     620                 :     GDALDriver  *poDriver;
     621                 : 
     622            1135 :     if( GDALGetDriverByName( "WEBP" ) == NULL )
     623                 :     {
     624            1093 :         poDriver = new GDALDriver();
     625                 : 
     626            1093 :         poDriver->SetDescription( "WEBP" );
     627                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
     628            1093 :                                    "WEBP" );
     629                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
     630            1093 :                                    "frmt_webp.html" );
     631            1093 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "webp" );
     632            1093 :         poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/webp" );
     633                 : 
     634                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
     635            1093 :                                    "Byte" );
     636                 : 
     637                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
     638                 : "<CreationOptionList>\n"
     639                 : "   <Option name='QUALITY' type='float' description='good=100, bad=0' default='75'/>\n"
     640                 : "   <Option name='PRESET' type='string-select' description='kind of image' default='DEFAULT'>\n"
     641                 : "       <Value>DEFAULT</Value>\n"
     642                 : "       <Value>PICTURE</Value>\n"
     643                 : "       <Value>PHOTO</Value>\n"
     644                 : "       <Value>DRAWING</Value>\n"
     645                 : "       <Value>ICON</Value>\n"
     646                 : "       <Value>TEXT</Value>\n"
     647                 : "   </Option>\n"
     648                 : "   <Option name='TARGETSIZE' type='int' description='if non-zero, desired target size in bytes. Has precedence over QUALITY'/>\n"
     649                 : "   <Option name='PSNR' type='float' description='if non-zero, minimal distortion to to achieve. Has precedence over TARGETSIZE'/>\n"
     650                 : "   <Option name='METHOD' type='int' description='quality/speed trade-off. fast=0, slower-better=6' default='4'/>\n"
     651                 : "   <Option name='SEGMENTS' type='int' description='maximum number of segments [1-4]' default='4'/>\n"
     652                 : "   <Option name='SNS_STRENGTH' type='int' description='Spatial Noise Shaping. off=0, maximum=100' default='50'/>\n"
     653                 : "   <Option name='FILTER_STRENGTH' type='int' description='Filter strength. off=0, strongest=100' default='20'/>\n"
     654                 : "   <Option name='FILTER_SHARPNESS' type='int' description='Filter sharpness. off=0, least sharp=7' default='0'/>\n"
     655                 : "   <Option name='FILTER_TYPE' type='int' description='Filtering type. simple=0, strong=1' default='0'/>\n"
     656                 : "   <Option name='AUTOFILTER' type='int' description=\"Auto adjust filter's strength. off=0, on=1\" default='0'/>\n"
     657                 : "   <Option name='PASS' type='int' description='Number of entropy analysis passes [1-10]' default='1'/>\n"
     658                 : "   <Option name='PREPROCESSING' type='int' description='Preprocessing filter. none=0, segment-smooth=1' default='0'/>\n"
     659                 : "   <Option name='PARTITIONS' type='int' description='log2(number of token partitions) in [0..3]' default='0'/>\n"
     660            1093 : "</CreationOptionList>\n" );
     661                 : 
     662            1093 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
     663                 : 
     664            1093 :         poDriver->pfnIdentify = WEBPDataset::Identify;
     665            1093 :         poDriver->pfnOpen = WEBPDataset::Open;
     666            1093 :         poDriver->pfnCreateCopy = WEBPDataset::CreateCopy;
     667                 : 
     668            1093 :         GetGDALDriverManager()->RegisterDriver( poDriver );
     669                 :     }
     670            1135 : }

Generated by: LCOV version 1.7