mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
alpha: preparatory cleanup
* make ALPHNew/Delete static * properly init ALPHDec::io_ * introduce AllocateAlphaPlane() and WebPDeallocateAlphaMemory() * reorganize VP8DecompressAlphaRows() but we're still allocate the full alpha-plane. Optim will come in another patch since it's tricky Change-Id: Ib6f190a40abb7926a71535b0ed67c39d0974e06a
This commit is contained in:
parent
b95ac0a221
commit
cf6c713a0b
@ -23,12 +23,14 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// ALPHDecoder object.
|
||||
|
||||
ALPHDecoder* ALPHNew(void) {
|
||||
// Allocates a new alpha decoder instance.
|
||||
static ALPHDecoder* ALPHNew(void) {
|
||||
ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
|
||||
return dec;
|
||||
}
|
||||
|
||||
void ALPHDelete(ALPHDecoder* const dec) {
|
||||
// Clears and deallocates an alpha decoder instance.
|
||||
static void ALPHDelete(ALPHDecoder* const dec) {
|
||||
if (dec != NULL) {
|
||||
VP8LDelete(dec->vp8l_dec_);
|
||||
dec->vp8l_dec_ = NULL;
|
||||
@ -44,17 +46,19 @@ void ALPHDelete(ALPHDecoder* const dec) {
|
||||
// Returns false in case of error in alpha header (data too short, invalid
|
||||
// compression method or filter, error in lossless header data etc).
|
||||
static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
|
||||
size_t data_size, int width, int height, uint8_t* output) {
|
||||
size_t data_size, const VP8Io* const src_io,
|
||||
uint8_t* output) {
|
||||
int ok = 0;
|
||||
const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
|
||||
const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
|
||||
int rsrv;
|
||||
VP8Io* const io = &dec->io_;
|
||||
|
||||
assert(width > 0 && height > 0);
|
||||
assert(data != NULL && output != NULL);
|
||||
assert(data != NULL && output != NULL && src_io != NULL);
|
||||
|
||||
dec->width_ = width;
|
||||
dec->height_ = height;
|
||||
dec->width_ = src_io->width;
|
||||
dec->height_ = src_io->height;
|
||||
assert(dec->width_ > 0 && dec->height_ > 0);
|
||||
|
||||
if (data_size <= ALPHA_HEADER_LEN) {
|
||||
return 0;
|
||||
@ -80,6 +84,21 @@ static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
|
||||
ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size, output);
|
||||
}
|
||||
VP8FiltersInit();
|
||||
|
||||
// Copy the necessary parameters from src_io to io
|
||||
VP8InitIo(io);
|
||||
WebPInitCustomIo(NULL, io);
|
||||
io->opaque = output; // output plane
|
||||
io->width = src_io->width;
|
||||
io->height = src_io->height;
|
||||
|
||||
io->use_cropping = src_io->use_cropping;
|
||||
io->crop_left = src_io->crop_left;
|
||||
io->crop_right = src_io->crop_right;
|
||||
io->crop_top = src_io->crop_top;
|
||||
io->crop_bottom = src_io->crop_bottom;
|
||||
// No need to copy the scaling parameters.
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
@ -116,6 +135,27 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int AllocateAlphaPlane(VP8Decoder* const dec, const VP8Io* const io) {
|
||||
const int stride = io->width;
|
||||
const int height = io->height;
|
||||
const uint64_t alpha_size = (uint64_t)stride * height;
|
||||
assert(dec->alpha_plane_mem_ == NULL);
|
||||
dec->alpha_plane_mem_ =
|
||||
(uint8_t*)WebPSafeMalloc(alpha_size, sizeof(*dec->alpha_plane_));
|
||||
if (dec->alpha_plane_mem_ == NULL) return 0;
|
||||
dec->alpha_plane_ = dec->alpha_plane_mem_;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void WebPDeallocateAlphaMemory(VP8Decoder* const dec) {
|
||||
assert(dec != NULL);
|
||||
WebPSafeFree(dec->alpha_plane_mem_);
|
||||
dec->alpha_plane_mem_ = NULL;
|
||||
dec->alpha_plane_ = NULL;
|
||||
ALPHDelete(dec->alph_dec_);
|
||||
dec->alph_dec_ = NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Main entry point.
|
||||
|
||||
@ -132,41 +172,42 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
||||
}
|
||||
|
||||
if (!dec->is_alpha_decoded_) {
|
||||
int ok;
|
||||
if (dec->alph_dec_ == NULL) { // Initialize decoder.
|
||||
assert(dec->alpha_plane_ != NULL);
|
||||
dec->alph_dec_ = ALPHNew();
|
||||
if (dec->alph_dec_ == NULL) return NULL;
|
||||
if (!AllocateAlphaPlane(dec, io)) goto Error;
|
||||
if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_,
|
||||
io->width, io->height, dec->alpha_plane_)) {
|
||||
ALPHDelete(dec->alph_dec_);
|
||||
dec->alph_dec_ = NULL;
|
||||
return NULL;
|
||||
io, dec->alpha_plane_)) {
|
||||
goto Error;
|
||||
}
|
||||
// if we allowed use of alpha dithering, check whether it's needed at all
|
||||
if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) {
|
||||
dec->alpha_dithering_ = 0; // disable dithering
|
||||
} else {
|
||||
num_rows = height; // decode everything in one pass
|
||||
num_rows = io->height - row; // decode everything in one pass
|
||||
}
|
||||
}
|
||||
|
||||
if (row + num_rows > height) {
|
||||
num_rows = height - row;
|
||||
}
|
||||
|
||||
ok = ALPHDecode(dec, row, num_rows);
|
||||
assert(dec->alph_dec_ != NULL);
|
||||
if (!ok || dec->is_alpha_decoded_) {
|
||||
assert(row + num_rows <= io->height);
|
||||
if (!ALPHDecode(dec, row, num_rows)) goto Error;
|
||||
|
||||
if (dec->is_alpha_decoded_) { // finished?
|
||||
ALPHDelete(dec->alph_dec_);
|
||||
dec->alph_dec_ = NULL;
|
||||
if (dec->alpha_dithering_ > 0) {
|
||||
if (!WebPDequantizeLevels(dec->alpha_plane_, width, height, width,
|
||||
dec->alpha_dithering_)) {
|
||||
goto Error;
|
||||
}
|
||||
if (ok && dec->is_alpha_decoded_ && dec->alpha_dithering_ > 0) {
|
||||
ok = WebPDequantizeLevels(dec->alpha_plane_, width, height, width,
|
||||
dec->alpha_dithering_);
|
||||
}
|
||||
if (!ok) return NULL; // Error.
|
||||
}
|
||||
}
|
||||
|
||||
// Return a pointer to the current decoded row.
|
||||
return dec->alpha_plane_ + row * width;
|
||||
|
||||
Error:
|
||||
WebPDeallocateAlphaMemory(dec);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -40,11 +40,8 @@ struct ALPHDecoder {
|
||||
//------------------------------------------------------------------------------
|
||||
// internal functions. Not public.
|
||||
|
||||
// Allocates a new alpha decoder instance.
|
||||
ALPHDecoder* ALPHNew(void);
|
||||
|
||||
// Clears and deallocates an alpha decoder instance.
|
||||
void ALPHDelete(ALPHDecoder* const dec);
|
||||
// Deallocate memory associated to dec->alpha_plane_ decoding
|
||||
void WebPDeallocateAlphaMemory(VP8Decoder* const dec);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -656,8 +656,7 @@ void VP8Clear(VP8Decoder* const dec) {
|
||||
return;
|
||||
}
|
||||
WebPGetWorkerInterface()->End(&dec->worker_);
|
||||
ALPHDelete(dec->alph_dec_);
|
||||
dec->alph_dec_ = NULL;
|
||||
WebPDeallocateAlphaMemory(dec);
|
||||
WebPSafeFree(dec->mem_);
|
||||
dec->mem_ = NULL;
|
||||
dec->mem_size_ = 0;
|
||||
@ -666,4 +665,3 @@ void VP8Clear(VP8Decoder* const dec) {
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
@ -259,8 +259,9 @@ struct VP8Decoder {
|
||||
const uint8_t* alpha_data_; // compressed alpha data (if present)
|
||||
size_t alpha_data_size_;
|
||||
int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_
|
||||
uint8_t* alpha_plane_mem_; // memory allocated for alpha_plane_
|
||||
uint8_t* alpha_plane_; // output. Persistent, contains the whole data.
|
||||
int alpha_dithering_; // derived from decoding options (0=off, 100=full).
|
||||
int alpha_dithering_; // derived from decoding options (0=off, 100=full)
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user