• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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