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 : }
|