blob: d5d4f882beb4f8ca58c123824869ecc4f341c0fb [file] [log] [blame]
// 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 <assert.h>
#include <stdlib.h>
#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