1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2011 Google Inc. All Rights Reserved.
27c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license
40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source
50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found
60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may
70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree.
87c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// -----------------------------------------------------------------------------
97c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
1033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// WebPPicture class basis
117c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora//
127c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// Author: Skal (pascal.massimino@gmail.com)
137c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
14466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#include <assert.h>
157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#include <stdlib.h>
16a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
17a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern#include "src/enc/vp8i_enc.h"
18a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern#include "src/dsp/dsp.h"
19a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern#include "src/utils/utils.h"
208b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
21a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
227c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora// WebPPicture
23a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
247c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2533f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic int DummyWriter(const uint8_t* data, size_t data_size,
2633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora                       const WebPPicture* const picture) {
2733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // The following are to prevent 'unused variable' error message.
2833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  (void)data;
2933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  (void)data_size;
3033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  (void)picture;
3133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return 1;
3233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora}
33a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
3433f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureInitInternal(WebPPicture* picture, int version) {
3533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (WEBP_ABI_IS_INCOMPATIBLE(version, WEBP_ENCODER_ABI_VERSION)) {
3633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    return 0;   // caller/system version mismatch!
3733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  }
3833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (picture != NULL) {
3933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    memset(picture, 0, sizeof(*picture));
4033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    picture->writer = DummyWriter;
4133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPEncodingSetError(picture, VP8_ENC_OK);
427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return 1;
447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
4633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------
4733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora
4833f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void WebPPictureResetBufferARGB(WebPPicture* const picture) {
49a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  picture->memory_argb_ = NULL;
50a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  picture->argb = NULL;
51a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  picture->argb_stride = 0;
52a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
5433f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void WebPPictureResetBufferYUVA(WebPPicture* const picture) {
55a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  picture->memory_ = NULL;
56a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  picture->y = picture->u = picture->v = picture->a = NULL;
57a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  picture->y_stride = picture->uv_stride = 0;
58a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  picture->a_stride = 0;
59a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
60a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
6133f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid WebPPictureResetBuffers(WebPPicture* const picture) {
6233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPPictureResetBufferARGB(picture);
6333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPPictureResetBufferYUVA(picture);
64a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
65a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
6633f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureAllocARGB(WebPPicture* const picture, int width, int height) {
6733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  void* memory;
6833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const uint64_t argb_size = (uint64_t)width * height;
69466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
7033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  assert(picture != NULL);
717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(picture->memory_argb_);
7333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPPictureResetBufferARGB(picture);
747c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
7533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (width <= 0 || height <= 0) {
7633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
77a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
7833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // allocate a new buffer.
79a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern  memory = WebPSafeMalloc(argb_size + WEBP_ALIGN_CST, sizeof(*picture->argb));
8033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (memory == NULL) {
8133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
82a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
8333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  picture->memory_argb_ = memory;
84a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern  picture->argb = (uint32_t*)WEBP_ALIGN(memory);
8533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  picture->argb_stride = width;
86a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return 1;
87a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
88a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
8933f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureAllocYUVA(WebPPicture* const picture, int width, int height) {
9098a63a77eb8652c81d64b5b7c3d8a347111807caJames Zern  const WebPEncCSP uv_csp =
9198a63a77eb8652c81d64b5b7c3d8a347111807caJames Zern      (WebPEncCSP)((int)picture->colorspace & WEBP_CSP_UV_MASK);
9298a63a77eb8652c81d64b5b7c3d8a347111807caJames Zern  const int has_alpha = (int)picture->colorspace & WEBP_CSP_ALPHA_BIT;
9333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int y_stride = width;
94a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern  const int uv_width = (int)(((int64_t)width + 1) >> 1);
95a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern  const int uv_height = (int)(((int64_t)height + 1) >> 1);
9633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  const int uv_stride = uv_width;
9733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  int a_width, a_stride;
9833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  uint64_t y_size, uv_size, a_size, total_size;
9933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  uint8_t* mem;
100466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
10133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  assert(picture != NULL);
102466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
10333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPSafeFree(picture->memory_);
10433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  WebPPictureResetBufferYUVA(picture);
105a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
10633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (uv_csp != WEBP_YUV420) {
10733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
108a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
109a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
11033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // alpha
11133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  a_width = has_alpha ? width : 0;
11233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  a_stride = a_width;
11333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  y_size = (uint64_t)y_stride * height;
11433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  uv_size = (uint64_t)uv_stride * uv_height;
11533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  a_size =  (uint64_t)a_stride * height;
116a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
11733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  total_size = y_size + a_size + 2 * uv_size;
118a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
11933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // Security and validation checks
120a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern  if (width <= 0 || height <= 0 ||           // luma/alpha param error
121a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern      uv_width <= 0 || uv_height <= 0) {     // u/v param error
12233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
123a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
12433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // allocate a new buffer.
12533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  mem = (uint8_t*)WebPSafeMalloc(total_size, sizeof(*mem));
12633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (mem == NULL) {
12733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
128a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
129466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
13033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // From now on, we're in the clear, we can no longer fail...
13133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  picture->memory_ = (void*)mem;
13233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  picture->y_stride  = y_stride;
13333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  picture->uv_stride = uv_stride;
13433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  picture->a_stride  = a_stride;
1357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
13633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  // TODO(skal): we could align the y/u/v planes and adjust stride.
13733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  picture->y = mem;
13833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  mem += y_size;
1397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
14033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  picture->u = mem;
14133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  mem += uv_size;
14233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  picture->v = mem;
14333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  mem += uv_size;
1447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
14533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (a_size > 0) {
14633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    picture->a = mem;
14733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    mem += a_size;
148a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
14933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  (void)mem;  // makes the static analyzer happy
150466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  return 1;
151466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora}
152466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
15333f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureAlloc(WebPPicture* picture) {
15433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (picture != NULL) {
15533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int width = picture->width;
15633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    const int height = picture->height;
157466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
15833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPPictureFree(picture);   // erase previous buffer
1598b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
16033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    if (!picture->use_argb) {
16133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      return WebPPictureAllocYUVA(picture, width, height);
16233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    } else {
16333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora      return WebPPictureAllocARGB(picture, width, height);
1648b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora    }
1658b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
16633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  return 1;
1678b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
1688b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
16933f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid WebPPictureFree(WebPPicture* picture) {
17033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (picture != NULL) {
17133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPSafeFree(picture->memory_);
17233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPSafeFree(picture->memory_argb_);
17333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPPictureResetBuffers(picture);
174a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  }
1757c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
1767c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
177a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
178a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// WebPMemoryWriter: Write-to-memory
1797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
180a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroravoid WebPMemoryWriterInit(WebPMemoryWriter* writer) {
181a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  writer->mem = NULL;
182a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  writer->size = 0;
1837c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  writer->max_size = 0;
1847c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
1857c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
186a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Aroraint WebPMemoryWrite(const uint8_t* data, size_t data_size,
187a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                    const WebPPicture* picture) {
1887c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  WebPMemoryWriter* const w = (WebPMemoryWriter*)picture->custom_ptr;
189a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  uint64_t next_size;
1907c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (w == NULL) {
1917c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    return 1;
1927c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
193a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  next_size = (uint64_t)w->size + data_size;
1947c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (next_size > w->max_size) {
1957c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    uint8_t* new_mem;
196a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    uint64_t next_max_size = 2ULL * w->max_size;
1977c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (next_max_size < next_size) next_max_size = next_size;
198a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (next_max_size < 8192ULL) next_max_size = 8192ULL;
199a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    new_mem = (uint8_t*)WebPSafeMalloc(next_max_size, 1);
2007c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    if (new_mem == NULL) {
2017c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      return 0;
2027c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
203a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    if (w->size > 0) {
204a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora      memcpy(new_mem, w->mem, w->size);
2057c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    }
20633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPSafeFree(w->mem);
207a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    w->mem = new_mem;
208a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    // down-cast is ok, thanks to WebPSafeMalloc
209a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    w->max_size = (size_t)next_max_size;
2107c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
211a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  if (data_size > 0) {
212a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    memcpy(w->mem + w->size, data, data_size);
213a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora    w->size += data_size;
2147c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
2157c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  return 1;
2167c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2177c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
21833f74dabbc7920a65ed435d7417987589febdc16Vikas Aroravoid WebPMemoryWriterClear(WebPMemoryWriter* writer) {
21933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora  if (writer != NULL) {
22033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPSafeFree(writer->mem);
22133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    writer->mem = NULL;
22233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    writer->size = 0;
22333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    writer->max_size = 0;
2248b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora  }
2258b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora}
2268b720228d581a84fd173b6dcb2fa295b59db489aVikas Arora
227a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
228a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Simplest high-level calls:
2297c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2307c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Aroratypedef int (*Importer)(WebPPicture* const, const uint8_t* const, int);
2317c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
232466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arorastatic size_t Encode(const uint8_t* rgba, int width, int height, int stride,
233a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                     Importer import, float quality_factor, int lossless,
234a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora                     uint8_t** output) {
2357c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  WebPPicture pic;
2367c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  WebPConfig config;
2377c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  WebPMemoryWriter wrt;
2387c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  int ok;
2397c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2400912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern  if (output == NULL) return 0;
2410912efc2528d03c59d45dd9bdc9ff9ec800a3fc1James Zern
2427c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (!WebPConfigPreset(&config, WEBP_PRESET_DEFAULT, quality_factor) ||
2437c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora      !WebPPictureInit(&pic)) {
2447c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    return 0;  // shouldn't happen, except if system installation is broken
2457c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
2467c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
247a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  config.lossless = !!lossless;
248a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  pic.use_argb = !!lossless;
2497c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  pic.width = width;
2507c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  pic.height = height;
2517c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  pic.writer = WebPMemoryWrite;
2527c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  pic.custom_ptr = &wrt;
253a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  WebPMemoryWriterInit(&wrt);
2547c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
255466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  ok = import(&pic, rgba, stride) && WebPEncode(&config, &pic);
2567c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  WebPPictureFree(&pic);
2577c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  if (!ok) {
25833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora    WebPMemoryWriterClear(&wrt);
2597c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    *output = NULL;
2607c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora    return 0;
2617c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora  }
262a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  *output = wrt.mem;
263a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return wrt.size;
2647c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2657c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
266a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define ENCODE_FUNC(NAME, IMPORTER)                                     \
267a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorasize_t NAME(const uint8_t* in, int w, int h, int bps, float q,          \
268a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora            uint8_t** out) {                                            \
269a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return Encode(in, w, h, bps, IMPORTER, q, 0, out);                    \
2707c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora}
2717c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2728b720228d581a84fd173b6dcb2fa295b59db489aVikas AroraENCODE_FUNC(WebPEncodeRGB, WebPPictureImportRGB)
2738b720228d581a84fd173b6dcb2fa295b59db489aVikas AroraENCODE_FUNC(WebPEncodeRGBA, WebPPictureImportRGBA)
274a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern#if !defined(WEBP_REDUCE_CSP)
275a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames ZernENCODE_FUNC(WebPEncodeBGR, WebPPictureImportBGR)
2768b720228d581a84fd173b6dcb2fa295b59db489aVikas AroraENCODE_FUNC(WebPEncodeBGRA, WebPPictureImportBGRA)
277a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern#endif  // WEBP_REDUCE_CSP
2787c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
2797c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora#undef ENCODE_FUNC
2807c970a0a679089e416c5887cf7fcece15a70bfa4Vikas Arora
281a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define LOSSLESS_DEFAULT_QUALITY 70.
282a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define LOSSLESS_ENCODE_FUNC(NAME, IMPORTER)                                 \
283a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorasize_t NAME(const uint8_t* in, int w, int h, int bps, uint8_t** out) {       \
284a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora  return Encode(in, w, h, bps, IMPORTER, LOSSLESS_DEFAULT_QUALITY, 1, out);  \
285a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora}
286a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
2878b720228d581a84fd173b6dcb2fa295b59db489aVikas AroraLOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGB, WebPPictureImportRGB)
2888b720228d581a84fd173b6dcb2fa295b59db489aVikas AroraLOSSLESS_ENCODE_FUNC(WebPEncodeLosslessRGBA, WebPPictureImportRGBA)
289a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern#if !defined(WEBP_REDUCE_CSP)
290a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames ZernLOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGR, WebPPictureImportBGR)
2918b720228d581a84fd173b6dcb2fa295b59db489aVikas AroraLOSSLESS_ENCODE_FUNC(WebPEncodeLosslessBGRA, WebPPictureImportBGRA)
292a187300ff9a8a7c10b1fb2ec84223fdd14e6d47bJames Zern#endif  // WEBP_REDUCE_CSP
293a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
294a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#undef LOSSLESS_ENCODE_FUNC
295a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora
296a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------
297