summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/libwebp/src/enc/alpha.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/libwebp/src/enc/alpha.c')
-rw-r--r--src/3rdparty/libwebp/src/enc/alpha.c101
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;