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 (at) 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 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 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 85 void VP8EncCodeAlphaBlock(VP8EncIterator* it) { 86 (void)it; 87 // Nothing for now. We just ZLIB-compress in the end. 88 } 89 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 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