alpha.c revision 466727975bcc57c0c5597bcd0747a2fe4777b303
1// Copyright 2011 Google Inc.
2//
3// This code is licensed under the same terms as WebM:
4//  Software License Agreement:  http://www.webmproject.org/license/software/
5//  Additional IP Rights Grant:  http://www.webmproject.org/license/additional/
6// -----------------------------------------------------------------------------
7//
8// Alpha-plane compression.
9//
10// Author: Skal (pascal.massimino@gmail.com)
11
12#include <assert.h>
13#include <stdlib.h>
14#include "vp8enci.h"
15
16#ifdef WEBP_EXPERIMENTAL_FEATURES
17#include "zlib.h"
18#endif
19
20#if defined(__cplusplus) || defined(c_plusplus)
21extern "C" {
22#endif
23
24#ifdef WEBP_EXPERIMENTAL_FEATURES
25
26#define CHUNK_SIZE 8192
27
28//-----------------------------------------------------------------------------
29
30static int CompressAlpha(const uint8_t* data, size_t data_size,
31                         uint8_t** output, size_t* output_size,
32                         int algo) {
33  int ret = Z_OK;
34  z_stream strm;
35  unsigned char chunk[CHUNK_SIZE];
36
37  *output = NULL;
38  *output_size = 0;
39  memset(&strm, 0, sizeof(strm));
40  if (deflateInit(&strm, algo ? Z_BEST_SPEED : Z_BEST_COMPRESSION) != Z_OK) {
41    return 0;
42  }
43  strm.next_in = (unsigned char*)data;
44  strm.avail_in = data_size;
45  do {
46    size_t size_out;
47
48    strm.next_out = chunk;
49    strm.avail_out = CHUNK_SIZE;
50    ret = deflate(&strm, Z_FINISH);
51    if (ret == Z_STREAM_ERROR) {
52      break;
53    }
54    size_out = CHUNK_SIZE - strm.avail_out;
55    if (size_out) {
56      size_t new_size = *output_size + size_out;
57      uint8_t* new_output = realloc(*output, new_size);
58      if (new_output == NULL) {
59        ret = Z_MEM_ERROR;
60        break;
61      }
62      memcpy(new_output + *output_size, chunk, size_out);
63      *output_size = new_size;
64      *output = new_output;
65    }
66  } while (ret != Z_STREAM_END || strm.avail_out == 0);
67
68  deflateEnd(&strm);
69  if (ret != Z_STREAM_END) {
70    free(*output);
71    output_size = 0;
72    return 0;
73  }
74  return 1;
75}
76
77#endif    /* WEBP_EXPERIMENTAL_FEATURES */
78
79void VP8EncInitAlpha(VP8Encoder* enc) {
80  enc->has_alpha_ = (enc->pic_->a != NULL);
81  enc->alpha_data_ = NULL;
82  enc->alpha_data_size_ = 0;
83}
84
85void VP8EncCodeAlphaBlock(VP8EncIterator* it) {
86  (void)it;
87  // Nothing for now. We just ZLIB-compress in the end.
88}
89
90int VP8EncFinishAlpha(VP8Encoder* enc) {
91  if (enc->has_alpha_) {
92#ifdef WEBP_EXPERIMENTAL_FEATURES
93    const WebPPicture* pic = enc->pic_;
94    assert(pic->a);
95    if (!CompressAlpha(pic->a, pic->width * pic->height,
96                       &enc->alpha_data_, &enc->alpha_data_size_,
97                       enc->config_->alpha_compression)) {
98      return 0;
99    }
100#endif
101  }
102  return 1;
103}
104
105void VP8EncDeleteAlpha(VP8Encoder* enc) {
106  free(enc->alpha_data_);
107  enc->alpha_data_ = NULL;
108  enc->alpha_data_size_ = 0;
109  enc->has_alpha_ = 0;
110}
111
112#if defined(__cplusplus) || defined(c_plusplus)
113}    // extern "C"
114#endif
115