// Copyright 2011 Google Inc. // // This code is licensed under the same terms as WebM: // Software License Agreement: http://www.webmproject.org/license/software/ // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ // ----------------------------------------------------------------------------- // // Alpha-plane compression. // // Author: Skal (pascal.massimino@gmail.com) #include #include #include "vp8enci.h" #ifdef WEBP_EXPERIMENTAL_FEATURES #include "zlib.h" #endif #if defined(__cplusplus) || defined(c_plusplus) extern "C" { #endif #ifdef WEBP_EXPERIMENTAL_FEATURES #define CHUNK_SIZE 8192 //----------------------------------------------------------------------------- static int CompressAlpha(const uint8_t* data, size_t data_size, uint8_t** output, size_t* output_size, int algo) { int ret = Z_OK; z_stream strm; unsigned char chunk[CHUNK_SIZE]; *output = NULL; *output_size = 0; memset(&strm, 0, sizeof(strm)); if (deflateInit(&strm, algo ? Z_BEST_SPEED : Z_BEST_COMPRESSION) != Z_OK) { return 0; } strm.next_in = (unsigned char*)data; strm.avail_in = data_size; do { size_t size_out; strm.next_out = chunk; strm.avail_out = CHUNK_SIZE; ret = deflate(&strm, Z_FINISH); if (ret == Z_STREAM_ERROR) { break; } size_out = CHUNK_SIZE - strm.avail_out; if (size_out) { size_t new_size = *output_size + size_out; uint8_t* new_output = realloc(*output, new_size); if (new_output == NULL) { ret = Z_MEM_ERROR; break; } memcpy(new_output + *output_size, chunk, size_out); *output_size = new_size; *output = new_output; } } while (ret != Z_STREAM_END || strm.avail_out == 0); deflateEnd(&strm); if (ret != Z_STREAM_END) { free(*output); output_size = 0; return 0; } return 1; } #endif /* WEBP_EXPERIMENTAL_FEATURES */ void VP8EncInitAlpha(VP8Encoder* enc) { enc->has_alpha_ = (enc->pic_->a != NULL); enc->alpha_data_ = NULL; enc->alpha_data_size_ = 0; } void VP8EncCodeAlphaBlock(VP8EncIterator* it) { (void)it; // Nothing for now. We just ZLIB-compress in the end. } int VP8EncFinishAlpha(VP8Encoder* enc) { if (enc->has_alpha_) { #ifdef WEBP_EXPERIMENTAL_FEATURES const WebPPicture* pic = enc->pic_; assert(pic->a); if (!CompressAlpha(pic->a, pic->width * pic->height, &enc->alpha_data_, &enc->alpha_data_size_, enc->config_->alpha_compression)) { return 0; } #endif } return 1; } void VP8EncDeleteAlpha(VP8Encoder* enc) { free(enc->alpha_data_); enc->alpha_data_ = NULL; enc->alpha_data_size_ = 0; enc->has_alpha_ = 0; } #if defined(__cplusplus) || defined(c_plusplus) } // extern "C" #endif