From c8581b06e1d9f129351b0c3794db787ec7363ad2 Mon Sep 17 00:00:00 2001 From: Vikas Arora Date: Tue, 4 Nov 2014 08:10:31 -0800 Subject: [PATCH] Optimize BackwardReferences for RLE encoding. Updated BackwardReferencesRle method by utilizing the local color cache. Also changed the name of method BackwardReferencesHashChain to BackwardReferencesLz77 to reflect the LZ77 coding. For the 1000 image corpus, this change saves 0.2% bytes (at default settings) and is 2-5% faster to encode. Change-Id: Ic3f288253b3bbb101a69945a80994c3fd0917f8b --- src/enc/backward_references.c | 85 +++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/src/enc/backward_references.c b/src/enc/backward_references.c index e235986b..53a30352 100644 --- a/src/enc/backward_references.c +++ b/src/enc/backward_references.c @@ -313,38 +313,6 @@ static int HashChainFindCopy(const VP8LHashChain* const p, return (best_length >= MIN_LENGTH); } -static WEBP_INLINE void PushBackCopy(VP8LBackwardRefs* const refs, int length) { - while (length >= MAX_LENGTH) { - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, MAX_LENGTH)); - length -= MAX_LENGTH; - } - if (length > 0) { - BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, length)); - } -} - -static int BackwardReferencesRle(int xsize, int ysize, - const uint32_t* const argb, - VP8LBackwardRefs* const refs) { - const int pix_count = xsize * ysize; - int match_len = 0; - int i; - ClearBackwardRefs(refs); - PushBackCopy(refs, match_len); // i=0 case - BackwardRefsCursorAdd(refs, PixOrCopyCreateLiteral(argb[0])); - for (i = 1; i < pix_count; ++i) { - if (argb[i] == argb[i - 1]) { - ++match_len; - } else { - PushBackCopy(refs, match_len); - match_len = 0; - BackwardRefsCursorAdd(refs, PixOrCopyCreateLiteral(argb[i])); - } - } - PushBackCopy(refs, match_len); - return !refs->error_; -} - static void AddSingleLiteral(uint32_t pixel, int use_color_cache, VP8LColorCache* const hashers, VP8LBackwardRefs* const refs) { @@ -360,7 +328,48 @@ static void AddSingleLiteral(uint32_t pixel, int use_color_cache, BackwardRefsCursorAdd(refs, v); } -static int BackwardReferencesHashChain(int xsize, int ysize, +static WEBP_INLINE void PushBackCopy(VP8LBackwardRefs* const refs, int length) { + while (length >= MAX_LENGTH) { + BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, MAX_LENGTH)); + length -= MAX_LENGTH; + } + if (length > 0) { + BackwardRefsCursorAdd(refs, PixOrCopyCreateCopy(1, length)); + } +} + +static int BackwardReferencesRle(int xsize, int ysize, + const uint32_t* const argb, + int cache_bits, VP8LBackwardRefs* const refs) { + const int pix_count = xsize * ysize; + int match_len = 0; + int i; + int cc_init = 0; + const int use_color_cache = (cache_bits > 0); + VP8LColorCache hashers; + + if (use_color_cache) { + cc_init = VP8LColorCacheInit(&hashers, cache_bits); + if (!cc_init) return 0; + } + ClearBackwardRefs(refs); + // Add first pixel as literal. + AddSingleLiteral(argb[0], use_color_cache, &hashers, refs); + for (i = 1; i < pix_count; ++i) { + if (argb[i] == argb[i - 1]) { + ++match_len; + } else { + PushBackCopy(refs, match_len); + match_len = 0; + AddSingleLiteral(argb[i], use_color_cache, &hashers, refs); + } + } + PushBackCopy(refs, match_len); + if (cc_init) VP8LColorCacheClear(&hashers); + return !refs->error_; +} + +static int BackwardReferencesLz77(int xsize, int ysize, const uint32_t* const argb, int cache_bits, int quality, VP8LHashChain* const hash_chain, @@ -813,11 +822,11 @@ VP8LBackwardRefs* VP8LGetBackwardReferences( VP8LHistogram* const histo = VP8LAllocateHistogram(cache_bits); if (histo == NULL) return NULL; - if (!BackwardReferencesHashChain(width, height, argb, cache_bits, quality, - hash_chain, refs_lz77)) { + if (!BackwardReferencesLz77(width, height, argb, cache_bits, quality, + hash_chain, refs_lz77)) { goto Error; } - if (!BackwardReferencesRle(width, height, argb, refs_rle)) { + if (!BackwardReferencesRle(width, height, argb, cache_bits, refs_rle)) { goto Error; } @@ -943,8 +952,8 @@ int VP8LCalculateEstimateForCacheSize(const uint32_t* const argb, return 1; } - if (!BackwardReferencesHashChain(xsize, ysize, argb, 0, quality, hash_chain, - refs)) { + if (!BackwardReferencesLz77(xsize, ysize, argb, 0, quality, hash_chain, + refs)) { return 0; } // Do a binary search to find the optimal entropy for cache_bits.