tif_webp.c 27 KB

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