tif_webp.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881
  1. /*
  2. * Copyright (c) 2018, Mapbox
  3. * Author: <norman.barker at mapbox.com>
  4. *
  5. * Permission to use, copy, modify, distribute, and sell this software and
  6. * its documentation for any purpose is hereby granted without fee, provided
  7. * that (i) the above copyright notices and this permission notice appear in
  8. * all copies of the software and related documentation, and (ii) the names of
  9. * Sam Leffler and Silicon Graphics may not be used in any advertising or
  10. * publicity relating to the software without the specific, prior written
  11. * permission of Sam Leffler and Silicon Graphics.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  14. * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  15. * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  16. *
  17. * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  18. * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  19. * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  20. * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
  21. * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  22. * OF THIS SOFTWARE.
  23. */
  24. #include "tiffiop.h"
  25. #ifdef WEBP_SUPPORT
  26. /*
  27. * TIFF Library.
  28. *
  29. * WEBP Compression Support
  30. *
  31. */
  32. #include "webp/decode.h"
  33. #include "webp/encode.h"
  34. #include <stdbool.h>
  35. #include <stdio.h>
  36. #define LSTATE_INIT_DECODE 0x01
  37. #define LSTATE_INIT_ENCODE 0x02
  38. /*
  39. * State block for each open TIFF
  40. * file using WEBP compression/decompression.
  41. */
  42. typedef struct
  43. {
  44. uint16_t nSamples; /* number of samples per pixel */
  45. int lossless; /* lossy/lossless compression */
  46. int lossless_exact; /* lossless exact mode. If TRUE, R,G,B values in areas
  47. with alpha = 0 will be preserved */
  48. int quality_level; /* compression level */
  49. WebPPicture sPicture; /* WebP Picture */
  50. WebPConfig sEncoderConfig; /* WebP encoder config */
  51. uint8_t *pBuffer; /* buffer to hold raw data on encoding */
  52. unsigned int buffer_offset; /* current offset into the buffer */
  53. unsigned int buffer_size;
  54. WebPIDecoder *psDecoder; /* WebPIDecoder */
  55. WebPDecBuffer sDecBuffer; /* Decoder buffer */
  56. int last_y; /* Last row decoded */
  57. int state; /* state flags */
  58. TIFFVGetMethod vgetparent; /* super-class method */
  59. TIFFVSetMethod vsetparent; /* super-class method */
  60. } WebPState;
  61. #define LState(tif) ((WebPState *)(tif)->tif_data)
  62. #define DecoderState(tif) LState(tif)
  63. #define EncoderState(tif) LState(tif)
  64. static int TWebPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
  65. static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
  66. static int TWebPDatasetWriter(const uint8_t *data, size_t data_size,
  67. const WebPPicture *const picture)
  68. {
  69. static const char module[] = "TWebPDatasetWriter";
  70. TIFF *tif = (TIFF *)(picture->custom_ptr);
  71. if ((tif->tif_rawcc + (tmsize_t)data_size) > tif->tif_rawdatasize)
  72. {
  73. TIFFErrorExtR(
  74. tif, module, "Buffer too small by %" TIFF_SIZE_FORMAT " bytes.",
  75. (size_t)(tif->tif_rawcc + data_size - tif->tif_rawdatasize));
  76. return 0;
  77. }
  78. else
  79. {
  80. _TIFFmemcpy(tif->tif_rawcp, data, data_size);
  81. tif->tif_rawcc += data_size;
  82. tif->tif_rawcp += data_size;
  83. return 1;
  84. }
  85. }
  86. /*
  87. * Encode a chunk of pixels.
  88. */
  89. static int TWebPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
  90. {
  91. static const char module[] = "TWebPEncode";
  92. WebPState *sp = EncoderState(tif);
  93. (void)s;
  94. assert(sp != NULL);
  95. assert(sp->state == LSTATE_INIT_ENCODE);
  96. if ((uint64_t)sp->buffer_offset + (uint64_t)cc > sp->buffer_size)
  97. {
  98. TIFFErrorExtR(tif, module, "Too many bytes to be written");
  99. return 0;
  100. }
  101. memcpy(sp->pBuffer + sp->buffer_offset, bp, cc);
  102. sp->buffer_offset += (unsigned)cc;
  103. return 1;
  104. }
  105. static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
  106. {
  107. static const char module[] = "WebPDecode";
  108. VP8StatusCode status = VP8_STATUS_OK;
  109. WebPState *sp = DecoderState(tif);
  110. uint32_t segment_width, segment_height;
  111. bool decode_whole_strile = false;
  112. (void)s;
  113. assert(sp != NULL);
  114. assert(sp->state == LSTATE_INIT_DECODE);
  115. if (sp->psDecoder == NULL)
  116. {
  117. TIFFDirectory *td = &tif->tif_dir;
  118. uint32_t buffer_size;
  119. if (isTiled(tif))
  120. {
  121. segment_width = td->td_tilewidth;
  122. segment_height = td->td_tilelength;
  123. }
  124. else
  125. {
  126. segment_width = td->td_imagewidth;
  127. segment_height = td->td_imagelength - tif->tif_row;
  128. if (segment_height > td->td_rowsperstrip)
  129. segment_height = td->td_rowsperstrip;
  130. }
  131. int webp_width, webp_height;
  132. if (!WebPGetInfo(tif->tif_rawcp,
  133. (uint64_t)tif->tif_rawcc > UINT32_MAX
  134. ? UINT32_MAX
  135. : (uint32_t)tif->tif_rawcc,
  136. &webp_width, &webp_height))
  137. {
  138. TIFFErrorExtR(tif, module, "WebPGetInfo() failed");
  139. return 0;
  140. }
  141. if ((uint32_t)webp_width != segment_width ||
  142. (uint32_t)webp_height != segment_height)
  143. {
  144. TIFFErrorExtR(
  145. tif, module, "WebP blob dimension is %dx%d. Expected %ux%u",
  146. webp_width, webp_height, segment_width, segment_height);
  147. return 0;
  148. }
  149. #if WEBP_DECODER_ABI_VERSION >= 0x0002
  150. WebPDecoderConfig config;
  151. if (!WebPInitDecoderConfig(&config))
  152. {
  153. TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed");
  154. return 0;
  155. }
  156. const bool bWebPGetFeaturesOK =
  157. WebPGetFeatures(tif->tif_rawcp,
  158. (uint64_t)tif->tif_rawcc > UINT32_MAX
  159. ? UINT32_MAX
  160. : (uint32_t)tif->tif_rawcc,
  161. &config.input) == VP8_STATUS_OK;
  162. WebPFreeDecBuffer(&config.output);
  163. if (!bWebPGetFeaturesOK)
  164. {
  165. TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed");
  166. return 0;
  167. }
  168. const int webp_bands = config.input.has_alpha ? 4 : 3;
  169. if (webp_bands != sp->nSamples &&
  170. /* We accept the situation where the WebP blob has only 3 bands,
  171. * whereas the raster is 4 bands. This can happen when the alpha
  172. * channel is fully opaque, and WebP decoding works fine in that
  173. * situation.
  174. */
  175. !(webp_bands == 3 && sp->nSamples == 4))
  176. {
  177. TIFFErrorExtR(tif, module,
  178. "WebP blob band count is %d. Expected %d", webp_bands,
  179. sp->nSamples);
  180. return 0;
  181. }
  182. #endif
  183. buffer_size = segment_width * segment_height * sp->nSamples;
  184. if (occ == (tmsize_t)buffer_size)
  185. {
  186. /* If decoding the whole strip/tile, we can directly use the */
  187. /* output buffer */
  188. decode_whole_strile = true;
  189. }
  190. else if (sp->pBuffer == NULL || buffer_size > sp->buffer_size)
  191. {
  192. if (sp->pBuffer != NULL)
  193. {
  194. _TIFFfreeExt(tif, sp->pBuffer);
  195. sp->pBuffer = NULL;
  196. }
  197. sp->pBuffer = _TIFFmallocExt(tif, buffer_size);
  198. if (!sp->pBuffer)
  199. {
  200. TIFFErrorExtR(tif, module, "Cannot allocate buffer");
  201. return 0;
  202. }
  203. sp->buffer_size = buffer_size;
  204. }
  205. sp->last_y = 0;
  206. WebPInitDecBuffer(&sp->sDecBuffer);
  207. sp->sDecBuffer.is_external_memory = 1;
  208. sp->sDecBuffer.width = segment_width;
  209. sp->sDecBuffer.height = segment_height;
  210. sp->sDecBuffer.u.RGBA.rgba = decode_whole_strile ? op : sp->pBuffer;
  211. sp->sDecBuffer.u.RGBA.stride = segment_width * sp->nSamples;
  212. sp->sDecBuffer.u.RGBA.size = buffer_size;
  213. if (sp->nSamples > 3)
  214. {
  215. sp->sDecBuffer.colorspace = MODE_RGBA;
  216. }
  217. else
  218. {
  219. sp->sDecBuffer.colorspace = MODE_RGB;
  220. }
  221. sp->psDecoder = WebPINewDecoder(&sp->sDecBuffer);
  222. if (sp->psDecoder == NULL)
  223. {
  224. TIFFErrorExtR(tif, module, "Unable to allocate WebP decoder.");
  225. return 0;
  226. }
  227. }
  228. if (occ % sp->sDecBuffer.u.RGBA.stride)
  229. {
  230. TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read");
  231. return 0;
  232. }
  233. status = WebPIAppend(sp->psDecoder, tif->tif_rawcp, tif->tif_rawcc);
  234. if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED)
  235. {
  236. if (status == VP8_STATUS_INVALID_PARAM)
  237. {
  238. TIFFErrorExtR(tif, module, "Invalid parameter used.");
  239. }
  240. else if (status == VP8_STATUS_OUT_OF_MEMORY)
  241. {
  242. TIFFErrorExtR(tif, module, "Out of memory.");
  243. }
  244. else
  245. {
  246. TIFFErrorExtR(tif, module, "Unrecognized error.");
  247. }
  248. return 0;
  249. }
  250. else
  251. {
  252. int current_y, stride;
  253. uint8_t *buf;
  254. /* Returns the RGB/A image decoded so far */
  255. buf = WebPIDecGetRGB(sp->psDecoder, &current_y, NULL, NULL, &stride);
  256. if ((buf != NULL) &&
  257. (occ <= (tmsize_t)stride * (current_y - sp->last_y)))
  258. {
  259. const int numberOfExpectedLines =
  260. (int)(occ / sp->sDecBuffer.u.RGBA.stride);
  261. if (decode_whole_strile)
  262. {
  263. if (current_y != numberOfExpectedLines)
  264. {
  265. TIFFErrorExtR(tif, module,
  266. "Unable to decode WebP data: less lines than "
  267. "expected.");
  268. return 0;
  269. }
  270. }
  271. else
  272. {
  273. memcpy(op, buf + (sp->last_y * stride), occ);
  274. }
  275. tif->tif_rawcp += tif->tif_rawcc;
  276. tif->tif_rawcc = 0;
  277. sp->last_y += numberOfExpectedLines;
  278. if (decode_whole_strile)
  279. {
  280. /* We can now free the decoder as we're completely done */
  281. if (sp->psDecoder != NULL)
  282. {
  283. WebPIDelete(sp->psDecoder);
  284. WebPFreeDecBuffer(&sp->sDecBuffer);
  285. sp->psDecoder = NULL;
  286. }
  287. }
  288. return 1;
  289. }
  290. else
  291. {
  292. TIFFErrorExtR(tif, module, "Unable to decode WebP data.");
  293. return 0;
  294. }
  295. }
  296. }
  297. static int TWebPFixupTags(TIFF *tif)
  298. {
  299. (void)tif;
  300. if (tif->tif_dir.td_planarconfig != PLANARCONFIG_CONTIG)
  301. {
  302. static const char module[] = "TWebPFixupTags";
  303. TIFFErrorExtR(tif, module,
  304. "TIFF WEBP requires data to be stored contiguously in "
  305. "RGB e.g. RGBRGBRGB "
  306. #if WEBP_ENCODER_ABI_VERSION >= 0x0100
  307. "or RGBARGBARGBA"
  308. #endif
  309. );
  310. return 0;
  311. }
  312. return 1;
  313. }
  314. static int TWebPSetupDecode(TIFF *tif)
  315. {
  316. static const char module[] = "WebPSetupDecode";
  317. uint16_t nBitsPerSample = tif->tif_dir.td_bitspersample;
  318. uint16_t sampleFormat = tif->tif_dir.td_sampleformat;
  319. WebPState *sp = DecoderState(tif);
  320. assert(sp != NULL);
  321. sp->nSamples = tif->tif_dir.td_samplesperpixel;
  322. /* check band count */
  323. if (sp->nSamples != 3
  324. #if WEBP_ENCODER_ABI_VERSION >= 0x0100
  325. && sp->nSamples != 4
  326. #endif
  327. )
  328. {
  329. TIFFErrorExtR(tif, module,
  330. "WEBP driver doesn't support %d bands. Must be 3 (RGB) "
  331. #if WEBP_ENCODER_ABI_VERSION >= 0x0100
  332. "or 4 (RGBA) "
  333. #endif
  334. "bands.",
  335. sp->nSamples);
  336. return 0;
  337. }
  338. /* check bits per sample and data type */
  339. if ((nBitsPerSample != 8) && (sampleFormat != 1))
  340. {
  341. TIFFErrorExtR(tif, module, "WEBP driver requires 8 bit unsigned data");
  342. return 0;
  343. }
  344. /* if we were last encoding, terminate this mode */
  345. if (sp->state & LSTATE_INIT_ENCODE)
  346. {
  347. WebPPictureFree(&sp->sPicture);
  348. if (sp->pBuffer != NULL)
  349. {
  350. _TIFFfreeExt(tif, sp->pBuffer);
  351. sp->pBuffer = NULL;
  352. }
  353. sp->buffer_offset = 0;
  354. sp->state = 0;
  355. }
  356. sp->state |= LSTATE_INIT_DECODE;
  357. return 1;
  358. }
  359. /*
  360. * Setup state for decoding a strip.
  361. */
  362. static int TWebPPreDecode(TIFF *tif, uint16_t s)
  363. {
  364. static const char module[] = "TWebPPreDecode";
  365. uint32_t segment_width, segment_height;
  366. WebPState *sp = DecoderState(tif);
  367. TIFFDirectory *td = &tif->tif_dir;
  368. (void)s;
  369. assert(sp != NULL);
  370. if (isTiled(tif))
  371. {
  372. segment_width = td->td_tilewidth;
  373. segment_height = td->td_tilelength;
  374. }
  375. else
  376. {
  377. segment_width = td->td_imagewidth;
  378. segment_height = td->td_imagelength - tif->tif_row;
  379. if (segment_height > td->td_rowsperstrip)
  380. segment_height = td->td_rowsperstrip;
  381. }
  382. if (segment_width > 16383 || segment_height > 16383)
  383. {
  384. TIFFErrorExtR(tif, module,
  385. "WEBP maximum image dimensions are 16383 x 16383.");
  386. return 0;
  387. }
  388. if ((sp->state & LSTATE_INIT_DECODE) == 0)
  389. tif->tif_setupdecode(tif);
  390. if (sp->psDecoder != NULL)
  391. {
  392. WebPIDelete(sp->psDecoder);
  393. WebPFreeDecBuffer(&sp->sDecBuffer);
  394. sp->psDecoder = NULL;
  395. }
  396. return 1;
  397. }
  398. static int TWebPSetupEncode(TIFF *tif)
  399. {
  400. static const char module[] = "WebPSetupEncode";
  401. uint16_t nBitsPerSample = tif->tif_dir.td_bitspersample;
  402. uint16_t sampleFormat = tif->tif_dir.td_sampleformat;
  403. WebPState *sp = EncoderState(tif);
  404. assert(sp != NULL);
  405. sp->nSamples = tif->tif_dir.td_samplesperpixel;
  406. /* check band count */
  407. if (sp->nSamples != 3
  408. #if WEBP_ENCODER_ABI_VERSION >= 0x0100
  409. && sp->nSamples != 4
  410. #endif
  411. )
  412. {
  413. TIFFErrorExtR(tif, module,
  414. "WEBP driver doesn't support %d bands. Must be 3 (RGB) "
  415. #if WEBP_ENCODER_ABI_VERSION >= 0x0100
  416. "or 4 (RGBA) "
  417. #endif
  418. "bands.",
  419. sp->nSamples);
  420. return 0;
  421. }
  422. /* check bits per sample and data type */
  423. if ((nBitsPerSample != 8) || (sampleFormat != SAMPLEFORMAT_UINT))
  424. {
  425. TIFFErrorExtR(tif, module, "WEBP driver requires 8 bit unsigned data");
  426. return 0;
  427. }
  428. if (sp->state & LSTATE_INIT_DECODE)
  429. {
  430. WebPIDelete(sp->psDecoder);
  431. WebPFreeDecBuffer(&sp->sDecBuffer);
  432. sp->psDecoder = NULL;
  433. sp->last_y = 0;
  434. sp->state = 0;
  435. }
  436. sp->state |= LSTATE_INIT_ENCODE;
  437. if (!WebPPictureInit(&sp->sPicture))
  438. {
  439. TIFFErrorExtR(tif, module, "Error initializing WebP picture.");
  440. return 0;
  441. }
  442. if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT,
  443. (float)sp->quality_level,
  444. WEBP_ENCODER_ABI_VERSION))
  445. {
  446. TIFFErrorExtR(tif, module,
  447. "Error creating WebP encoder configuration.");
  448. return 0;
  449. }
  450. // WebPConfigInitInternal above sets lossless to false
  451. #if WEBP_ENCODER_ABI_VERSION >= 0x0100
  452. sp->sEncoderConfig.lossless = sp->lossless;
  453. if (sp->lossless)
  454. {
  455. sp->sPicture.use_argb = 1;
  456. #if WEBP_ENCODER_ABI_VERSION >= 0x0209
  457. sp->sEncoderConfig.exact = sp->lossless_exact;
  458. #endif
  459. }
  460. #endif
  461. if (!WebPValidateConfig(&sp->sEncoderConfig))
  462. {
  463. TIFFErrorExtR(tif, module, "Error with WebP encoder configuration.");
  464. return 0;
  465. }
  466. return 1;
  467. }
  468. /*
  469. * Reset encoding state at the start of a strip.
  470. */
  471. static int TWebPPreEncode(TIFF *tif, uint16_t s)
  472. {
  473. static const char module[] = "TWebPPreEncode";
  474. uint32_t segment_width, segment_height;
  475. WebPState *sp = EncoderState(tif);
  476. TIFFDirectory *td = &tif->tif_dir;
  477. (void)s;
  478. assert(sp != NULL);
  479. if (sp->state != LSTATE_INIT_ENCODE)
  480. tif->tif_setupencode(tif);
  481. /*
  482. * Set encoding parameters for this strip/tile.
  483. */
  484. if (isTiled(tif))
  485. {
  486. segment_width = td->td_tilewidth;
  487. segment_height = td->td_tilelength;
  488. }
  489. else
  490. {
  491. segment_width = td->td_imagewidth;
  492. segment_height = td->td_imagelength - tif->tif_row;
  493. if (segment_height > td->td_rowsperstrip)
  494. segment_height = td->td_rowsperstrip;
  495. }
  496. if (segment_width > 16383 || segment_height > 16383)
  497. {
  498. TIFFErrorExtR(tif, module,
  499. "WEBP maximum image dimensions are 16383 x 16383.");
  500. return 0;
  501. }
  502. /* set up buffer for raw data */
  503. /* given above check and that nSamples <= 4, buffer_size is <= 1 GB */
  504. sp->buffer_size = segment_width * segment_height * sp->nSamples;
  505. if (sp->pBuffer != NULL)
  506. {
  507. _TIFFfreeExt(tif, sp->pBuffer);
  508. sp->pBuffer = NULL;
  509. }
  510. sp->pBuffer = _TIFFmallocExt(tif, sp->buffer_size);
  511. if (!sp->pBuffer)
  512. {
  513. TIFFErrorExtR(tif, module, "Cannot allocate buffer");
  514. return 0;
  515. }
  516. sp->buffer_offset = 0;
  517. sp->sPicture.width = segment_width;
  518. sp->sPicture.height = segment_height;
  519. sp->sPicture.writer = TWebPDatasetWriter;
  520. sp->sPicture.custom_ptr = tif;
  521. return 1;
  522. }
  523. /*
  524. * Finish off an encoded strip by flushing it.
  525. */
  526. static int TWebPPostEncode(TIFF *tif)
  527. {
  528. static const char module[] = "WebPPostEncode";
  529. int64_t stride;
  530. WebPState *sp = EncoderState(tif);
  531. assert(sp != NULL);
  532. assert(sp->state == LSTATE_INIT_ENCODE);
  533. stride = (int64_t)sp->sPicture.width * sp->nSamples;
  534. #if WEBP_ENCODER_ABI_VERSION >= 0x0100
  535. if (sp->nSamples == 4)
  536. {
  537. if (!WebPPictureImportRGBA(&sp->sPicture, sp->pBuffer, (int)stride))
  538. {
  539. TIFFErrorExtR(tif, module, "WebPPictureImportRGBA() failed");
  540. return 0;
  541. }
  542. }
  543. else
  544. #endif
  545. if (!WebPPictureImportRGB(&sp->sPicture, sp->pBuffer, (int)stride))
  546. {
  547. TIFFErrorExtR(tif, module, "WebPPictureImportRGB() failed");
  548. return 0;
  549. }
  550. if (!WebPEncode(&sp->sEncoderConfig, &sp->sPicture))
  551. {
  552. #if WEBP_ENCODER_ABI_VERSION >= 0x0100
  553. const char *pszErrorMsg = NULL;
  554. switch (sp->sPicture.error_code)
  555. {
  556. case VP8_ENC_ERROR_OUT_OF_MEMORY:
  557. pszErrorMsg = "Out of memory";
  558. break;
  559. case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY:
  560. pszErrorMsg = "Out of memory while flushing bits";
  561. break;
  562. case VP8_ENC_ERROR_NULL_PARAMETER:
  563. pszErrorMsg = "A pointer parameter is NULL";
  564. break;
  565. case VP8_ENC_ERROR_INVALID_CONFIGURATION:
  566. pszErrorMsg = "Configuration is invalid";
  567. break;
  568. case VP8_ENC_ERROR_BAD_DIMENSION:
  569. pszErrorMsg = "Picture has invalid width/height";
  570. break;
  571. case VP8_ENC_ERROR_PARTITION0_OVERFLOW:
  572. pszErrorMsg = "Partition is bigger than 512k. Try using less "
  573. "SEGMENTS, or increase PARTITION_LIMIT value";
  574. break;
  575. case VP8_ENC_ERROR_PARTITION_OVERFLOW:
  576. pszErrorMsg = "Partition is bigger than 16M";
  577. break;
  578. case VP8_ENC_ERROR_BAD_WRITE:
  579. pszErrorMsg = "Error while fludshing bytes";
  580. break;
  581. case VP8_ENC_ERROR_FILE_TOO_BIG:
  582. pszErrorMsg = "File is bigger than 4G";
  583. break;
  584. case VP8_ENC_ERROR_USER_ABORT:
  585. pszErrorMsg = "User interrupted";
  586. break;
  587. default:
  588. TIFFErrorExtR(tif, module,
  589. "WebPEncode returned an unknown error code: %d",
  590. sp->sPicture.error_code);
  591. pszErrorMsg = "Unknown WebP error type.";
  592. break;
  593. }
  594. TIFFErrorExtR(tif, module, "WebPEncode() failed : %s", pszErrorMsg);
  595. #else
  596. TIFFErrorExtR(tif, module, "Error in WebPEncode()");
  597. #endif
  598. return 0;
  599. }
  600. sp->sPicture.custom_ptr = NULL;
  601. if (!TIFFFlushData1(tif))
  602. {
  603. TIFFErrorExtR(tif, module, "Error flushing TIFF WebP encoder.");
  604. return 0;
  605. }
  606. return 1;
  607. }
  608. static void TWebPCleanup(TIFF *tif)
  609. {
  610. WebPState *sp = LState(tif);
  611. assert(sp != 0);
  612. tif->tif_tagmethods.vgetfield = sp->vgetparent;
  613. tif->tif_tagmethods.vsetfield = sp->vsetparent;
  614. if (sp->state & LSTATE_INIT_ENCODE)
  615. {
  616. WebPPictureFree(&sp->sPicture);
  617. }
  618. if (sp->psDecoder != NULL)
  619. {
  620. WebPIDelete(sp->psDecoder);
  621. WebPFreeDecBuffer(&sp->sDecBuffer);
  622. sp->psDecoder = NULL;
  623. sp->last_y = 0;
  624. }
  625. if (sp->pBuffer != NULL)
  626. {
  627. _TIFFfreeExt(tif, sp->pBuffer);
  628. sp->pBuffer = NULL;
  629. }
  630. _TIFFfreeExt(tif, tif->tif_data);
  631. tif->tif_data = NULL;
  632. _TIFFSetDefaultCompressionState(tif);
  633. }
  634. static int TWebPVSetField(TIFF *tif, uint32_t tag, va_list ap)
  635. {
  636. static const char module[] = "WebPVSetField";
  637. WebPState *sp = LState(tif);
  638. switch (tag)
  639. {
  640. case TIFFTAG_WEBP_LEVEL:
  641. sp->quality_level = (int)va_arg(ap, int);
  642. if (sp->quality_level <= 0 || sp->quality_level > 100.0f)
  643. {
  644. TIFFWarningExtR(tif, module,
  645. "WEBP_LEVEL should be between 1 and 100");
  646. }
  647. return 1;
  648. case TIFFTAG_WEBP_LOSSLESS:
  649. #if WEBP_ENCODER_ABI_VERSION >= 0x0100
  650. sp->lossless = va_arg(ap, int);
  651. if (sp->lossless)
  652. {
  653. sp->quality_level = 100;
  654. }
  655. return 1;
  656. #else
  657. TIFFErrorExtR(
  658. tif, module,
  659. "Need to upgrade WEBP driver, this version doesn't support "
  660. "lossless compression.");
  661. return 0;
  662. #endif
  663. case TIFFTAG_WEBP_LOSSLESS_EXACT:
  664. #if WEBP_ENCODER_ABI_VERSION >= 0x0209
  665. sp->lossless_exact = va_arg(ap, int);
  666. return 1;
  667. #else
  668. TIFFErrorExtR(
  669. tif, module,
  670. "Need to upgrade WEBP driver, this version doesn't support "
  671. "lossless compression.");
  672. return 0;
  673. #endif
  674. default:
  675. return (*sp->vsetparent)(tif, tag, ap);
  676. }
  677. /*NOTREACHED*/
  678. }
  679. static int TWebPVGetField(TIFF *tif, uint32_t tag, va_list ap)
  680. {
  681. WebPState *sp = LState(tif);
  682. switch (tag)
  683. {
  684. case TIFFTAG_WEBP_LEVEL:
  685. *va_arg(ap, int *) = sp->quality_level;
  686. break;
  687. case TIFFTAG_WEBP_LOSSLESS:
  688. *va_arg(ap, int *) = sp->lossless;
  689. break;
  690. case TIFFTAG_WEBP_LOSSLESS_EXACT:
  691. *va_arg(ap, int *) = sp->lossless_exact;
  692. break;
  693. default:
  694. return (*sp->vgetparent)(tif, tag, ap);
  695. }
  696. return 1;
  697. }
  698. static const TIFFField TWebPFields[] = {
  699. {TIFFTAG_WEBP_LEVEL, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
  700. TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "WEBP quality", NULL},
  701. {TIFFTAG_WEBP_LOSSLESS, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
  702. TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "WEBP lossless/lossy",
  703. NULL},
  704. {TIFFTAG_WEBP_LOSSLESS_EXACT, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
  705. TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "WEBP exact lossless",
  706. NULL},
  707. };
  708. int TIFFInitWebP(TIFF *tif, int scheme)
  709. {
  710. static const char module[] = "TIFFInitWebP";
  711. WebPState *sp;
  712. (void)scheme;
  713. assert(scheme == COMPRESSION_WEBP);
  714. /*
  715. * Merge codec-specific tag information.
  716. */
  717. if (!_TIFFMergeFields(tif, TWebPFields, TIFFArrayCount(TWebPFields)))
  718. {
  719. TIFFErrorExtR(tif, module, "Merging WebP codec-specific tags failed");
  720. return 0;
  721. }
  722. /*
  723. * Allocate state block so tag methods have storage to record values.
  724. */
  725. tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(WebPState));
  726. if (tif->tif_data == NULL)
  727. goto bad;
  728. sp = LState(tif);
  729. /*
  730. * Override parent get/set field methods.
  731. */
  732. sp->vgetparent = tif->tif_tagmethods.vgetfield;
  733. tif->tif_tagmethods.vgetfield = TWebPVGetField; /* hook for codec tags */
  734. sp->vsetparent = tif->tif_tagmethods.vsetfield;
  735. tif->tif_tagmethods.vsetfield = TWebPVSetField; /* hook for codec tags */
  736. /* Default values for codec-specific fields */
  737. sp->quality_level = 75; /* default comp. level */
  738. sp->lossless = 0; /* default to false */
  739. sp->lossless_exact = 1; /* exact lossless mode (if lossless enabled) */
  740. sp->state = 0;
  741. sp->nSamples = 0;
  742. sp->psDecoder = NULL;
  743. sp->last_y = 0;
  744. sp->buffer_offset = 0;
  745. sp->pBuffer = NULL;
  746. /*
  747. * Install codec methods.
  748. * Notes:
  749. * encoderow is not supported
  750. */
  751. tif->tif_fixuptags = TWebPFixupTags;
  752. tif->tif_setupdecode = TWebPSetupDecode;
  753. tif->tif_predecode = TWebPPreDecode;
  754. tif->tif_decoderow = TWebPDecode;
  755. tif->tif_decodestrip = TWebPDecode;
  756. tif->tif_decodetile = TWebPDecode;
  757. tif->tif_setupencode = TWebPSetupEncode;
  758. tif->tif_preencode = TWebPPreEncode;
  759. tif->tif_postencode = TWebPPostEncode;
  760. tif->tif_encoderow = TWebPEncode;
  761. tif->tif_encodestrip = TWebPEncode;
  762. tif->tif_encodetile = TWebPEncode;
  763. tif->tif_cleanup = TWebPCleanup;
  764. return 1;
  765. bad:
  766. TIFFErrorExtR(tif, module, "No space for WebP state block");
  767. return 0;
  768. }
  769. #endif /* WEBP_SUPPORT */