From a80fcc4ae1c1121abd0ec84c54b5ce39a0041c80 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Thu, 31 Aug 2017 14:02:05 +0200 Subject: [PATCH] ifdef code not used by Chrome/Android. Change-Id: Id086f6fd602b1fe3dc9034764b6a920a696ff1d2 --- CMakeLists.txt | 1 + cmake/config.h.in | 3 +++ configure.ac | 15 +++++++++++++++ src/enc/near_lossless_enc.c | 9 +++++++++ src/enc/predictor_enc.c | 24 +++++++++++++++++++++--- src/enc/vp8l_enc.c | 8 ++++++++ src/enc/vp8li_enc.h | 11 +++++++++++ 7 files changed, 68 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7028a8e0..7b2020cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ option(WEBP_BUILD_GIF2WEBP "Build the gif2webp conversion tool." OFF) option(WEBP_BUILD_IMG2WEBP "Build the img2webp animation tool." OFF) option(WEBP_BUILD_WEBPINFO "Build the webpinfo command line tool." OFF) option(WEBP_BUILD_WEBP_JS "Emscripten build of webp.js." OFF) +option(WEBP_ENABLE_NEAR_LOSSLESS "Enable near-lossless encoding" ON) option(WEBP_EXPERIMENTAL_FEATURES "Build with experimental features." OFF) option(WEBP_ENABLE_SWAP_16BIT_CSP "Enable byte swap for 16 bit colorspaces." OFF) diff --git a/cmake/config.h.in b/cmake/config.h.in index 32e10b53..9410a1b5 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -140,6 +140,9 @@ /* Set to 1 if TIFF library is installed */ #cmakedefine WEBP_HAVE_TIFF 1 +/* Enable near lossless encoding */ +#cmakedefine WEBP_NEAR_LOSSLESS 1 + /* Undefine this to disable thread support. */ #cmakedefine WEBP_USE_THREAD 1 diff --git a/configure.ac b/configure.ac index 928f7b13..b327a795 100644 --- a/configure.ac +++ b/configure.ac @@ -689,6 +689,21 @@ fi AC_MSG_RESULT(${enable_experimental-no}) AC_SUBST(USE_EXPERIMENTAL_CODE) +dnl === If --disable-near-lossless is defined, add -DWEBP_NEAR_LOSSLESS=0 + +AC_DEFINE(WEBP_NEAR_LOSSLESS, [1], [Enable near lossless encoding]) +AC_MSG_CHECKING(if --disable-near-lossless option is specified) +AC_ARG_ENABLE([near_lossless], + AS_HELP_STRING([--disable-near-lossless], + [Disable near lossless encoding]), + [], [enable_near_lossless=yes]) +if test "$enable_near_lossless" = "no"; then + AC_DEFINE(WEBP_NEAR_LOSSLESS, [0], [Enable near lossless encoding]) + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + dnl === Check whether libwebpmux should be built AC_MSG_CHECKING(whether libwebpmux is to be built) AC_ARG_ENABLE([libwebpmux], diff --git a/src/enc/near_lossless_enc.c b/src/enc/near_lossless_enc.c index 634f1df1..1a3ae0ad 100644 --- a/src/enc/near_lossless_enc.c +++ b/src/enc/near_lossless_enc.c @@ -21,6 +21,8 @@ #include "../utils/utils.h" #include "./vp8li_enc.h" +#if (WEBP_NEAR_LOSSLESS == 1) + #define MIN_DIM_FOR_NEAR_LOSSLESS 64 #define MAX_LIMIT_BITS 5 @@ -140,3 +142,10 @@ int VP8ApplyNearLossless(const WebPPicture* const picture, int quality, WebPSafeFree(copy_buffer); return 1; } +#else // (WEBP_NEAR_LOSSLESS == 1) + +// Define a stub to suppress compiler warnings. +extern void VP8LNearLosslessStub(void); +WEBP_TSAN_IGNORE_FUNCTION void VP8LNearLosslessStub(void) {} + +#endif // (WEBP_NEAR_LOSSLESS == 1) diff --git a/src/enc/predictor_enc.c b/src/enc/predictor_enc.c index 3fa3462b..791991d7 100644 --- a/src/enc/predictor_enc.c +++ b/src/enc/predictor_enc.c @@ -26,7 +26,6 @@ static const uint32_t kMaskAlpha = 0xff000000; // Mostly used to reduce code size + readability static WEBP_INLINE int GetMin(int a, int b) { return (a > b) ? b : a; } -static WEBP_INLINE int GetMax(int a, int b) { return (a < b) ? b : a; } //------------------------------------------------------------------------------ // Methods to calculate Entropy (Shannon). @@ -90,6 +89,9 @@ static WEBP_INLINE void PredictBatch(int mode, int x_start, int y, } } +#if (WEBP_NEAR_LOSSLESS == 1) +static WEBP_INLINE int GetMax(int a, int b) { return (a < b) ? b : a; } + static int MaxDiffBetweenPixels(uint32_t p1, uint32_t p2) { const int diff_a = abs((int)(p1 >> 24) - (int)(p2 >> 24)); const int diff_r = abs((int)((p1 >> 16) & 0xff) - (int)((p2 >> 16) & 0xff)); @@ -220,6 +222,7 @@ static uint32_t NearLossless(uint32_t value, uint32_t predict, return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; } #undef NEAR_LOSSLESS_DIFF +#endif // (WEBP_NEAR_LOSSLESS == 1) // Stores the difference between the pixel and its prediction in "out". // In case of a lossy encoding, updates the source image to avoid propagating @@ -246,6 +249,7 @@ static WEBP_INLINE void GetResidual( } else { predict = pred_func(current_row[x - 1], upper_row + x); } +#if (WEBP_NEAR_LOSSLESS == 1) if (max_quantization == 1 || mode == 0 || y == 0 || y == height - 1 || x == 0 || x == width - 1) { residual = VP8LSubPixels(current_row[x], predict); @@ -256,6 +260,11 @@ static WEBP_INLINE void GetResidual( current_row[x] = VP8LAddPixels(predict, residual); // x is never 0 here so we do not need to update upper_row like below. } +#else + (void)max_quantization; + (void)used_subtract_green; + residual = VP8LSubPixels(current_row[x], predict); +#endif if ((current_row[x] & kMaskAlpha) == 0) { // If alpha is 0, cleanup RGB. We can choose the RGB values of the // residual for best compression. The prediction of alpha itself can be @@ -298,11 +307,12 @@ static int GetBestPredictorForTile(int width, int height, const int max_x = GetMin(tile_size, width - start_x); // Whether there exist columns just outside the tile. const int have_left = (start_x > 0); - const int have_right = (max_x < width - start_x); // Position and size of the strip covering the tile and adjacent columns if // they exist. const int context_start_x = start_x - have_left; - const int context_width = max_x + have_left + have_right; +#if (WEBP_NEAR_LOSSLESS == 1) + const int context_width = max_x + have_left + (max_x < width - start_x); +#endif const int tiles_per_row = VP8LSubSampleSize(width, bits); // Prediction modes of the left and above neighbor tiles. const int left_mode = (tile_x > 0) ? @@ -314,7 +324,9 @@ static int GetBestPredictorForTile(int width, int height, // when at the right edge. uint32_t* upper_row = argb_scratch; uint32_t* current_row = upper_row + width + 1; +#if (WEBP_NEAR_LOSSLESS == 1) uint8_t* const max_diffs = (uint8_t*)(current_row + width + 1); +#endif float best_diff = MAX_DIFF_COST; int best_mode = 0; int mode; @@ -354,10 +366,12 @@ static int GetBestPredictorForTile(int width, int height, memcpy(current_row + context_start_x, argb + y * width + context_start_x, sizeof(*argb) * (max_x + have_left + (y + 1 < height))); +#if (WEBP_NEAR_LOSSLESS == 1) if (max_quantization > 1 && y >= 1 && y + 1 < height) { MaxDiffsForRow(context_width, width, argb + y * width + context_start_x, max_diffs + context_start_x, used_subtract_green); } +#endif GetResidual(width, height, upper_row, current_row, max_diffs, mode, start_x, start_x + max_x, y, max_quantization, exact, @@ -406,8 +420,10 @@ static void CopyImageWithPrediction(int width, int height, // when at the right edge. uint32_t* upper_row = argb_scratch; uint32_t* current_row = upper_row + width + 1; +#if (WEBP_NEAR_LOSSLESS == 1) uint8_t* current_max_diffs = (uint8_t*)(current_row + width + 1); uint8_t* lower_max_diffs = current_max_diffs + width; +#endif int y; for (y = 0; y < height; ++y) { @@ -422,6 +438,7 @@ static void CopyImageWithPrediction(int width, int height, PredictBatch(kPredLowEffort, 0, y, width, current_row, upper_row, argb + y * width); } else { +#if (WEBP_NEAR_LOSSLESS == 1) if (max_quantization > 1) { // Compute max_diffs for the lower row now, because that needs the // contents of argb for the current row, which we will overwrite with @@ -434,6 +451,7 @@ static void CopyImageWithPrediction(int width, int height, used_subtract_green); } } +#endif for (x = 0; x < width;) { const int mode = (modes[(y >> bits) * tiles_per_row + (x >> bits)] >> 8) & 0xff; diff --git a/src/enc/vp8l_enc.c b/src/enc/vp8l_enc.c index edc0fc33..2e34b92f 100644 --- a/src/enc/vp8l_enc.c +++ b/src/enc/vp8l_enc.c @@ -1567,10 +1567,14 @@ static int EncodeStreamHook(void* input, void* data2) { WebPEncodingError err = VP8_ENC_OK; const int quality = (int)config->quality; const int low_effort = (config->method == 0); +#if (WEBP_NEAR_LOSSLESS == 1) || defined(WEBP_EXPERIMENTAL_FEATURES) const int width = picture->width; +#endif const int height = picture->height; const size_t byte_position = VP8LBitWriterNumBytes(bw); +#if (WEBP_NEAR_LOSSLESS == 1) int use_near_lossless = 0; +#endif int hdr_size = 0; int data_size = 0; int use_delta_palette = 0; @@ -1602,6 +1606,7 @@ static int EncodeStreamHook(void* input, void* data2) { VP8LBackwardRefsClear(&enc->refs_[0]); VP8LBackwardRefsClear(&enc->refs_[1]); +#if (WEBP_NEAR_LOSSLESS == 1) // Apply near-lossless preprocessing. use_near_lossless = (config->near_lossless < 100) && !enc->use_palette_ && !enc->use_predict_; @@ -1617,6 +1622,9 @@ static int EncodeStreamHook(void* input, void* data2) { } else { enc->argb_content_ = kEncoderNone; } +#else + enc->argb_content_ = kEncoderNone; +#endif #ifdef WEBP_EXPERIMENTAL_FEATURES if (config->use_delta_palette) { diff --git a/src/enc/vp8li_enc.h b/src/enc/vp8li_enc.h index 6368985d..6ebdb51f 100644 --- a/src/enc/vp8li_enc.h +++ b/src/enc/vp8li_enc.h @@ -14,6 +14,15 @@ #ifndef WEBP_ENC_VP8LI_H_ #define WEBP_ENC_VP8LI_H_ +#ifdef HAVE_CONFIG_H +#include "../webp/config.h" +#endif +// Either WEBP_NEAR_LOSSLESS is defined as 0 in config.h when compiling to +// disable near-lossless, or it is enabled by default. +#ifndef WEBP_NEAR_LOSSLESS +#define WEBP_NEAR_LOSSLESS 1 +#endif + #include "./backward_references_enc.h" #include "./histogram_enc.h" #include "../utils/bit_writer_utils.h" @@ -82,10 +91,12 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, const WebPPicture* const picture, VP8LBitWriter* const bw, int use_cache); +#if (WEBP_NEAR_LOSSLESS == 1) // in near_lossless.c // Near lossless preprocessing in RGB color-space. int VP8ApplyNearLossless(const WebPPicture* const picture, int quality, uint32_t* const argb_dst); +#endif //------------------------------------------------------------------------------ // Image transforms in predictor.c.