mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 10:25:46 +01:00 
			
		
		
		
	lossless: Less code for the entropy selection
Tested: 1000 png corpus gives same results Change-Id: Ief5ea7727290743b9bd893b08af7aa7951f556cb
This commit is contained in:
		
				
					committed by
					
						 James Zern
						James Zern
					
				
			
			
				
	
			
			
			
						parent
						
							16ab951abf
						
					
				
				
					commit
					84326e4ab0
				
			
							
								
								
									
										105
									
								
								src/enc/vp8l.c
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								src/enc/vp8l.c
									
									
									
									
									
								
							| @@ -198,27 +198,26 @@ static void AddSinglePixSubtractGreen(VP8LHistogram* const histo, | |||||||
|   ++histo->blue_[(PixOrCopyLiteral(v, 0) - green) & 0xff]; |   ++histo->blue_[(PixOrCopyLiteral(v, 0) - green) & 0xff]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // These five modes are evaluated and their respective entropy is computed. | ||||||
|  | typedef enum { | ||||||
|  |   kDirect = 0, | ||||||
|  |   kSpatial = 1, | ||||||
|  |   kSubGreen = 2, | ||||||
|  |   kSpatialSubGreen = 3, | ||||||
|  |   kPalette = 4, | ||||||
|  |   kNumEntropyIx = 5, | ||||||
|  | } EntropyIx; | ||||||
|  |  | ||||||
| static int AnalyzeEntropy(const uint32_t* argb, | static int AnalyzeEntropy(const uint32_t* argb, | ||||||
|                           int width, int height, int argb_stride, |                           int width, int height, int argb_stride, | ||||||
|                           double* const nonpredicted_bits, |                           double entropy[kNumEntropyIx]) { | ||||||
|                           double* const predicted_bits, |  | ||||||
|                           double* const predicted_sub_green_bits, |  | ||||||
|                           double* const nonpredicted_sub_green_bits, |  | ||||||
|                           double* const palette_bits) { |  | ||||||
|   // Allocate histogram set with cache_bits = 0. |   // Allocate histogram set with cache_bits = 0. | ||||||
|   VP8LHistogramSet* const histo_set = VP8LAllocateHistogramSet(5, 0); |   VP8LHistogramSet* const histo_set = VP8LAllocateHistogramSet(5, 0); | ||||||
|   assert(nonpredicted_bits != NULL); |  | ||||||
|   assert(predicted_bits != NULL); |  | ||||||
|  |  | ||||||
|   if (histo_set != NULL) { |   if (histo_set != NULL) { | ||||||
|     int x, y; |     int i, x, y; | ||||||
|     const uint32_t* prev_row = argb; |     const uint32_t* prev_row = argb; | ||||||
|     const uint32_t* curr_row = argb + argb_stride; |     const uint32_t* curr_row = argb + argb_stride; | ||||||
|     VP8LHistogram* const histo_non_pred = histo_set->histograms[0]; |     VP8LHistogram* const * const histo = &histo_set->histograms[0]; | ||||||
|     VP8LHistogram* const histo_pred = histo_set->histograms[1]; |  | ||||||
|     VP8LHistogram* const histo_pred_subgreen = histo_set->histograms[2]; |  | ||||||
|     VP8LHistogram* const histo_subgreen = histo_set->histograms[3]; |  | ||||||
|     VP8LHistogram* const histo_palette = histo_set->histograms[4]; |  | ||||||
|     for (y = 1; y < height; ++y) { |     for (y = 1; y < height; ++y) { | ||||||
|       uint32_t prev_pix = curr_row[0]; |       uint32_t prev_pix = curr_row[0]; | ||||||
|       for (x = 1; x < width; ++x) { |       for (x = 1; x < width; ++x) { | ||||||
| @@ -229,27 +228,23 @@ static int AnalyzeEntropy(const uint32_t* argb, | |||||||
|         { |         { | ||||||
|           const PixOrCopy pix_token = PixOrCopyCreateLiteral(pix); |           const PixOrCopy pix_token = PixOrCopyCreateLiteral(pix); | ||||||
|           const PixOrCopy pix_diff_token = PixOrCopyCreateLiteral(pix_diff); |           const PixOrCopy pix_diff_token = PixOrCopyCreateLiteral(pix_diff); | ||||||
|           VP8LHistogramAddSinglePixOrCopy(histo_non_pred, &pix_token); |           VP8LHistogramAddSinglePixOrCopy(histo[kDirect], &pix_token); | ||||||
|           VP8LHistogramAddSinglePixOrCopy(histo_pred, &pix_diff_token); |           VP8LHistogramAddSinglePixOrCopy(histo[kSpatial], &pix_diff_token); | ||||||
|           AddSinglePixSubtractGreen(histo_subgreen, &pix_token); |           AddSinglePixSubtractGreen(histo[kSubGreen], &pix_token); | ||||||
|           AddSinglePixSubtractGreen(histo_pred_subgreen, &pix_diff_token); |           AddSinglePixSubtractGreen(histo[kSpatialSubGreen], &pix_diff_token); | ||||||
|         } |         } | ||||||
|         { |         { | ||||||
|           // Approximate the palette by the entropy of the multiplicative hash. |           // Approximate the palette by the entropy of the multiplicative hash. | ||||||
|           const int hash = ((pix + (pix >> 19)) * 0x39c5fba7) >> 24; |           const int hash = ((pix + (pix >> 19)) * 0x39c5fba7) >> 24; | ||||||
|           ++histo_palette->red_[hash & 0xff]; |           ++histo[kPalette]->red_[hash & 0xff]; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|       prev_row = curr_row; |       prev_row = curr_row; | ||||||
|       curr_row += argb_stride; |       curr_row += argb_stride; | ||||||
|     } |     } | ||||||
|     *nonpredicted_bits = VP8LHistogramEstimateBitsBulk(histo_non_pred); |     for (i = 0; i < kNumEntropyIx; ++i) { | ||||||
|     *predicted_bits = VP8LHistogramEstimateBitsBulk(histo_pred); |       entropy[i] = VP8LHistogramEstimateBitsBulk(histo[i]); | ||||||
|     *predicted_sub_green_bits = |     } | ||||||
|         VP8LHistogramEstimateBitsBulk(histo_pred_subgreen); |  | ||||||
|     *nonpredicted_sub_green_bits = |  | ||||||
|         VP8LHistogramEstimateBitsBulk(histo_subgreen); |  | ||||||
|     *palette_bits = VP8LHistogramEstimateBitsBulk(histo_palette); |  | ||||||
|     VP8LFreeHistogramSet(histo_set); |     VP8LFreeHistogramSet(histo_set); | ||||||
|     return 1; |     return 1; | ||||||
|   } else { |   } else { | ||||||
| @@ -286,11 +281,6 @@ static int AnalyzeAndInit(VP8LEncoder* const enc) { | |||||||
|   // we round the block size up, so we're guaranteed to have |   // we round the block size up, so we're guaranteed to have | ||||||
|   // at max MAX_REFS_BLOCK_PER_IMAGE blocks used: |   // at max MAX_REFS_BLOCK_PER_IMAGE blocks used: | ||||||
|   int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1; |   int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1; | ||||||
|   double non_pred_entropy = 0.; |  | ||||||
|   double non_pred_subtract_green_entropy = 0.; |  | ||||||
|   double pred_entropy = 0.; |  | ||||||
|   double pred_subtract_green_entropy = 0.; |  | ||||||
|   double palette_entropy = 0.; |  | ||||||
|   assert(pic != NULL && pic->argb != NULL); |   assert(pic != NULL && pic->argb != NULL); | ||||||
|  |  | ||||||
|   enc->use_cross_color_ = 0; |   enc->use_cross_color_ = 0; | ||||||
| @@ -305,49 +295,26 @@ static int AnalyzeAndInit(VP8LEncoder* const enc) { | |||||||
|     enc->use_subtract_green_ = !enc->use_palette_; |     enc->use_subtract_green_ = !enc->use_palette_; | ||||||
|     enc->use_cross_color_ = 0; |     enc->use_cross_color_ = 0; | ||||||
|   } else { |   } else { | ||||||
|  |     double entropy[kNumEntropyIx]; | ||||||
|  |     EntropyIx min_entropy_ix = kDirect; | ||||||
|  |     EntropyIx i = kDirect; | ||||||
|  |     EntropyIx last_mode_to_analyze; | ||||||
|     if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, |     if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, | ||||||
|                         &non_pred_entropy, &pred_entropy, |                         &entropy[0])) { | ||||||
|                         &pred_subtract_green_entropy, |  | ||||||
|                         &non_pred_subtract_green_entropy, |  | ||||||
|                         &palette_entropy)) { |  | ||||||
|       return 0; |       return 0; | ||||||
|     } |     } | ||||||
|     palette_entropy -= 10.;  // Small bias in favor of using the palette. |     entropy[kPalette] -= 10.;  // Small bias in favor of using the palette. | ||||||
|  |     last_mode_to_analyze = enc->use_palette_ ? kPalette : kSpatialSubGreen; | ||||||
|     if (enc->use_palette_) { |     for (i = 1; i <= last_mode_to_analyze; ++i) { | ||||||
|       // Check if avoiding the palette coding likely improves compression. |       if (entropy[min_entropy_ix] > entropy[i]) { | ||||||
|       if (palette_entropy >= non_pred_entropy || |         min_entropy_ix = i; | ||||||
|           palette_entropy >= non_pred_subtract_green_entropy || |  | ||||||
|           palette_entropy >= pred_entropy || |  | ||||||
|           palette_entropy >= pred_subtract_green_entropy) { |  | ||||||
|         enc->use_palette_ = 0; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     // TODO(jyrki): make this more clear. |  | ||||||
|     if (!enc->use_palette_) { |  | ||||||
|       // Choose the smallest of four options. |  | ||||||
|       if (non_pred_entropy < non_pred_subtract_green_entropy && |  | ||||||
|           non_pred_entropy < pred_entropy && |  | ||||||
|           non_pred_entropy < pred_subtract_green_entropy) { |  | ||||||
|         enc->use_subtract_green_ = 0; |  | ||||||
|         enc->use_predict_ = 0; |  | ||||||
|         enc->use_cross_color_ = 0; |  | ||||||
|       } else if (pred_entropy < non_pred_subtract_green_entropy && |  | ||||||
|                  pred_entropy < pred_subtract_green_entropy) { |  | ||||||
|         enc->use_subtract_green_ = 0; |  | ||||||
|         enc->use_predict_ = 1; |  | ||||||
|         enc->use_cross_color_ = 1; |  | ||||||
|       } else if (non_pred_subtract_green_entropy < |  | ||||||
|                  pred_subtract_green_entropy) { |  | ||||||
|         enc->use_subtract_green_ = 1; |  | ||||||
|         enc->use_predict_ = 0; |  | ||||||
|         enc->use_cross_color_ = 0; |  | ||||||
|       } else { |  | ||||||
|         enc->use_subtract_green_ = 1; |  | ||||||
|         enc->use_predict_ = 1; |  | ||||||
|         enc->use_cross_color_ = 1; |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |     enc->use_palette_ = (min_entropy_ix == kPalette); | ||||||
|  |     enc->use_subtract_green_ = | ||||||
|  |         (min_entropy_ix == kSubGreen) || (min_entropy_ix == kSpatialSubGreen); | ||||||
|  |     enc->use_cross_color_ = enc->use_predict_ = | ||||||
|  |         (min_entropy_ix == kSpatial) || (min_entropy_ix == kSpatialSubGreen); | ||||||
|   } |   } | ||||||
|   // Evaluate histogram bits based on the original value of use_palette flag. |   // Evaluate histogram bits based on the original value of use_palette flag. | ||||||
|   enc->histo_bits_ = GetHistoBits(method, enc->use_palette_, pic->width, |   enc->histo_bits_ = GetHistoBits(method, enc->use_palette_, pic->width, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user