diff --git a/src/dec/alpha.c b/src/dec/alpha.c index 47c70395..4a6d25e5 100644 --- a/src/dec/alpha.c +++ b/src/dec/alpha.c @@ -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 + 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; } diff --git a/src/dec/alphai.h b/src/dec/alphai.h index b4170229..ea4ce2f4 100644 --- a/src/dec/alphai.h +++ b/src/dec/alphai.h @@ -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); //------------------------------------------------------------------------------ diff --git a/src/dec/vp8.c b/src/dec/vp8.c index 214b8273..955c784d 100644 --- a/src/dec/vp8.c +++ b/src/dec/vp8.c @@ -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) { } //------------------------------------------------------------------------------ - diff --git a/src/dec/vp8i.h b/src/dec/vp8i.h index 6b9afd75..ef14f4ec 100644 --- a/src/dec/vp8i.h +++ b/src/dec/vp8i.h @@ -258,9 +258,10 @@ struct VP8Decoder { struct ALPHDecoder* alph_dec_; // alpha-plane decoder object 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_; // output. Persistent, contains the whole data. - int alpha_dithering_; // derived from decoding options (0=off, 100=full). + 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) }; //------------------------------------------------------------------------------