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