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