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)
21 extern "C" {
22 #endif
23
24 #ifdef WEBP_EXPERIMENTAL_FEATURES
25
26 #define CHUNK_SIZE 8192
27
28 //-----------------------------------------------------------------------------
29
CompressAlpha(const uint8_t * data,size_t data_size,uint8_t ** output,size_t * output_size,int algo)30 static 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
VP8EncInitAlpha(VP8Encoder * enc)79 void VP8EncInitAlpha(VP8Encoder* enc) {
80 enc->has_alpha_ = (enc->pic_->a != NULL);
81 enc->alpha_data_ = NULL;
82 enc->alpha_data_size_ = 0;
83 }
84
VP8EncCodeAlphaBlock(VP8EncIterator * it)85 void VP8EncCodeAlphaBlock(VP8EncIterator* it) {
86 (void)it;
87 // Nothing for now. We just ZLIB-compress in the end.
88 }
89
VP8EncFinishAlpha(VP8Encoder * enc)90 int 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
VP8EncDeleteAlpha(VP8Encoder * enc)105 void 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