mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 10:25:46 +01:00 
			
		
		
		
	Apply the RLE heuristic to LZ77.
Change-Id: I7317eed7e017ee8981f40fcf1737f97e0e3a238c
This commit is contained in:
		| @@ -242,7 +242,8 @@ static WEBP_INLINE int MaxFindCopyLength(int len) { | |||||||
| } | } | ||||||
|  |  | ||||||
| int VP8LHashChainFill(VP8LHashChain* const p, int quality, | int VP8LHashChainFill(VP8LHashChain* const p, int quality, | ||||||
|                       const uint32_t* const argb, int xsize, int ysize) { |                       const uint32_t* const argb, int xsize, int ysize, | ||||||
|  |                       int low_effort) { | ||||||
|   const int size = xsize * ysize; |   const int size = xsize * ysize; | ||||||
|   const int iter_max = GetMaxItersForQuality(quality); |   const int iter_max = GetMaxItersForQuality(quality); | ||||||
|   const int iter_min = iter_max - quality / 10; |   const int iter_min = iter_max - quality / 10; | ||||||
| @@ -285,7 +286,23 @@ int VP8LHashChainFill(VP8LHashChain* const p, int quality, | |||||||
|     const int length_max = (max_len < 256) ? max_len : 256; |     const int length_max = (max_len < 256) ? max_len : 256; | ||||||
|     uint32_t max_base_position; |     uint32_t max_base_position; | ||||||
|  |  | ||||||
|     for (pos = chain[base_position]; pos >= min_pos; pos = chain[pos]) { |     pos = chain[base_position]; | ||||||
|  |     if (!low_effort) { | ||||||
|  |       // Heuristic: use the comparison with the above line as an initialization. | ||||||
|  |       if (base_position >= (uint32_t)xsize) { | ||||||
|  |         const int curr_length = FindMatchLength(argb_start - xsize, argb_start, | ||||||
|  |                                                 best_length, max_len); | ||||||
|  |         if (curr_length > best_length) { | ||||||
|  |           best_length = curr_length; | ||||||
|  |           best_distance = xsize; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       --iter; | ||||||
|  |       // Skip the for loop if we already have the maximum. | ||||||
|  |       if (best_length == MAX_LENGTH) pos = min_pos - 1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     for (; pos >= min_pos; pos = chain[pos]) { | ||||||
|       int curr_length; |       int curr_length; | ||||||
|       if (--iter < 0) { |       if (--iter < 0) { | ||||||
|         break; |         break; | ||||||
|   | |||||||
| @@ -130,7 +130,8 @@ struct VP8LHashChain { | |||||||
| int VP8LHashChainInit(VP8LHashChain* const p, int size); | int VP8LHashChainInit(VP8LHashChain* const p, int size); | ||||||
| // Pre-compute the best matches for argb. | // Pre-compute the best matches for argb. | ||||||
| int VP8LHashChainFill(VP8LHashChain* const p, int quality, | int VP8LHashChainFill(VP8LHashChain* const p, int quality, | ||||||
|                       const uint32_t* const argb, int xsize, int ysize); |                       const uint32_t* const argb, int xsize, int ysize, | ||||||
|  |                       int low_effort); | ||||||
| void VP8LHashChainClear(VP8LHashChain* const p);  // release memory | void VP8LHashChainClear(VP8LHashChain* const p);  // release memory | ||||||
|  |  | ||||||
| // ----------------------------------------------------------------------------- | // ----------------------------------------------------------------------------- | ||||||
|   | |||||||
| @@ -697,7 +697,7 @@ static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw, | |||||||
|                                               VP8LHashChain* const hash_chain, |                                               VP8LHashChain* const hash_chain, | ||||||
|                                               VP8LBackwardRefs refs_array[2], |                                               VP8LBackwardRefs refs_array[2], | ||||||
|                                               int width, int height, |                                               int width, int height, | ||||||
|                                               int quality) { |                                               int quality, int low_effort) { | ||||||
|   int i; |   int i; | ||||||
|   int max_tokens = 0; |   int max_tokens = 0; | ||||||
|   WebPEncodingError err = VP8_ENC_OK; |   WebPEncodingError err = VP8_ENC_OK; | ||||||
| @@ -715,7 +715,8 @@ static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw, | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Calculate backward references from ARGB image. |   // Calculate backward references from ARGB image. | ||||||
|   if (VP8LHashChainFill(hash_chain, quality, argb, width, height) == 0) { |   if (!VP8LHashChainFill(hash_chain, quality, argb, width, height, | ||||||
|  |                          low_effort)) { | ||||||
|     err = VP8_ENC_ERROR_OUT_OF_MEMORY; |     err = VP8_ENC_ERROR_OUT_OF_MEMORY; | ||||||
|     goto Error; |     goto Error; | ||||||
|   } |   } | ||||||
| @@ -819,7 +820,8 @@ static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw, | |||||||
|   // 'best_refs' is the reference to the best backward refs and points to one |   // 'best_refs' is the reference to the best backward refs and points to one | ||||||
|   // of refs_array[0] or refs_array[1]. |   // of refs_array[0] or refs_array[1]. | ||||||
|   // Calculate backward references from ARGB image. |   // Calculate backward references from ARGB image. | ||||||
|   if (VP8LHashChainFill(hash_chain, quality, argb, width, height) == 0) { |   if (!VP8LHashChainFill(hash_chain, quality, argb, width, height, | ||||||
|  |                          low_effort)) { | ||||||
|     err = VP8_ENC_ERROR_OUT_OF_MEMORY; |     err = VP8_ENC_ERROR_OUT_OF_MEMORY; | ||||||
|     goto Error; |     goto Error; | ||||||
|   } |   } | ||||||
| @@ -900,7 +902,7 @@ static WebPEncodingError EncodeImageInternal(VP8LBitWriter* const bw, | |||||||
|       err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array, |       err = EncodeImageNoHuffman(bw, histogram_argb, hash_chain, refs_array, | ||||||
|                                  VP8LSubSampleSize(width, histogram_bits), |                                  VP8LSubSampleSize(width, histogram_bits), | ||||||
|                                  VP8LSubSampleSize(height, histogram_bits), |                                  VP8LSubSampleSize(height, histogram_bits), | ||||||
|                                  quality); |                                  quality, low_effort); | ||||||
|       WebPSafeFree(histogram_argb); |       WebPSafeFree(histogram_argb); | ||||||
|       if (err != VP8_ENC_OK) goto Error; |       if (err != VP8_ENC_OK) goto Error; | ||||||
|     } |     } | ||||||
| @@ -991,12 +993,12 @@ static WebPEncodingError ApplyPredictFilter(const VP8LEncoder* const enc, | |||||||
|                               (VP8LHashChain*)&enc->hash_chain_, |                               (VP8LHashChain*)&enc->hash_chain_, | ||||||
|                               (VP8LBackwardRefs*)enc->refs_,  // cast const away |                               (VP8LBackwardRefs*)enc->refs_,  // cast const away | ||||||
|                               transform_width, transform_height, |                               transform_width, transform_height, | ||||||
|                               quality); |                               quality, low_effort); | ||||||
| } | } | ||||||
|  |  | ||||||
| static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc, | static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc, | ||||||
|                                                int width, int height, |                                                int width, int height, | ||||||
|                                                int quality, |                                                int quality, int low_effort, | ||||||
|                                                VP8LBitWriter* const bw) { |                                                VP8LBitWriter* const bw) { | ||||||
|   const int ccolor_transform_bits = enc->transform_bits_; |   const int ccolor_transform_bits = enc->transform_bits_; | ||||||
|   const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); |   const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); | ||||||
| @@ -1012,7 +1014,7 @@ static WebPEncodingError ApplyCrossColorFilter(const VP8LEncoder* const enc, | |||||||
|                               (VP8LHashChain*)&enc->hash_chain_, |                               (VP8LHashChain*)&enc->hash_chain_, | ||||||
|                               (VP8LBackwardRefs*)enc->refs_,  // cast const away |                               (VP8LBackwardRefs*)enc->refs_,  // cast const away | ||||||
|                               transform_width, transform_height, |                               transform_width, transform_height, | ||||||
|                               quality); |                               quality, low_effort); | ||||||
| } | } | ||||||
|  |  | ||||||
| // ----------------------------------------------------------------------------- | // ----------------------------------------------------------------------------- | ||||||
| @@ -1291,7 +1293,7 @@ static WebPEncodingError MapImageFromPalette(VP8LEncoder* const enc, | |||||||
| } | } | ||||||
|  |  | ||||||
| // Save palette_[] to bitstream. | // Save palette_[] to bitstream. | ||||||
| static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, | static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, int low_effort, | ||||||
|                                        VP8LEncoder* const enc) { |                                        VP8LEncoder* const enc) { | ||||||
|   int i; |   int i; | ||||||
|   uint32_t tmp_palette[MAX_PALETTE_SIZE]; |   uint32_t tmp_palette[MAX_PALETTE_SIZE]; | ||||||
| @@ -1306,13 +1308,14 @@ static WebPEncodingError EncodePalette(VP8LBitWriter* const bw, | |||||||
|   } |   } | ||||||
|   tmp_palette[0] = palette[0]; |   tmp_palette[0] = palette[0]; | ||||||
|   return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, enc->refs_, |   return EncodeImageNoHuffman(bw, tmp_palette, &enc->hash_chain_, enc->refs_, | ||||||
|                               palette_size, 1, 20 /* quality */); |                               palette_size, 1, 20 /* quality */, low_effort); | ||||||
| } | } | ||||||
|  |  | ||||||
| #ifdef WEBP_EXPERIMENTAL_FEATURES | #ifdef WEBP_EXPERIMENTAL_FEATURES | ||||||
|  |  | ||||||
| static WebPEncodingError EncodeDeltaPalettePredictorImage( | static WebPEncodingError EncodeDeltaPalettePredictorImage( | ||||||
|     VP8LBitWriter* const bw, VP8LEncoder* const enc, int quality) { |     VP8LBitWriter* const bw, VP8LEncoder* const enc, int quality, | ||||||
|  |     int low_effort) { | ||||||
|   const WebPPicture* const pic = enc->pic_; |   const WebPPicture* const pic = enc->pic_; | ||||||
|   const int width = pic->width; |   const int width = pic->width; | ||||||
|   const int height = pic->height; |   const int height = pic->height; | ||||||
| @@ -1343,7 +1346,7 @@ static WebPEncodingError EncodeDeltaPalettePredictorImage( | |||||||
|   err = EncodeImageNoHuffman(bw, predictors, &enc->hash_chain_, |   err = EncodeImageNoHuffman(bw, predictors, &enc->hash_chain_, | ||||||
|                              (VP8LBackwardRefs*)enc->refs_,  // cast const away |                              (VP8LBackwardRefs*)enc->refs_,  // cast const away | ||||||
|                              transform_width, transform_height, |                              transform_width, transform_height, | ||||||
|                              quality); |                              quality, low_effort); | ||||||
|   WebPSafeFree(predictors); |   WebPSafeFree(predictors); | ||||||
|   return err; |   return err; | ||||||
| } | } | ||||||
| @@ -1433,7 +1436,7 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, | |||||||
|     if (enc->use_palette_) { |     if (enc->use_palette_) { | ||||||
|       err = AllocateTransformBuffer(enc, width, height); |       err = AllocateTransformBuffer(enc, width, height); | ||||||
|       if (err != VP8_ENC_OK) goto Error; |       if (err != VP8_ENC_OK) goto Error; | ||||||
|       err = EncodeDeltaPalettePredictorImage(bw, enc, quality); |       err = EncodeDeltaPalettePredictorImage(bw, enc, quality, low_effort); | ||||||
|       if (err != VP8_ENC_OK) goto Error; |       if (err != VP8_ENC_OK) goto Error; | ||||||
|       use_delta_palettization = 1; |       use_delta_palettization = 1; | ||||||
|     } |     } | ||||||
| @@ -1442,7 +1445,7 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, | |||||||
|  |  | ||||||
|   // Encode palette |   // Encode palette | ||||||
|   if (enc->use_palette_) { |   if (enc->use_palette_) { | ||||||
|     err = EncodePalette(bw, enc); |     err = EncodePalette(bw, low_effort, enc); | ||||||
|     if (err != VP8_ENC_OK) goto Error; |     if (err != VP8_ENC_OK) goto Error; | ||||||
|     err = MapImageFromPalette(enc, use_delta_palettization); |     err = MapImageFromPalette(enc, use_delta_palettization); | ||||||
|     if (err != VP8_ENC_OK) goto Error; |     if (err != VP8_ENC_OK) goto Error; | ||||||
| @@ -1469,7 +1472,7 @@ WebPEncodingError VP8LEncodeStream(const WebPConfig* const config, | |||||||
|  |  | ||||||
|     if (enc->use_cross_color_) { |     if (enc->use_cross_color_) { | ||||||
|       err = ApplyCrossColorFilter(enc, enc->current_width_, |       err = ApplyCrossColorFilter(enc, enc->current_width_, | ||||||
|                                   height, quality, bw); |                                   height, quality, low_effort, bw); | ||||||
|       if (err != VP8_ENC_OK) goto Error; |       if (err != VP8_ENC_OK) goto Error; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user