1466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Copyright 2011 Google Inc.
2466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora//
3466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// This code is licensed under the same terms as WebM:
4466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora//  Software License Agreement:  http://www.webmproject.org/license/software/
5466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora//  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
6466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// -----------------------------------------------------------------------------
7466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora//
8466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Alpha-plane compression.
9466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora//
10466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora// Author: Skal (pascal.massimino@gmail.com)
11466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
12466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#include <assert.h>
13466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#include <stdlib.h>
14466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#include "vp8enci.h"
15466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
16466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#ifdef WEBP_EXPERIMENTAL_FEATURES
17466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#include "zlib.h"
18466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#endif
19466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
20466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#if defined(__cplusplus) || defined(c_plusplus)
21466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroraextern "C" {
22466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#endif
23466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
24466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#ifdef WEBP_EXPERIMENTAL_FEATURES
25466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
26466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#define CHUNK_SIZE 8192
27466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
28466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora//-----------------------------------------------------------------------------
29466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
30466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arorastatic int CompressAlpha(const uint8_t* data, size_t data_size,
31466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora                         uint8_t** output, size_t* output_size,
32466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora                         int algo) {
33466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  int ret = Z_OK;
34466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  z_stream strm;
35466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  unsigned char chunk[CHUNK_SIZE];
36466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
37466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  *output = NULL;
38466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  *output_size = 0;
39466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  memset(&strm, 0, sizeof(strm));
40466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  if (deflateInit(&strm, algo ? Z_BEST_SPEED : Z_BEST_COMPRESSION) != Z_OK) {
41466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    return 0;
42466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  }
43466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  strm.next_in = (unsigned char*)data;
44466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  strm.avail_in = data_size;
45466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  do {
46466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    size_t size_out;
47466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
48466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    strm.next_out = chunk;
49466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    strm.avail_out = CHUNK_SIZE;
50466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    ret = deflate(&strm, Z_FINISH);
51466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    if (ret == Z_STREAM_ERROR) {
52466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      break;
53466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    }
54466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    size_out = CHUNK_SIZE - strm.avail_out;
55466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    if (size_out) {
56466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      size_t new_size = *output_size + size_out;
57466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      uint8_t* new_output = realloc(*output, new_size);
58466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      if (new_output == NULL) {
59466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora        ret = Z_MEM_ERROR;
60466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora        break;
61466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      }
62466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      memcpy(new_output + *output_size, chunk, size_out);
63466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      *output_size = new_size;
64466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      *output = new_output;
65466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    }
66466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  } while (ret != Z_STREAM_END || strm.avail_out == 0);
67466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
68466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  deflateEnd(&strm);
69466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  if (ret != Z_STREAM_END) {
70466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    free(*output);
71466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    output_size = 0;
72466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    return 0;
73466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  }
74466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  return 1;
75466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora}
76466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
77466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#endif    /* WEBP_EXPERIMENTAL_FEATURES */
78466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
79466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroravoid VP8EncInitAlpha(VP8Encoder* enc) {
80466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  enc->has_alpha_ = (enc->pic_->a != NULL);
81466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  enc->alpha_data_ = NULL;
82466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  enc->alpha_data_size_ = 0;
83466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora}
84466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
85466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroravoid VP8EncCodeAlphaBlock(VP8EncIterator* it) {
86466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  (void)it;
87466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  // Nothing for now. We just ZLIB-compress in the end.
88466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora}
89466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
90466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroraint VP8EncFinishAlpha(VP8Encoder* enc) {
91466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  if (enc->has_alpha_) {
92466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#ifdef WEBP_EXPERIMENTAL_FEATURES
93466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    const WebPPicture* pic = enc->pic_;
94466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    assert(pic->a);
95466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    if (!CompressAlpha(pic->a, pic->width * pic->height,
96466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora                       &enc->alpha_data_, &enc->alpha_data_size_,
97466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora                       enc->config_->alpha_compression)) {
98466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora      return 0;
99466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora    }
100466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#endif
101466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  }
102466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  return 1;
103466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora}
104466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
105466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroravoid VP8EncDeleteAlpha(VP8Encoder* enc) {
106466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  free(enc->alpha_data_);
107466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  enc->alpha_data_ = NULL;
108466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  enc->alpha_data_size_ = 0;
109466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora  enc->has_alpha_ = 0;
110466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora}
111466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora
112466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#if defined(__cplusplus) || defined(c_plusplus)
113466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora}    // extern "C"
114466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora#endif
115