mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-20 12:28:26 +01:00
Speedup WebP lossless compression for low effort (m=0) mode with following:
- Disable Cross-Color transform. - Evaluate predictors #11 (paeth), #12 and #13 only. Change-Id: I857264c85c61c3957d4fb45ae32d261d947c8bed
This commit is contained in:
parent
9275d91c79
commit
31a9cf6417
@ -758,9 +758,12 @@ static WEBP_INLINE void UpdateHisto(int histo_argb[4][256], uint32_t argb) {
|
|||||||
|
|
||||||
static int GetBestPredictorForTile(int width, int height,
|
static int GetBestPredictorForTile(int width, int height,
|
||||||
int tile_x, int tile_y, int bits,
|
int tile_x, int tile_y, int bits,
|
||||||
|
int low_effort,
|
||||||
const int accumulated[4][256],
|
const int accumulated[4][256],
|
||||||
const uint32_t* const argb_scratch) {
|
const uint32_t* const argb_scratch) {
|
||||||
const int kNumPredModes = 14;
|
const int kNumPredModes = 14;
|
||||||
|
const int kPredModePaeth = 11;
|
||||||
|
const int start_mode = low_effort ? kPredModePaeth : 0;
|
||||||
const int col_start = tile_x << bits;
|
const int col_start = tile_x << bits;
|
||||||
const int row_start = tile_y << bits;
|
const int row_start = tile_y << bits;
|
||||||
const int tile_size = 1 << bits;
|
const int tile_size = 1 << bits;
|
||||||
@ -769,7 +772,7 @@ static int GetBestPredictorForTile(int width, int height,
|
|||||||
float best_diff = MAX_DIFF_COST;
|
float best_diff = MAX_DIFF_COST;
|
||||||
int best_mode = 0;
|
int best_mode = 0;
|
||||||
int mode;
|
int mode;
|
||||||
for (mode = 0; mode < kNumPredModes; ++mode) {
|
for (mode = start_mode; mode < kNumPredModes; ++mode) {
|
||||||
const uint32_t* current_row = argb_scratch;
|
const uint32_t* current_row = argb_scratch;
|
||||||
const VP8LPredictorFunc pred_func = VP8LPredictors[mode];
|
const VP8LPredictorFunc pred_func = VP8LPredictors[mode];
|
||||||
float cur_diff;
|
float cur_diff;
|
||||||
@ -839,7 +842,7 @@ static void CopyTileWithPrediction(int width, int height,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VP8LResidualImage(int width, int height, int bits,
|
void VP8LResidualImage(int width, int height, int bits, int low_effort,
|
||||||
uint32_t* const argb, uint32_t* const argb_scratch,
|
uint32_t* const argb, uint32_t* const argb_scratch,
|
||||||
uint32_t* const image) {
|
uint32_t* const image) {
|
||||||
const int max_tile_size = 1 << bits;
|
const int max_tile_size = 1 << bits;
|
||||||
@ -870,7 +873,7 @@ void VP8LResidualImage(int width, int height, int bits,
|
|||||||
all_x_max = width;
|
all_x_max = width;
|
||||||
}
|
}
|
||||||
pred = GetBestPredictorForTile(width, height, tile_x, tile_y, bits,
|
pred = GetBestPredictorForTile(width, height, tile_x, tile_y, bits,
|
||||||
(const int (*)[256])histo,
|
low_effort, (const int (*)[256])histo,
|
||||||
argb_scratch);
|
argb_scratch);
|
||||||
image[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8);
|
image[tile_y * tiles_per_row + tile_x] = 0xff000000u | (pred << 8);
|
||||||
CopyTileWithPrediction(width, height, tile_x, tile_y, bits, pred,
|
CopyTileWithPrediction(width, height, tile_x, tile_y, bits, pred,
|
||||||
|
@ -98,7 +98,7 @@ void VP8LColorIndexInverseTransformAlpha(
|
|||||||
const struct VP8LTransform* const transform, int y_start, int y_end,
|
const struct VP8LTransform* const transform, int y_start, int y_end,
|
||||||
const uint8_t* src, uint8_t* dst);
|
const uint8_t* src, uint8_t* dst);
|
||||||
|
|
||||||
void VP8LResidualImage(int width, int height, int bits,
|
void VP8LResidualImage(int width, int height, int bits, int low_effort,
|
||||||
uint32_t* const argb, uint32_t* const argb_scratch,
|
uint32_t* const argb, uint32_t* const argb_scratch,
|
||||||
uint32_t* const image);
|
uint32_t* const image);
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ static int AnalyzeAndInit(VP8LEncoder* const enc, WebPImageHint image_hint) {
|
|||||||
if (!enc->use_palette_) {
|
if (!enc->use_palette_) {
|
||||||
if (image_hint == WEBP_HINT_PHOTO) {
|
if (image_hint == WEBP_HINT_PHOTO) {
|
||||||
enc->use_predict_ = 1;
|
enc->use_predict_ = 1;
|
||||||
enc->use_cross_color_ = 1;
|
enc->use_cross_color_ = (method > 0);
|
||||||
} else {
|
} else {
|
||||||
double non_pred_entropy, pred_entropy;
|
double non_pred_entropy, pred_entropy;
|
||||||
if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride,
|
if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride,
|
||||||
@ -350,7 +350,7 @@ static int AnalyzeAndInit(VP8LEncoder* const enc, WebPImageHint image_hint) {
|
|||||||
}
|
}
|
||||||
if (pred_entropy < 0.95 * non_pred_entropy) {
|
if (pred_entropy < 0.95 * non_pred_entropy) {
|
||||||
enc->use_predict_ = 1;
|
enc->use_predict_ = 1;
|
||||||
enc->use_cross_color_ = 1;
|
enc->use_cross_color_ = (method > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -919,14 +919,15 @@ static void ApplySubtractGreen(VP8LEncoder* const enc, int width, int height,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc,
|
static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc,
|
||||||
int width, int height, int quality,
|
int width, int height,
|
||||||
|
int quality, int low_effort,
|
||||||
VP8LBitWriter* const bw) {
|
VP8LBitWriter* const bw) {
|
||||||
const int pred_bits = enc->transform_bits_;
|
const int pred_bits = enc->transform_bits_;
|
||||||
const int transform_width = VP8LSubSampleSize(width, pred_bits);
|
const int transform_width = VP8LSubSampleSize(width, pred_bits);
|
||||||
const int transform_height = VP8LSubSampleSize(height, pred_bits);
|
const int transform_height = VP8LSubSampleSize(height, pred_bits);
|
||||||
|
|
||||||
VP8LResidualImage(width, height, pred_bits, enc->argb_, enc->argb_scratch_,
|
VP8LResidualImage(width, height, pred_bits, low_effort, enc->argb_,
|
||||||
enc->transform_data_);
|
enc->argb_scratch_, enc->transform_data_);
|
||||||
VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
|
VP8LPutBits(bw, TRANSFORM_PRESENT, 1);
|
||||||
VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2);
|
VP8LPutBits(bw, PREDICTOR_TRANSFORM, 2);
|
||||||
assert(pred_bits >= 2);
|
assert(pred_bits >= 2);
|
||||||
@ -1207,6 +1208,7 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
|
|||||||
VP8LBitWriter* const bw) {
|
VP8LBitWriter* const bw) {
|
||||||
WebPEncodingError err = VP8_ENC_OK;
|
WebPEncodingError err = VP8_ENC_OK;
|
||||||
const int quality = (int)config->quality;
|
const int quality = (int)config->quality;
|
||||||
|
const int low_effort = (config->method == 0);
|
||||||
const int width = picture->width;
|
const int width = picture->width;
|
||||||
const int height = picture->height;
|
const int height = picture->height;
|
||||||
VP8LEncoder* const enc = VP8LEncoderNew(config, picture);
|
VP8LEncoder* const enc = VP8LEncoderNew(config, picture);
|
||||||
@ -1279,7 +1281,8 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // WEBP_EXPERIMENTAL_FEATURES
|
#endif // WEBP_EXPERIMENTAL_FEATURES
|
||||||
err = ApplyPredictFilter(enc, enc->current_width_, height, quality, bw);
|
err = ApplyPredictFilter(enc, enc->current_width_, height, quality,
|
||||||
|
low_effort, bw);
|
||||||
if (err != VP8_ENC_OK) {
|
if (err != VP8_ENC_OK) {
|
||||||
WebPSafeFree(copy_buffer);
|
WebPSafeFree(copy_buffer);
|
||||||
goto Error;
|
goto Error;
|
||||||
|
Loading…
Reference in New Issue
Block a user