mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 02:15:42 +01:00 
			
		
		
		
	Allow transform_bits to be different during encoding.
The spec allows it but it is currently forced to the same value for simplicity. Change-Id: I26197dbf3342f7a72115cc7f7805c154313a2afb
This commit is contained in:
		| @@ -178,8 +178,14 @@ static void PrintFullLosslessInfo(const WebPAuxStats* const stats, | |||||||
|     if (stats->lossless_features & 8) fprintf(stderr, " PALETTE"); |     if (stats->lossless_features & 8) fprintf(stderr, " PALETTE"); | ||||||
|     fprintf(stderr, "\n"); |     fprintf(stderr, "\n"); | ||||||
|   } |   } | ||||||
|   fprintf(stderr, "  * Precision Bits: histogram=%d transform=%d cache=%d\n", |   fprintf(stderr, "  * Precision Bits: histogram=%d", stats->histogram_bits); | ||||||
|           stats->histogram_bits, stats->transform_bits, stats->cache_bits); |   if (stats->lossless_features & 1) { | ||||||
|  |     fprintf(stderr, " prediction=%d", stats->transform_bits); | ||||||
|  |   } | ||||||
|  |   if (stats->lossless_features & 2) { | ||||||
|  |     fprintf(stderr, " cross-color=%d", stats->cross_color_transform_bits); | ||||||
|  |   } | ||||||
|  |   fprintf(stderr, " cache=%d\n", stats->cache_bits); | ||||||
|   if (stats->palette_size > 0) { |   if (stats->palette_size > 0) { | ||||||
|     fprintf(stderr, "  * Palette size:   %d\n", stats->palette_size); |     fprintf(stderr, "  * Palette size:   %d\n", stats->palette_size); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -276,6 +276,7 @@ static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height, | |||||||
|       stats->lossless_features = best.stats.lossless_features; |       stats->lossless_features = best.stats.lossless_features; | ||||||
|       stats->histogram_bits = best.stats.histogram_bits; |       stats->histogram_bits = best.stats.histogram_bits; | ||||||
|       stats->transform_bits = best.stats.transform_bits; |       stats->transform_bits = best.stats.transform_bits; | ||||||
|  |       stats->cross_color_transform_bits = best.stats.cross_color_transform_bits; | ||||||
|       stats->cache_bits = best.stats.cache_bits; |       stats->cache_bits = best.stats.cache_bits; | ||||||
|       stats->palette_size = best.stats.palette_size; |       stats->palette_size = best.stats.palette_size; | ||||||
|       stats->lossless_size = best.stats.lossless_size; |       stats->lossless_size = best.stats.lossless_size; | ||||||
|   | |||||||
| @@ -281,7 +281,7 @@ static int EncoderAnalyze(VP8LEncoder* const enc, | |||||||
|   const int method = config->method; |   const int method = config->method; | ||||||
|   const int low_effort = (config->method == 0); |   const int low_effort = (config->method == 0); | ||||||
|   int i; |   int i; | ||||||
|   int use_palette; |   int use_palette, transform_bits; | ||||||
|   int n_lz77s; |   int n_lz77s; | ||||||
|   // If set to 0, analyze the cache with the computed cache value. If 1, also |   // If set to 0, analyze the cache with the computed cache value. If 1, also | ||||||
|   // analyze with no-cache. |   // analyze with no-cache. | ||||||
| @@ -298,7 +298,9 @@ static int EncoderAnalyze(VP8LEncoder* const enc, | |||||||
|   // Empirical bit sizes. |   // Empirical bit sizes. | ||||||
|   enc->histo_bits_ = GetHistoBits(method, use_palette, |   enc->histo_bits_ = GetHistoBits(method, use_palette, | ||||||
|                                   pic->width, pic->height); |                                   pic->width, pic->height); | ||||||
|   enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_); |   transform_bits = GetTransformBits(method, enc->histo_bits_); | ||||||
|  |   enc->predictor_transform_bits_ = transform_bits; | ||||||
|  |   enc->cross_color_transform_bits_ = transform_bits; | ||||||
|  |  | ||||||
|   if (low_effort) { |   if (low_effort) { | ||||||
|     // AnalyzeEntropy is somewhat slow. |     // AnalyzeEntropy is somewhat slow. | ||||||
| @@ -312,8 +314,8 @@ static int EncoderAnalyze(VP8LEncoder* const enc, | |||||||
|     // Try out multiple LZ77 on images with few colors. |     // Try out multiple LZ77 on images with few colors. | ||||||
|     n_lz77s = (enc->palette_size_ > 0 && enc->palette_size_ <= 16) ? 2 : 1; |     n_lz77s = (enc->palette_size_ > 0 && enc->palette_size_ <= 16) ? 2 : 1; | ||||||
|     if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, use_palette, |     if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, use_palette, | ||||||
|                         enc->palette_size_, enc->transform_bits_, |                         enc->palette_size_, transform_bits, &min_entropy_ix, | ||||||
|                         &min_entropy_ix, red_and_blue_always_zero)) { |                         red_and_blue_always_zero)) { | ||||||
|       return 0; |       return 0; | ||||||
|     } |     } | ||||||
|     if (method == 6 && config->quality == 100) { |     if (method == 6 && config->quality == 100) { | ||||||
| @@ -1069,7 +1071,7 @@ static int ApplyPredictFilter(VP8LEncoder* const enc, int width, int height, | |||||||
|                               int quality, int low_effort, |                               int quality, int low_effort, | ||||||
|                               int used_subtract_green, VP8LBitWriter* const bw, |                               int used_subtract_green, VP8LBitWriter* const bw, | ||||||
|                               int percent_range, int* const percent) { |                               int percent_range, int* const percent) { | ||||||
|   const int pred_bits = enc->transform_bits_; |   const int pred_bits = enc->predictor_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); | ||||||
|   // we disable near-lossless quantization if palette is used. |   // we disable near-lossless quantization if palette is used. | ||||||
| @@ -1093,11 +1095,11 @@ static int ApplyPredictFilter(VP8LEncoder* const enc, int width, int height, | |||||||
|       percent); |       percent); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int ApplyCrossColorFilter(const VP8LEncoder* const enc, int width, | static int ApplyCrossColorFilter(VP8LEncoder* const enc, int width, int height, | ||||||
|                                  int height, int quality, int low_effort, |                                  int quality, int low_effort, | ||||||
|                                  VP8LBitWriter* const bw, int percent_range, |                                  VP8LBitWriter* const bw, int percent_range, | ||||||
|                                  int* const percent) { |                                  int* const percent) { | ||||||
|   const int ccolor_transform_bits = enc->transform_bits_; |   const int ccolor_transform_bits = enc->cross_color_transform_bits_; | ||||||
|   const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); |   const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits); | ||||||
|   const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits); |   const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits); | ||||||
|  |  | ||||||
| @@ -1200,10 +1202,14 @@ static int AllocateTransformBuffer(VP8LEncoder* const enc, int width, | |||||||
|       enc->use_predict_ ? (width + 1) * 2 + (width * 2 + sizeof(uint32_t) - 1) / |       enc->use_predict_ ? (width + 1) * 2 + (width * 2 + sizeof(uint32_t) - 1) / | ||||||
|                                                 sizeof(uint32_t) |                                                 sizeof(uint32_t) | ||||||
|                         : 0; |                         : 0; | ||||||
|  |   const int min_transform_bits = | ||||||
|  |       (enc->predictor_transform_bits_ < enc->cross_color_transform_bits_) | ||||||
|  |           ? enc->predictor_transform_bits_ | ||||||
|  |           : enc->cross_color_transform_bits_; | ||||||
|   const uint64_t transform_data_size = |   const uint64_t transform_data_size = | ||||||
|       (enc->use_predict_ || enc->use_cross_color_) |       (enc->use_predict_ || enc->use_cross_color_) | ||||||
|           ? (uint64_t)VP8LSubSampleSize(width, enc->transform_bits_) * |           ? (uint64_t)VP8LSubSampleSize(width, min_transform_bits) * | ||||||
|                 VP8LSubSampleSize(height, enc->transform_bits_) |                 VP8LSubSampleSize(height, min_transform_bits) | ||||||
|           : 0; |           : 0; | ||||||
|   const uint64_t max_alignment_in_words = |   const uint64_t max_alignment_in_words = | ||||||
|       (WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t); |       (WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t); | ||||||
| @@ -1628,7 +1634,8 @@ static int EncodeStreamHook(void* input, void* data2) { | |||||||
|         if (enc->use_subtract_green_) stats->lossless_features |= 4; |         if (enc->use_subtract_green_) stats->lossless_features |= 4; | ||||||
|         if (enc->use_palette_) stats->lossless_features |= 8; |         if (enc->use_palette_) stats->lossless_features |= 8; | ||||||
|         stats->histogram_bits = enc->histo_bits_; |         stats->histogram_bits = enc->histo_bits_; | ||||||
|         stats->transform_bits = enc->transform_bits_; |         stats->transform_bits = enc->predictor_transform_bits_; | ||||||
|  |         stats->cross_color_transform_bits = enc->cross_color_transform_bits_; | ||||||
|         stats->cache_bits = enc->cache_bits_; |         stats->cache_bits = enc->cache_bits_; | ||||||
|         stats->palette_size = enc->palette_size_; |         stats->palette_size = enc->palette_size_; | ||||||
|         stats->lossless_size = (int)(best_size - byte_position); |         stats->lossless_size = (int)(best_size - byte_position); | ||||||
| @@ -1738,7 +1745,10 @@ int VP8LEncodeStream(const WebPConfig* const config, | |||||||
|         } |         } | ||||||
|         // Copy the values that were computed for the main encoder. |         // Copy the values that were computed for the main encoder. | ||||||
|         enc_side->histo_bits_ = enc_main->histo_bits_; |         enc_side->histo_bits_ = enc_main->histo_bits_; | ||||||
|         enc_side->transform_bits_ = enc_main->transform_bits_; |         enc_side->predictor_transform_bits_ = | ||||||
|  |             enc_main->predictor_transform_bits_; | ||||||
|  |         enc_side->cross_color_transform_bits_ = | ||||||
|  |             enc_main->cross_color_transform_bits_; | ||||||
|         enc_side->palette_size_ = enc_main->palette_size_; |         enc_side->palette_size_ = enc_main->palette_size_; | ||||||
|         memcpy(enc_side->palette_, enc_main->palette_, |         memcpy(enc_side->palette_, enc_main->palette_, | ||||||
|                sizeof(enc_main->palette_)); |                sizeof(enc_main->palette_)); | ||||||
|   | |||||||
| @@ -59,7 +59,8 @@ typedef struct { | |||||||
|  |  | ||||||
|   // Encoding parameters derived from quality parameter. |   // Encoding parameters derived from quality parameter. | ||||||
|   int histo_bits_; |   int histo_bits_; | ||||||
|   int transform_bits_;    // <= MAX_TRANSFORM_BITS. |   int predictor_transform_bits_;    // <= MAX_TRANSFORM_BITS | ||||||
|  |   int cross_color_transform_bits_;  // <= MAX_TRANSFORM_BITS | ||||||
|   int cache_bits_;        // If equal to 0, don't use color cache. |   int cache_bits_;        // If equal to 0, don't use color cache. | ||||||
|  |  | ||||||
|   // Encoding parameters derived from image characteristics. |   // Encoding parameters derived from image characteristics. | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ | |||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #define WEBP_ENCODER_ABI_VERSION 0x020f    // MAJOR(8b) + MINOR(8b) | #define WEBP_ENCODER_ABI_VERSION 0x0210  // MAJOR(8b) + MINOR(8b) | ||||||
|  |  | ||||||
| // Note: forward declaring enumerations is not allowed in (strict) C and C++, | // Note: forward declaring enumerations is not allowed in (strict) C and C++, | ||||||
| // the types are left here for reference. | // the types are left here for reference. | ||||||
| @@ -224,14 +224,15 @@ struct WebPAuxStats { | |||||||
|   uint32_t lossless_features;  // bit0:predictor bit1:cross-color transform |   uint32_t lossless_features;  // bit0:predictor bit1:cross-color transform | ||||||
|                                // bit2:subtract-green bit3:color indexing |                                // bit2:subtract-green bit3:color indexing | ||||||
|   int histogram_bits;          // number of precision bits of histogram |   int histogram_bits;          // number of precision bits of histogram | ||||||
|   int transform_bits;          // precision bits for transform |   int transform_bits;          // precision bits for predictor transform | ||||||
|   int cache_bits;              // number of bits for color cache lookup |   int cache_bits;              // number of bits for color cache lookup | ||||||
|   int palette_size;            // number of color in palette, if used |   int palette_size;            // number of color in palette, if used | ||||||
|   int lossless_size;           // final lossless size |   int lossless_size;           // final lossless size | ||||||
|   int lossless_hdr_size;       // lossless header (transform, huffman etc) size |   int lossless_hdr_size;       // lossless header (transform, huffman etc) size | ||||||
|   int lossless_data_size;      // lossless image data size |   int lossless_data_size;      // lossless image data size | ||||||
|  |   int cross_color_transform_bits;  // precision bits for cross-color transform | ||||||
|  |  | ||||||
|   uint32_t pad[2];        // padding for later use |   uint32_t pad[1];  // padding for later use | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // Signature for output function. Should return true if writing was successful. | // Signature for output function. Should return true if writing was successful. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user