mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 06:08: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 object.
|
||||||
|
|
||||||
ALPHDecoder* ALPHNew(void) {
|
// Allocates a new alpha decoder instance.
|
||||||
|
static ALPHDecoder* ALPHNew(void) {
|
||||||
ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
|
ALPHDecoder* const dec = (ALPHDecoder*)WebPSafeCalloc(1ULL, sizeof(*dec));
|
||||||
return dec;
|
return dec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ALPHDelete(ALPHDecoder* const dec) {
|
// Clears and deallocates an alpha decoder instance.
|
||||||
|
static void ALPHDelete(ALPHDecoder* const dec) {
|
||||||
if (dec != NULL) {
|
if (dec != NULL) {
|
||||||
VP8LDelete(dec->vp8l_dec_);
|
VP8LDelete(dec->vp8l_dec_);
|
||||||
dec->vp8l_dec_ = NULL;
|
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
|
// Returns false in case of error in alpha header (data too short, invalid
|
||||||
// compression method or filter, error in lossless header data etc).
|
// compression method or filter, error in lossless header data etc).
|
||||||
static int ALPHInit(ALPHDecoder* const dec, const uint8_t* data,
|
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;
|
int ok = 0;
|
||||||
const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
|
const uint8_t* const alpha_data = data + ALPHA_HEADER_LEN;
|
||||||
const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
|
const size_t alpha_data_size = data_size - ALPHA_HEADER_LEN;
|
||||||
int rsrv;
|
int rsrv;
|
||||||
|
VP8Io* const io = &dec->io_;
|
||||||
|
|
||||||
assert(width > 0 && height > 0);
|
assert(data != NULL && output != NULL && src_io != NULL);
|
||||||
assert(data != NULL && output != NULL);
|
|
||||||
|
|
||||||
dec->width_ = width;
|
dec->width_ = src_io->width;
|
||||||
dec->height_ = height;
|
dec->height_ = src_io->height;
|
||||||
|
assert(dec->width_ > 0 && dec->height_ > 0);
|
||||||
|
|
||||||
if (data_size <= ALPHA_HEADER_LEN) {
|
if (data_size <= ALPHA_HEADER_LEN) {
|
||||||
return 0;
|
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);
|
ok = VP8LDecodeAlphaHeader(dec, alpha_data, alpha_data_size, output);
|
||||||
}
|
}
|
||||||
VP8FiltersInit();
|
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;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,6 +135,27 @@ static int ALPHDecode(VP8Decoder* const dec, int row, int num_rows) {
|
|||||||
return 1;
|
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.
|
// Main entry point.
|
||||||
|
|
||||||
@ -132,41 +172,42 @@ const uint8_t* VP8DecompressAlphaRows(VP8Decoder* const dec,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!dec->is_alpha_decoded_) {
|
if (!dec->is_alpha_decoded_) {
|
||||||
int ok;
|
|
||||||
if (dec->alph_dec_ == NULL) { // Initialize decoder.
|
if (dec->alph_dec_ == NULL) { // Initialize decoder.
|
||||||
assert(dec->alpha_plane_ != NULL);
|
|
||||||
dec->alph_dec_ = ALPHNew();
|
dec->alph_dec_ = ALPHNew();
|
||||||
if (dec->alph_dec_ == NULL) return NULL;
|
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_,
|
if (!ALPHInit(dec->alph_dec_, dec->alpha_data_, dec->alpha_data_size_,
|
||||||
io->width, io->height, dec->alpha_plane_)) {
|
io, dec->alpha_plane_)) {
|
||||||
ALPHDelete(dec->alph_dec_);
|
goto Error;
|
||||||
dec->alph_dec_ = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
// if we allowed use of alpha dithering, check whether it's needed at all
|
// if we allowed use of alpha dithering, check whether it's needed at all
|
||||||
if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) {
|
if (dec->alph_dec_->pre_processing_ != ALPHA_PREPROCESSED_LEVELS) {
|
||||||
dec->alpha_dithering_ = 0; // disable dithering
|
dec->alpha_dithering_ = 0; // disable dithering
|
||||||
} else {
|
} 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);
|
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_);
|
ALPHDelete(dec->alph_dec_);
|
||||||
dec->alph_dec_ = NULL;
|
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 a pointer to the current decoded row.
|
||||||
return dec->alpha_plane_ + row * width;
|
return dec->alpha_plane_ + row * width;
|
||||||
|
|
||||||
|
Error:
|
||||||
|
WebPDeallocateAlphaMemory(dec);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -40,11 +40,8 @@ struct ALPHDecoder {
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// internal functions. Not public.
|
// internal functions. Not public.
|
||||||
|
|
||||||
// Allocates a new alpha decoder instance.
|
// Deallocate memory associated to dec->alpha_plane_ decoding
|
||||||
ALPHDecoder* ALPHNew(void);
|
void WebPDeallocateAlphaMemory(VP8Decoder* const dec);
|
||||||
|
|
||||||
// Clears and deallocates an alpha decoder instance.
|
|
||||||
void ALPHDelete(ALPHDecoder* const dec);
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -656,8 +656,7 @@ void VP8Clear(VP8Decoder* const dec) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
WebPGetWorkerInterface()->End(&dec->worker_);
|
WebPGetWorkerInterface()->End(&dec->worker_);
|
||||||
ALPHDelete(dec->alph_dec_);
|
WebPDeallocateAlphaMemory(dec);
|
||||||
dec->alph_dec_ = NULL;
|
|
||||||
WebPSafeFree(dec->mem_);
|
WebPSafeFree(dec->mem_);
|
||||||
dec->mem_ = NULL;
|
dec->mem_ = NULL;
|
||||||
dec->mem_size_ = 0;
|
dec->mem_size_ = 0;
|
||||||
@ -666,4 +665,3 @@ void VP8Clear(VP8Decoder* const dec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -258,9 +258,10 @@ struct VP8Decoder {
|
|||||||
struct ALPHDecoder* alph_dec_; // alpha-plane decoder object
|
struct ALPHDecoder* alph_dec_; // alpha-plane decoder object
|
||||||
const uint8_t* alpha_data_; // compressed alpha data (if present)
|
const uint8_t* alpha_data_; // compressed alpha data (if present)
|
||||||
size_t alpha_data_size_;
|
size_t alpha_data_size_;
|
||||||
int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_
|
int is_alpha_decoded_; // true if alpha_data_ is decoded in alpha_plane_
|
||||||
uint8_t* alpha_plane_; // output. Persistent, contains the whole data.
|
uint8_t* alpha_plane_mem_; // memory allocated for alpha_plane_
|
||||||
int alpha_dithering_; // derived from decoding options (0=off, 100=full).
|
uint8_t* alpha_plane_; // output. Persistent, contains the whole data.
|
||||||
|
int alpha_dithering_; // derived from decoding options (0=off, 100=full)
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user