diff options
Diffstat (limited to 'src/3rdparty/libwebp/src/enc/alpha.c')
-rw-r--r-- | src/3rdparty/libwebp/src/enc/alpha.c | 101 |
1 files changed, 62 insertions, 39 deletions
diff --git a/src/3rdparty/libwebp/src/enc/alpha.c b/src/3rdparty/libwebp/src/enc/alpha.c index 21d4b5c..79cb94d 100644 --- a/src/3rdparty/libwebp/src/enc/alpha.c +++ b/src/3rdparty/libwebp/src/enc/alpha.c @@ -17,6 +17,7 @@ #include "./vp8enci.h" #include "../utils/filters.h" #include "../utils/quant_levels.h" +#include "../utils/utils.h" #include "../webp/format_constants.h" // ----------------------------------------------------------------------------- @@ -34,7 +35,7 @@ // // 'output' corresponds to the buffer containing compressed alpha data. // This buffer is allocated by this method and caller should call -// free(*output) when done. +// WebPSafeFree(*output) when done. // 'output_size' corresponds to size of this compressed alpha buffer. // // Returns 1 on successfully encoding the alpha and @@ -46,12 +47,11 @@ static int EncodeLossless(const uint8_t* const data, int width, int height, int effort_level, // in [0..6] range - VP8BitWriter* const bw, + VP8LBitWriter* const bw, WebPAuxStats* const stats) { int ok = 0; WebPConfig config; WebPPicture picture; - VP8LBitWriter tmp_bw; WebPPictureInit(&picture); picture.width = width; @@ -83,16 +83,15 @@ static int EncodeLossless(const uint8_t* const data, int width, int height, config.quality = 8.f * effort_level; assert(config.quality >= 0 && config.quality <= 100.f); - ok = VP8LBitWriterInit(&tmp_bw, (width * height) >> 3); - ok = ok && (VP8LEncodeStream(&config, &picture, &tmp_bw) == VP8_ENC_OK); + ok = (VP8LEncodeStream(&config, &picture, bw) == VP8_ENC_OK); WebPPictureFree(&picture); - if (ok) { - const uint8_t* const buffer = VP8LBitWriterFinish(&tmp_bw); - const size_t buffer_size = VP8LBitWriterNumBytes(&tmp_bw); - VP8BitWriterAppend(bw, buffer, buffer_size); + ok = ok && !bw->error_; + if (!ok) { + VP8LBitWriterDestroy(bw); + return 0; } - VP8LBitWriterDestroy(&tmp_bw); - return ok && !bw->error_; + return 1; + } // ----------------------------------------------------------------------------- @@ -114,8 +113,10 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height, const uint8_t* alpha_src; WebPFilterFunc filter_func; uint8_t header; - size_t expected_size; const size_t data_size = width * height; + const uint8_t* output = NULL; + size_t output_size = 0; + VP8LBitWriter tmp_bw; assert((uint64_t)data_size == (uint64_t)width * height); // as per spec assert(filter >= 0 && filter < WEBP_FILTER_LAST); @@ -124,15 +125,6 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height, assert(sizeof(header) == ALPHA_HEADER_LEN); // TODO(skal): have a common function and #define's to validate alpha params. - expected_size = - (method == ALPHA_NO_COMPRESSION) ? (ALPHA_HEADER_LEN + data_size) - : (data_size >> 5); - header = method | (filter << 2); - if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4; - - VP8BitWriterInit(&result->bw, expected_size); - VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN); - filter_func = WebPFilters[filter]; if (filter_func != NULL) { filter_func(data, width, height, width, tmp_alpha); @@ -141,14 +133,42 @@ static int EncodeAlphaInternal(const uint8_t* const data, int width, int height, alpha_src = data; } + if (method != ALPHA_NO_COMPRESSION) { + ok = VP8LBitWriterInit(&tmp_bw, data_size >> 3); + ok = ok && EncodeLossless(alpha_src, width, height, effort_level, + &tmp_bw, &result->stats); + if (ok) { + output = VP8LBitWriterFinish(&tmp_bw); + output_size = VP8LBitWriterNumBytes(&tmp_bw); + if (output_size > data_size) { + // compressed size is larger than source! Revert to uncompressed mode. + method = ALPHA_NO_COMPRESSION; + VP8LBitWriterDestroy(&tmp_bw); + } + } else { + VP8LBitWriterDestroy(&tmp_bw); + return 0; + } + } + if (method == ALPHA_NO_COMPRESSION) { - ok = VP8BitWriterAppend(&result->bw, alpha_src, width * height); - ok = ok && !result->bw.error_; - } else { - ok = EncodeLossless(alpha_src, width, height, effort_level, - &result->bw, &result->stats); - VP8BitWriterFinish(&result->bw); + output = alpha_src; + output_size = data_size; + ok = 1; + } + + // Emit final result. + header = method | (filter << 2); + if (reduce_levels) header |= ALPHA_PREPROCESSED_LEVELS << 4; + + VP8BitWriterInit(&result->bw, ALPHA_HEADER_LEN + output_size); + ok = ok && VP8BitWriterAppend(&result->bw, &header, ALPHA_HEADER_LEN); + ok = ok && VP8BitWriterAppend(&result->bw, output, output_size); + + if (method != ALPHA_NO_COMPRESSION) { + VP8LBitWriterDestroy(&tmp_bw); } + ok = ok && !result->bw.error_; result->score = VP8BitWriterSize(&result->bw); return ok; } @@ -231,7 +251,7 @@ static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height, GetFilterMap(alpha, width, height, filter, effort_level); InitFilterTrial(&best); if (try_map != FILTER_TRY_NONE) { - uint8_t* filtered_alpha = (uint8_t*)malloc(data_size); + uint8_t* filtered_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); if (filtered_alpha == NULL) return 0; for (filter = WEBP_FILTER_NONE; ok && try_map; ++filter, try_map >>= 1) { @@ -248,7 +268,7 @@ static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height, } } } - free(filtered_alpha); + WebPSafeFree(filtered_alpha); } else { ok = EncodeAlphaInternal(alpha, width, height, method, WEBP_FILTER_NONE, reduce_levels, effort_level, NULL, &best); @@ -298,7 +318,7 @@ static int EncodeAlpha(VP8Encoder* const enc, filter = WEBP_FILTER_NONE; } - quant_alpha = (uint8_t*)malloc(data_size); + quant_alpha = (uint8_t*)WebPSafeMalloc(1ULL, data_size); if (quant_alpha == NULL) { return 0; } @@ -325,7 +345,7 @@ static int EncodeAlpha(VP8Encoder* const enc, } } - free(quant_alpha); + WebPSafeFree(quant_alpha); return ok; } @@ -346,7 +366,7 @@ static int CompressAlphaJob(VP8Encoder* const enc, void* dummy) { return 0; } if (alpha_size != (uint32_t)alpha_size) { // Sanity check. - free(alpha_data); + WebPSafeFree(alpha_data); return 0; } enc->alpha_data_size_ = (uint32_t)alpha_size; @@ -361,7 +381,7 @@ void VP8EncInitAlpha(VP8Encoder* const enc) { enc->alpha_data_size_ = 0; if (enc->thread_level_ > 0) { WebPWorker* const worker = &enc->alpha_worker_; - WebPWorkerInit(worker); + WebPGetWorkerInterface()->Init(worker); worker->data1 = enc; worker->data2 = NULL; worker->hook = (WebPWorkerHook)CompressAlphaJob; @@ -372,10 +392,11 @@ int VP8EncStartAlpha(VP8Encoder* const enc) { if (enc->has_alpha_) { if (enc->thread_level_ > 0) { WebPWorker* const worker = &enc->alpha_worker_; - if (!WebPWorkerReset(worker)) { // Makes sure worker is good to go. + // Makes sure worker is good to go. + if (!WebPGetWorkerInterface()->Reset(worker)) { return 0; } - WebPWorkerLaunch(worker); + WebPGetWorkerInterface()->Launch(worker); return 1; } else { return CompressAlphaJob(enc, NULL); // just do the job right away @@ -388,7 +409,7 @@ int VP8EncFinishAlpha(VP8Encoder* const enc) { if (enc->has_alpha_) { if (enc->thread_level_ > 0) { WebPWorker* const worker = &enc->alpha_worker_; - if (!WebPWorkerSync(worker)) return 0; // error + if (!WebPGetWorkerInterface()->Sync(worker)) return 0; // error } } return WebPReportProgress(enc->pic_, enc->percent_ + 20, &enc->percent_); @@ -398,10 +419,12 @@ int VP8EncDeleteAlpha(VP8Encoder* const enc) { int ok = 1; if (enc->thread_level_ > 0) { WebPWorker* const worker = &enc->alpha_worker_; - ok = WebPWorkerSync(worker); // finish anything left in flight - WebPWorkerEnd(worker); // still need to end the worker, even if !ok + // finish anything left in flight + ok = WebPGetWorkerInterface()->Sync(worker); + // still need to end the worker, even if !ok + WebPGetWorkerInterface()->End(worker); } - free(enc->alpha_data_); + WebPSafeFree(enc->alpha_data_); enc->alpha_data_ = NULL; enc->alpha_data_size_ = 0; enc->has_alpha_ = 0; |