Add Alpha Encode support from WebPEncode.

Extend WebP Encode functionality to encode Alpha data and produce
bit-stream (RIFF+VP8X+ALPH+VP8) corresponding to WebP-Alpha.

Change-Id: I983b4cd97be94a86a8e6d03b3b9c728db851bf48
This commit is contained in:
Vikas Arora
2011-12-01 12:14:15 +05:30
parent 16612ddd30
commit 9523f2a5de
9 changed files with 207 additions and 138 deletions

View File

@ -12,92 +12,38 @@
#include <assert.h>
#include <stdlib.h>
#include "vp8enci.h"
#ifdef WEBP_EXPERIMENTAL_FEATURES
#include "zlib.h"
#endif
#include "../utils/alpha.h"
#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 WebPConfig* config = enc->config_;
const WebPPicture* pic = enc->pic_;
uint8_t* tmp_data = NULL;
size_t tmp_size = 0;
assert(pic->a);
if (!CompressAlpha(pic->a, pic->width * pic->height,
&enc->alpha_data_, &enc->alpha_data_size_,
enc->config_->alpha_compression)) {
if (!EncodeAlpha(pic->a, pic->width, pic->height, pic->a_stride,
config->alpha_quality, config->alpha_compression,
&tmp_data, &tmp_size)) {
return 0;
}
#endif
if (tmp_size != (uint32_t)tmp_size) { // Sanity check.
free(tmp_data);
return 0;
}
enc->alpha_data_size_ = (uint32_t)tmp_size;
enc->alpha_data_ = tmp_data;
}
return 1;
}