mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 02:15:42 +01:00 
			
		
		
		
	Add VP8L prefix to backward ref & histogram methods.
Change-Id: I8c14fb219a1d7830d3244aa780c91c9964867330
This commit is contained in:
		| @@ -32,7 +32,7 @@ static const uint8_t plane_to_code_lut[128] = { | |||||||
|  |  | ||||||
| static const int kMinLength = 2; | static const int kMinLength = 2; | ||||||
|  |  | ||||||
| int DistanceToPlaneCode(int xsize, int dist) { | int VP8LDistanceToPlaneCode(int xsize, int dist) { | ||||||
|   int yoffset = dist / xsize; |   int yoffset = dist / xsize; | ||||||
|   int xoffset = dist - yoffset * xsize; |   int xoffset = dist - yoffset * xsize; | ||||||
|   if (xoffset <= 8 && yoffset < 8) { |   if (xoffset <= 8 && yoffset < 8) { | ||||||
| @@ -193,8 +193,8 @@ static WEBP_INLINE void PushBackCopy(int length, | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void BackwardReferencesRle(int xsize, int ysize, const uint32_t* argb, | void VP8LBackwardReferencesRle(int xsize, int ysize, const uint32_t* argb, | ||||||
|                            PixOrCopy* stream, int* stream_size) { |                                PixOrCopy* stream, int* stream_size) { | ||||||
|   const int pix_count = xsize * ysize; |   const int pix_count = xsize * ysize; | ||||||
|   int streak = 0; |   int streak = 0; | ||||||
|   int i; |   int i; | ||||||
| @@ -213,10 +213,10 @@ void BackwardReferencesRle(int xsize, int ysize, const uint32_t* argb, | |||||||
| } | } | ||||||
|  |  | ||||||
| // Returns 1 when successful. | // Returns 1 when successful. | ||||||
| int BackwardReferencesHashChain(int xsize, int ysize, int use_palette, | int VP8LBackwardReferencesHashChain(int xsize, int ysize, int use_palette, | ||||||
|                                 const uint32_t* argb, int palette_bits, |                                     const uint32_t* argb, int palette_bits, | ||||||
|                                 int quality, |                                     int quality, PixOrCopy* stream, | ||||||
|                                 PixOrCopy* stream, int* stream_size) { |                                     int* stream_size) { | ||||||
|   const int pix_count = xsize * ysize; |   const int pix_count = xsize * ysize; | ||||||
|   int i; |   int i; | ||||||
|   int ok = 0; |   int ok = 0; | ||||||
| @@ -320,7 +320,7 @@ static int CostModel_Build(CostModel* p, int xsize, int ysize, | |||||||
|                            const uint32_t* argb, int palette_bits) { |                            const uint32_t* argb, int palette_bits) { | ||||||
|   int ok = 0; |   int ok = 0; | ||||||
|   int stream_size; |   int stream_size; | ||||||
|   Histogram histo; |   VP8LHistogram histo; | ||||||
|   int i; |   int i; | ||||||
|   PixOrCopy* stream = (PixOrCopy*)malloc(xsize * ysize * sizeof(*stream)); |   PixOrCopy* stream = (PixOrCopy*)malloc(xsize * ysize * sizeof(*stream)); | ||||||
|   if (stream == NULL) { |   if (stream == NULL) { | ||||||
| @@ -328,34 +328,33 @@ static int CostModel_Build(CostModel* p, int xsize, int ysize, | |||||||
|   } |   } | ||||||
|   p->palette_bits_ = palette_bits; |   p->palette_bits_ = palette_bits; | ||||||
|   if (recursion_level > 0) { |   if (recursion_level > 0) { | ||||||
|     if (!BackwardReferencesTraceBackwards(xsize, ysize, recursion_level - 1, |     if (!VP8LBackwardReferencesTraceBackwards(xsize, ysize, recursion_level - 1, | ||||||
|                                           use_palette, argb, |                                               use_palette, argb, palette_bits, | ||||||
|                                           palette_bits, |                                               &stream[0], &stream_size)) { | ||||||
|                                           &stream[0], &stream_size)) { |  | ||||||
|       goto Error; |       goto Error; | ||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
|     const int quality = 100; |     const int quality = 100; | ||||||
|     if (!BackwardReferencesHashChain(xsize, ysize, use_palette, argb, |     if (!VP8LBackwardReferencesHashChain(xsize, ysize, use_palette, argb, | ||||||
|                                      palette_bits, quality, |                                          palette_bits, quality, | ||||||
|                                      &stream[0], &stream_size)) { |                                          &stream[0], &stream_size)) { | ||||||
|       goto Error; |       goto Error; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   HistogramInit(&histo, palette_bits); |   VP8LHistogramInit(&histo, palette_bits); | ||||||
|   for (i = 0; i < stream_size; ++i) { |   for (i = 0; i < stream_size; ++i) { | ||||||
|     HistogramAddSinglePixOrCopy(&histo, stream[i]); |     VP8LHistogramAddSinglePixOrCopy(&histo, stream[i]); | ||||||
|   } |   } | ||||||
|   ConvertPopulationCountTableToBitEstimates( |   VP8LConvertPopulationCountTableToBitEstimates( | ||||||
|       HistogramNumPixOrCopyCodes(&histo), |       VP8LHistogramNumCodes(&histo), | ||||||
|       &histo.literal_[0], &p->literal_[0]); |       &histo.literal_[0], &p->literal_[0]); | ||||||
|   ConvertPopulationCountTableToBitEstimates( |   VP8LConvertPopulationCountTableToBitEstimates( | ||||||
|       VALUES_IN_BYTE, &histo.red_[0], &p->red_[0]); |       VALUES_IN_BYTE, &histo.red_[0], &p->red_[0]); | ||||||
|   ConvertPopulationCountTableToBitEstimates( |   VP8LConvertPopulationCountTableToBitEstimates( | ||||||
|       VALUES_IN_BYTE, &histo.blue_[0], &p->blue_[0]); |       VALUES_IN_BYTE, &histo.blue_[0], &p->blue_[0]); | ||||||
|   ConvertPopulationCountTableToBitEstimates( |   VP8LConvertPopulationCountTableToBitEstimates( | ||||||
|       VALUES_IN_BYTE, &histo.alpha_[0], &p->alpha_[0]); |       VALUES_IN_BYTE, &histo.alpha_[0], &p->alpha_[0]); | ||||||
|   ConvertPopulationCountTableToBitEstimates( |   VP8LConvertPopulationCountTableToBitEstimates( | ||||||
|       DISTANCE_CODES_MAX, &histo.distance_[0], &p->distance_[0]); |       DISTANCE_CODES_MAX, &histo.distance_[0], &p->distance_[0]); | ||||||
|   ok = 1; |   ok = 1; | ||||||
| Error: | Error: | ||||||
| @@ -440,7 +439,7 @@ static int BackwardReferencesHashChainDistanceOnly( | |||||||
|                                &offset, &len); |                                &offset, &len); | ||||||
|       } |       } | ||||||
|       if (len >= kMinLength) { |       if (len >= kMinLength) { | ||||||
|         const int code = DistanceToPlaneCode(xsize, offset); |         const int code = VP8LDistanceToPlaneCode(xsize, offset); | ||||||
|         const double distance_cost = |         const double distance_cost = | ||||||
|             prev_cost + CostModel_DistanceCost(cost_model, code); |             prev_cost + CostModel_DistanceCost(cost_model, code); | ||||||
|         int k; |         int k; | ||||||
| @@ -601,13 +600,13 @@ Error: | |||||||
| } | } | ||||||
|  |  | ||||||
| // Returns 1 on success. | // Returns 1 on success. | ||||||
| int BackwardReferencesTraceBackwards(int xsize, int ysize, | int VP8LBackwardReferencesTraceBackwards(int xsize, int ysize, | ||||||
|                                      int recursive_cost_model, |                                          int recursive_cost_model, | ||||||
|                                      int use_palette, |                                          int use_palette, | ||||||
|                                      const uint32_t* argb, |                                          const uint32_t* argb, | ||||||
|                                      int palette_bits, |                                          int palette_bits, | ||||||
|                                      PixOrCopy* stream, |                                          PixOrCopy* stream, | ||||||
|                                      int* stream_size) { |                                          int* stream_size) { | ||||||
|   int ok = 0; |   int ok = 0; | ||||||
|   const int dist_array_size = xsize * ysize; |   const int dist_array_size = xsize * ysize; | ||||||
|   uint32_t* chosen_path = NULL; |   uint32_t* chosen_path = NULL; | ||||||
| @@ -638,21 +637,22 @@ Error: | |||||||
|   return ok; |   return ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| void BackwardReferences2DLocality(int xsize, int data_size, PixOrCopy* data) { | void VP8LBackwardReferences2DLocality(int xsize, int data_size, | ||||||
|  |                                       PixOrCopy* data) { | ||||||
|   int i; |   int i; | ||||||
|   for (i = 0; i < data_size; ++i) { |   for (i = 0; i < data_size; ++i) { | ||||||
|     if (PixOrCopyIsCopy(&data[i])) { |     if (PixOrCopyIsCopy(&data[i])) { | ||||||
|       int dist = data[i].argb_or_offset; |       int dist = data[i].argb_or_offset; | ||||||
|       int transformed_dist = DistanceToPlaneCode(xsize, dist); |       int transformed_dist = VP8LDistanceToPlaneCode(xsize, dist); | ||||||
|       data[i].argb_or_offset = transformed_dist; |       data[i].argb_or_offset = transformed_dist; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| int VerifyBackwardReferences(const uint32_t* argb, int xsize, int ysize, | int VP8LVerifyBackwardReferences(const uint32_t* argb, int xsize, int ysize, | ||||||
|                              int palette_bits, |                                  int palette_bits, | ||||||
|                              const PixOrCopy* lit, |                                  const PixOrCopy* lit, | ||||||
|                              int lit_size) { |                                  int lit_size) { | ||||||
|   int num_pixels = 0; |   int num_pixels = 0; | ||||||
|   int i; |   int i; | ||||||
|   VP8LColorCache hashers; |   VP8LColorCache hashers; | ||||||
| @@ -717,7 +717,7 @@ int VerifyBackwardReferences(const uint32_t* argb, int xsize, int ysize, | |||||||
| // Returns 1 on success. | // Returns 1 on success. | ||||||
| static int ComputePaletteHistogram(const uint32_t* argb, int xsize, int ysize, | static int ComputePaletteHistogram(const uint32_t* argb, int xsize, int ysize, | ||||||
|                                    PixOrCopy* stream, int stream_size, |                                    PixOrCopy* stream, int stream_size, | ||||||
|                                    int palette_bits, Histogram* histo) { |                                    int palette_bits, VP8LHistogram* histo) { | ||||||
|   int pixel_index = 0; |   int pixel_index = 0; | ||||||
|   int i; |   int i; | ||||||
|   uint32_t k; |   uint32_t k; | ||||||
| @@ -732,12 +732,12 @@ static int ComputePaletteHistogram(const uint32_t* argb, int xsize, int ysize, | |||||||
|           VP8LColorCacheContains(&hashers, argb[pixel_index])) { |           VP8LColorCacheContains(&hashers, argb[pixel_index])) { | ||||||
|         // push pixel as a palette pixel |         // push pixel as a palette pixel | ||||||
|         const int ix = VP8LColorCacheGetIndex(&hashers, argb[pixel_index]); |         const int ix = VP8LColorCacheGetIndex(&hashers, argb[pixel_index]); | ||||||
|         HistogramAddSinglePixOrCopy(histo, PixOrCopyCreatePaletteIx(ix)); |         VP8LHistogramAddSinglePixOrCopy(histo, PixOrCopyCreatePaletteIx(ix)); | ||||||
|       } else { |       } else { | ||||||
|         HistogramAddSinglePixOrCopy(histo, v); |         VP8LHistogramAddSinglePixOrCopy(histo, v); | ||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       HistogramAddSinglePixOrCopy(histo, v); |       VP8LHistogramAddSinglePixOrCopy(histo, v); | ||||||
|     } |     } | ||||||
|     for (k = 0; k < PixOrCopyLength(&v); ++k) { |     for (k = 0; k < PixOrCopyLength(&v); ++k) { | ||||||
|       VP8LColorCacheInsert(&hashers, argb[pixel_index]); |       VP8LColorCacheInsert(&hashers, argb[pixel_index]); | ||||||
| @@ -752,9 +752,9 @@ static int ComputePaletteHistogram(const uint32_t* argb, int xsize, int ysize, | |||||||
| } | } | ||||||
|  |  | ||||||
| // Returns how many bits are to be used for a palette. | // Returns how many bits are to be used for a palette. | ||||||
| int CalculateEstimateForPaletteSize(const uint32_t* argb, | int VP8LCalculateEstimateForPaletteSize(const uint32_t* argb, | ||||||
|                                     int xsize, int ysize, |                                         int xsize, int ysize, | ||||||
|                                     int* best_palette_bits) { |                                         int* best_palette_bits) { | ||||||
|   int ok = 0; |   int ok = 0; | ||||||
|   int palette_bits; |   int palette_bits; | ||||||
|   double lowest_entropy = 1e99; |   double lowest_entropy = 1e99; | ||||||
| @@ -763,17 +763,17 @@ int CalculateEstimateForPaletteSize(const uint32_t* argb, | |||||||
|   static const double kSmallPenaltyForLargePalette = 4.0; |   static const double kSmallPenaltyForLargePalette = 4.0; | ||||||
|   static const int quality = 30; |   static const int quality = 30; | ||||||
|   if (stream == NULL || |   if (stream == NULL || | ||||||
|       !BackwardReferencesHashChain(xsize, ysize, |       !VP8LBackwardReferencesHashChain(xsize, ysize, 0, argb, 0, quality, | ||||||
|                                    0, argb, 0, quality, stream, &stream_size)) { |                                        stream, &stream_size)) { | ||||||
|     goto Error; |     goto Error; | ||||||
|   } |   } | ||||||
|   for (palette_bits = 0; palette_bits < 12; ++palette_bits) { |   for (palette_bits = 0; palette_bits < 12; ++palette_bits) { | ||||||
|     double cur_entropy; |     double cur_entropy; | ||||||
|     Histogram histo; |     VP8LHistogram histo; | ||||||
|     HistogramInit(&histo, palette_bits); |     VP8LHistogramInit(&histo, palette_bits); | ||||||
|     ComputePaletteHistogram(argb, xsize, ysize, &stream[0], stream_size, |     ComputePaletteHistogram(argb, xsize, ysize, &stream[0], stream_size, | ||||||
|                             palette_bits, &histo); |                             palette_bits, &histo); | ||||||
|     cur_entropy = HistogramEstimateBits(&histo) + |     cur_entropy = VP8LHistogramEstimateBits(&histo) + | ||||||
|         kSmallPenaltyForLargePalette * palette_bits; |         kSmallPenaltyForLargePalette * palette_bits; | ||||||
|     if (palette_bits == 0 || cur_entropy < lowest_entropy) { |     if (palette_bits == 0 || cur_entropy < lowest_entropy) { | ||||||
|       *best_palette_bits = palette_bits; |       *best_palette_bits = palette_bits; | ||||||
|   | |||||||
| @@ -173,7 +173,7 @@ static WEBP_INLINE void PixOrCopyLengthCodeAndBits( | |||||||
|  |  | ||||||
| // Ridiculously simple backward references for images where it is unlikely | // Ridiculously simple backward references for images where it is unlikely | ||||||
| // that there are large backward references (photos). | // that there are large backward references (photos). | ||||||
| void BackwardReferencesRle( | void VP8LBackwardReferencesRle( | ||||||
|     int xsize, |     int xsize, | ||||||
|     int ysize, |     int ysize, | ||||||
|     const uint32_t *argb, |     const uint32_t *argb, | ||||||
| @@ -182,7 +182,7 @@ void BackwardReferencesRle( | |||||||
|  |  | ||||||
| // This is a simple fast function for obtaining backward references | // This is a simple fast function for obtaining backward references | ||||||
| // based on simple heuristics. Returns 1 on success. | // based on simple heuristics. Returns 1 on success. | ||||||
| int BackwardReferencesHashChain( | int VP8LBackwardReferencesHashChain( | ||||||
|     int xsize, |     int xsize, | ||||||
|     int ysize, |     int ysize, | ||||||
|     int use_palette, |     int use_palette, | ||||||
| @@ -195,7 +195,7 @@ int BackwardReferencesHashChain( | |||||||
| // This method looks for a shortest path through the backward reference | // This method looks for a shortest path through the backward reference | ||||||
| // network based on a cost model generated by a first round of compression. | // network based on a cost model generated by a first round of compression. | ||||||
| // Returns 1 on success. | // Returns 1 on success. | ||||||
| int BackwardReferencesTraceBackwards( | int VP8LBackwardReferencesTraceBackwards( | ||||||
|     int xsize, |     int xsize, | ||||||
|     int ysize, |     int ysize, | ||||||
|     int recursive_cost_model, |     int recursive_cost_model, | ||||||
| @@ -208,24 +208,24 @@ int BackwardReferencesTraceBackwards( | |||||||
| // Convert backward references that are of linear distance along | // Convert backward references that are of linear distance along | ||||||
| // the image scan lines to have a 2d locality indexing where | // the image scan lines to have a 2d locality indexing where | ||||||
| // smaller values are used for backward references that are close by. | // smaller values are used for backward references that are close by. | ||||||
| void BackwardReferences2DLocality(int xsize, int data_size, | void VP8LBackwardReferences2DLocality(int xsize, int data_size, | ||||||
|                                   PixOrCopy *data); |                                       PixOrCopy *data); | ||||||
|  |  | ||||||
| // Internals of locality transform exposed for testing use. | // Internals of locality transform exposed for testing use. | ||||||
| int DistanceToPlaneCode(int xsize, int distance); | int VP8LDistanceToPlaneCode(int xsize, int distance); | ||||||
|  |  | ||||||
| // Returns true if the given backward references actually produce | // Returns true if the given backward references actually produce | ||||||
| // the image given in tuple (argb, xsize, ysize). | // the image given in tuple (argb, xsize, ysize). | ||||||
| int VerifyBackwardReferences(const uint32_t* argb, | int VP8LVerifyBackwardReferences(const uint32_t* argb, | ||||||
|                              int xsize, int ysize, |                                  int xsize, int ysize, | ||||||
|                              int palette_bits, |                                  int palette_bits, | ||||||
|                              const PixOrCopy *lit, |                                  const PixOrCopy *lit, | ||||||
|                              int lit_size); |                                  int lit_size); | ||||||
|  |  | ||||||
| // Produce an estimate for a good emerging palette size for the image. | // Produce an estimate for a good emerging palette size for the image. | ||||||
| int CalculateEstimateForPaletteSize(const uint32_t *argb, | int VP8LCalculateEstimateForPaletteSize(const uint32_t *argb, | ||||||
|                                     int xsize, int ysize, |                                         int xsize, int ysize, | ||||||
|                                     int *best_palette_bits); |                                         int *best_palette_bits); | ||||||
|  |  | ||||||
| #if defined(__cplusplus) || defined(c_plusplus) | #if defined(__cplusplus) || defined(c_plusplus) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -116,7 +116,7 @@ static WEBP_INLINE double FastLog(int v) { | |||||||
|   return log(v); |   return log(v); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ConvertPopulationCountTableToBitEstimates( | void VP8LConvertPopulationCountTableToBitEstimates( | ||||||
|     int num_symbols, |     int num_symbols, | ||||||
|     const int* const population_counts, |     const int* const population_counts, | ||||||
|     double* const output) { |     double* const output) { | ||||||
| @@ -145,7 +145,8 @@ void ConvertPopulationCountTableToBitEstimates( | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void HistogramAddSinglePixOrCopy(Histogram* const p, const PixOrCopy v) { | void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const p, | ||||||
|  |                                      const PixOrCopy v) { | ||||||
|   if (PixOrCopyIsLiteral(&v)) { |   if (PixOrCopyIsLiteral(&v)) { | ||||||
|     ++p->alpha_[PixOrCopyLiteral(&v, 3)]; |     ++p->alpha_[PixOrCopyLiteral(&v, 3)]; | ||||||
|     ++p->red_[PixOrCopyLiteral(&v, 2)]; |     ++p->red_[PixOrCopyLiteral(&v, 2)]; | ||||||
| @@ -165,17 +166,17 @@ void HistogramAddSinglePixOrCopy(Histogram* const p, const PixOrCopy v) { | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| void HistogramBuild(Histogram* const p, | void VP8LHistogramCreate(VP8LHistogram* const p, | ||||||
|                     const PixOrCopy* const literal_and_length, |                          const PixOrCopy* const literal_and_length, | ||||||
|                     int n_literal_and_length) { |                          int n_literal_and_length) { | ||||||
|   int i; |   int i; | ||||||
|   HistogramClear(p); |   VP8LHistogramClear(p); | ||||||
|   for (i = 0; i < n_literal_and_length; ++i) { |   for (i = 0; i < n_literal_and_length; ++i) { | ||||||
|     HistogramAddSinglePixOrCopy(p, literal_and_length[i]); |     VP8LHistogramAddSinglePixOrCopy(p, literal_and_length[i]); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| double ShannonEntropy(const int* const array, int n) { | double VP8LShannonEntropy(const int* const array, int n) { | ||||||
|   int i; |   int i; | ||||||
|   double retval = 0; |   double retval = 0; | ||||||
|   int sum = 0; |   int sum = 0; | ||||||
| @@ -208,7 +209,7 @@ static double BitsEntropy(const int* const array, int n) { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   retval -= sum * FastLog(sum); |   retval -= sum * FastLog(sum); | ||||||
|   retval *= -1.4426950408889634;  // 1.0 / -FastLog(2); |   retval *= -1.4426950408889634;  // 1.0 / -Log(2); | ||||||
|   mix = 0.627; |   mix = 0.627; | ||||||
|   if (nonzeros < 5) { |   if (nonzeros < 5) { | ||||||
|     if (nonzeros <= 1) { |     if (nonzeros <= 1) { | ||||||
| @@ -240,8 +241,8 @@ static double BitsEntropy(const int* const array, int n) { | |||||||
|   return retval; |   return retval; | ||||||
| } | } | ||||||
|  |  | ||||||
| double HistogramEstimateBitsBulk(const Histogram* const p) { | double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p) { | ||||||
|   double retval = BitsEntropy(&p->literal_[0], HistogramNumPixOrCopyCodes(p)) + |   double retval = BitsEntropy(&p->literal_[0], VP8LHistogramNumCodes(p)) + | ||||||
|       BitsEntropy(&p->red_[0], 256) + |       BitsEntropy(&p->red_[0], 256) + | ||||||
|       BitsEntropy(&p->blue_[0], 256) + |       BitsEntropy(&p->blue_[0], 256) + | ||||||
|       BitsEntropy(&p->alpha_[0], 256) + |       BitsEntropy(&p->alpha_[0], 256) + | ||||||
| @@ -258,8 +259,8 @@ double HistogramEstimateBitsBulk(const Histogram* const p) { | |||||||
|   return retval; |   return retval; | ||||||
| } | } | ||||||
|  |  | ||||||
| double HistogramEstimateBits(const Histogram* const p) { | double VP8LHistogramEstimateBits(const VP8LHistogram* const p) { | ||||||
|   return HistogramEstimateBitsHeader(p) + HistogramEstimateBitsBulk(p); |   return VP8LHistogramEstimateBitsHeader(p) + VP8LHistogramEstimateBitsBulk(p); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Returns the cost encode the rle-encoded entropy code. | // Returns the cost encode the rle-encoded entropy code. | ||||||
| @@ -301,35 +302,33 @@ static double HuffmanCost(const int* const population, int length) { | |||||||
|   return retval; |   return retval; | ||||||
| } | } | ||||||
|  |  | ||||||
| double HistogramEstimateBitsHeader(const Histogram* const p) { | double VP8LHistogramEstimateBitsHeader(const VP8LHistogram* const p) { | ||||||
|   return HuffmanCost(&p->alpha_[0], 256) + |   return HuffmanCost(&p->alpha_[0], 256) + | ||||||
|       HuffmanCost(&p->red_[0], 256) + |       HuffmanCost(&p->red_[0], 256) + | ||||||
|       HuffmanCost(&p->literal_[0], HistogramNumPixOrCopyCodes(p)) + |       HuffmanCost(&p->literal_[0], VP8LHistogramNumCodes(p)) + | ||||||
|       HuffmanCost(&p->blue_[0], 256) + |       HuffmanCost(&p->blue_[0], 256) + | ||||||
|       HuffmanCost(&p->distance_[0], DISTANCE_CODES_MAX); |       HuffmanCost(&p->distance_[0], DISTANCE_CODES_MAX); | ||||||
| } | } | ||||||
|  |  | ||||||
| int BuildHistogramImage(int xsize, int ysize, | int VP8LHistogramBuildImage(int xsize, int ysize, | ||||||
|                         int histobits, |                             int histobits, int palettebits, | ||||||
|                         int palettebits, |                             const PixOrCopy* backward_refs, | ||||||
|                         const PixOrCopy* backward_refs, |                             int backward_refs_size, | ||||||
|                         int backward_refs_size, |                             VP8LHistogram*** image_arg, int* image_size) { | ||||||
|                         Histogram*** image_arg, |  | ||||||
|                         int* image_size) { |  | ||||||
|   int histo_xsize = histobits ? (xsize + (1 << histobits) - 1) >> histobits : 1; |   int histo_xsize = histobits ? (xsize + (1 << histobits) - 1) >> histobits : 1; | ||||||
|   int histo_ysize = histobits ? (ysize + (1 << histobits) - 1) >> histobits : 1; |   int histo_ysize = histobits ? (ysize + (1 << histobits) - 1) >> histobits : 1; | ||||||
|   int i; |   int i; | ||||||
|   int x = 0; |   int x = 0; | ||||||
|   int y = 0; |   int y = 0; | ||||||
|   Histogram** image; |   VP8LHistogram** image; | ||||||
|   *image_arg = NULL; |   *image_arg = NULL; | ||||||
|   *image_size = histo_xsize * histo_ysize; |   *image_size = histo_xsize * histo_ysize; | ||||||
|   image = (Histogram**)calloc(*image_size, sizeof(*image)); |   image = (VP8LHistogram**)calloc(*image_size, sizeof(*image)); | ||||||
|   if (image == NULL) { |   if (image == NULL) { | ||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
|   for (i = 0; i < *image_size; ++i) { |   for (i = 0; i < *image_size; ++i) { | ||||||
|     image[i] = (Histogram*)malloc(sizeof(*image[i])); |     image[i] = (VP8LHistogram*)malloc(sizeof(*image[i])); | ||||||
|     if (!image[i]) { |     if (!image[i]) { | ||||||
|       int k; |       int k; | ||||||
|       for (k = 0; k < *image_size; ++k) { |       for (k = 0; k < *image_size; ++k) { | ||||||
| @@ -338,14 +337,14 @@ int BuildHistogramImage(int xsize, int ysize, | |||||||
|       free(image); |       free(image); | ||||||
|       return 0; |       return 0; | ||||||
|     } |     } | ||||||
|     HistogramInit(image[i], palettebits); |     VP8LHistogramInit(image[i], palettebits); | ||||||
|   } |   } | ||||||
|   // x and y trace the position in the image. |   // x and y trace the position in the image. | ||||||
|   for (i = 0; i < backward_refs_size; ++i) { |   for (i = 0; i < backward_refs_size; ++i) { | ||||||
|     const PixOrCopy v = backward_refs[i]; |     const PixOrCopy v = backward_refs[i]; | ||||||
|     const int ix = |     const int ix = | ||||||
|         histobits ? (y >> histobits) * histo_xsize + (x >> histobits) : 0; |         histobits ? (y >> histobits) * histo_xsize + (x >> histobits) : 0; | ||||||
|     HistogramAddSinglePixOrCopy(image[ix], v); |     VP8LHistogramAddSinglePixOrCopy(image[ix], v); | ||||||
|     x += PixOrCopyLength(&v); |     x += PixOrCopyLength(&v); | ||||||
|     while (x >= xsize) { |     while (x >= xsize) { | ||||||
|       x -= xsize; |       x -= xsize; | ||||||
| @@ -356,11 +355,8 @@ int BuildHistogramImage(int xsize, int ysize, | |||||||
|   return 1; |   return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
| int CombineHistogramImage(Histogram** in, | int VP8LHistogramCombine(VP8LHistogram** in, int in_size, int quality, | ||||||
|                           int in_size, |                          VP8LHistogram*** out_arg, int* out_size) { | ||||||
|                           int quality, |  | ||||||
|                           Histogram*** out_arg, |  | ||||||
|                           int* out_size) { |  | ||||||
|   int ok = 0; |   int ok = 0; | ||||||
|   int i; |   int i; | ||||||
|   unsigned int seed = 0; |   unsigned int seed = 0; | ||||||
| @@ -368,7 +364,7 @@ int CombineHistogramImage(Histogram** in, | |||||||
|   int inner_iters = 10 + quality / 2; |   int inner_iters = 10 + quality / 2; | ||||||
|   int iter; |   int iter; | ||||||
|   double* bit_costs = (double*)malloc(in_size * sizeof(*bit_costs)); |   double* bit_costs = (double*)malloc(in_size * sizeof(*bit_costs)); | ||||||
|   Histogram** out = (Histogram**)calloc(in_size, sizeof(*out)); |   VP8LHistogram** out = (VP8LHistogram**)calloc(in_size, sizeof(*out)); | ||||||
|   *out_arg = out; |   *out_arg = out; | ||||||
|   *out_size = in_size; |   *out_size = in_size; | ||||||
|   if (bit_costs == NULL || out == NULL) { |   if (bit_costs == NULL || out == NULL) { | ||||||
| @@ -376,13 +372,13 @@ int CombineHistogramImage(Histogram** in, | |||||||
|   } |   } | ||||||
|   // Copy |   // Copy | ||||||
|   for (i = 0; i < in_size; ++i) { |   for (i = 0; i < in_size; ++i) { | ||||||
|     Histogram* new_histo = (Histogram*)malloc(sizeof(*new_histo)); |     VP8LHistogram* new_histo = (VP8LHistogram*)malloc(sizeof(*new_histo)); | ||||||
|     if (new_histo == NULL) { |     if (new_histo == NULL) { | ||||||
|       goto Error; |       goto Error; | ||||||
|     } |     } | ||||||
|     *new_histo = *(in[i]); |     *new_histo = *(in[i]); | ||||||
|     out[i] = new_histo; |     out[i] = new_histo; | ||||||
|     bit_costs[i] = HistogramEstimateBits(out[i]); |     bit_costs[i] = VP8LHistogramEstimateBits(out[i]); | ||||||
|   } |   } | ||||||
|   // Collapse similar histograms. |   // Collapse similar histograms. | ||||||
|   for (iter = 0; iter < in_size * 3 && *out_size >= 2; ++iter) { |   for (iter = 0; iter < in_size * 3 && *out_size >= 2; ++iter) { | ||||||
| @@ -394,7 +390,7 @@ int CombineHistogramImage(Histogram** in, | |||||||
|     for (k = 0; k < inner_iters; ++k) { |     for (k = 0; k < inner_iters; ++k) { | ||||||
|       // Choose two, build a combo out of them. |       // Choose two, build a combo out of them. | ||||||
|       double cost_val; |       double cost_val; | ||||||
|       Histogram* combo; |       VP8LHistogram* combo; | ||||||
|       int ix0 = rand_r(&seed) % *out_size; |       int ix0 = rand_r(&seed) % *out_size; | ||||||
|       int ix1; |       int ix1; | ||||||
|       int diff = ((k & 7) + 1) % (*out_size - 1); |       int diff = ((k & 7) + 1) % (*out_size - 1); | ||||||
| @@ -405,13 +401,14 @@ int CombineHistogramImage(Histogram** in, | |||||||
|       if (ix0 == ix1) { |       if (ix0 == ix1) { | ||||||
|         continue; |         continue; | ||||||
|       } |       } | ||||||
|       combo = (Histogram*)malloc(sizeof(*combo)); |       combo = (VP8LHistogram*)malloc(sizeof(*combo)); | ||||||
|       if (combo == NULL) { |       if (combo == NULL) { | ||||||
|         goto Error; |         goto Error; | ||||||
|       } |       } | ||||||
|       *combo = *out[ix0]; |       *combo = *out[ix0]; | ||||||
|       HistogramAdd(combo, out[ix1]); |       VP8LHistogramAdd(combo, out[ix1]); | ||||||
|       cost_val = HistogramEstimateBits(combo) - bit_costs[ix0] - bit_costs[ix1]; |       cost_val = | ||||||
|  |           VP8LHistogramEstimateBits(combo) - bit_costs[ix0] - bit_costs[ix1]; | ||||||
|       if (best_val > cost_val) { |       if (best_val > cost_val) { | ||||||
|         best_val = cost_val; |         best_val = cost_val; | ||||||
|         best_ix0 = ix0; |         best_ix0 = ix0; | ||||||
| @@ -420,7 +417,7 @@ int CombineHistogramImage(Histogram** in, | |||||||
|       free(combo); |       free(combo); | ||||||
|     } |     } | ||||||
|     if (best_val < 0.0) { |     if (best_val < 0.0) { | ||||||
|       HistogramAdd(out[best_ix0], out[best_ix1]); |       VP8LHistogramAdd(out[best_ix0], out[best_ix1]); | ||||||
|       bit_costs[best_ix0] = |       bit_costs[best_ix0] = | ||||||
|           best_val + bit_costs[best_ix0] + bit_costs[best_ix1]; |           best_val + bit_costs[best_ix0] + bit_costs[best_ix1]; | ||||||
|       // Erase (*out)[best_ix1] |       // Erase (*out)[best_ix1] | ||||||
| @@ -453,42 +450,39 @@ Error: | |||||||
|  |  | ||||||
| // What is the bit cost of moving square_histogram from | // What is the bit cost of moving square_histogram from | ||||||
| // cur_symbol to candidate_symbol. | // cur_symbol to candidate_symbol. | ||||||
| static double HistogramDistance(const Histogram* const square_histogram, | static double HistogramDistance(const VP8LHistogram* const square_histogram, | ||||||
|                                 int cur_symbol, |                                 int cur_symbol, | ||||||
|                                 int candidate_symbol, |                                 int candidate_symbol, | ||||||
|                                 Histogram** candidate_histograms) { |                                 VP8LHistogram** candidate_histograms) { | ||||||
|   double new_bit_cost; |   double new_bit_cost; | ||||||
|   double previous_bit_cost; |   double previous_bit_cost; | ||||||
|   Histogram modified; |   VP8LHistogram modified; | ||||||
|   if (cur_symbol == candidate_symbol) { |   if (cur_symbol == candidate_symbol) { | ||||||
|     return 0;  // Going nowhere. No savings. |     return 0;  // Going nowhere. No savings. | ||||||
|   } |   } | ||||||
|   previous_bit_cost = |   previous_bit_cost = | ||||||
|       HistogramEstimateBits(candidate_histograms[candidate_symbol]); |       VP8LHistogramEstimateBits(candidate_histograms[candidate_symbol]); | ||||||
|   if (cur_symbol != -1) { |   if (cur_symbol != -1) { | ||||||
|     previous_bit_cost += |     previous_bit_cost += | ||||||
|         HistogramEstimateBits(candidate_histograms[cur_symbol]); |         VP8LHistogramEstimateBits(candidate_histograms[cur_symbol]); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Compute the bit cost of the histogram where the data moves to. |   // Compute the bit cost of the histogram where the data moves to. | ||||||
|   modified = *candidate_histograms[candidate_symbol]; |   modified = *candidate_histograms[candidate_symbol]; | ||||||
|   HistogramAdd(&modified, square_histogram); |   VP8LHistogramAdd(&modified, square_histogram); | ||||||
|   new_bit_cost = HistogramEstimateBits(&modified); |   new_bit_cost = VP8LHistogramEstimateBits(&modified); | ||||||
|  |  | ||||||
|   // Compute the bit cost of the histogram where the data moves away. |   // Compute the bit cost of the histogram where the data moves away. | ||||||
|   if (cur_symbol != -1) { |   if (cur_symbol != -1) { | ||||||
|     modified = *candidate_histograms[cur_symbol]; |     modified = *candidate_histograms[cur_symbol]; | ||||||
|     HistogramRemove(&modified, square_histogram); |     VP8LHistogramRemove(&modified, square_histogram); | ||||||
|     new_bit_cost += HistogramEstimateBits(&modified); |     new_bit_cost += VP8LHistogramEstimateBits(&modified); | ||||||
|   } |   } | ||||||
|   return new_bit_cost - previous_bit_cost; |   return new_bit_cost - previous_bit_cost; | ||||||
| } | } | ||||||
|  |  | ||||||
| void RefineHistogramImage(Histogram** raw, | void VP8LHistogramRefine(VP8LHistogram** raw, int raw_size, | ||||||
|                           int raw_size, |                          uint32_t* symbols, int out_size, VP8LHistogram** out) { | ||||||
|                           uint32_t* symbols, |  | ||||||
|                           int out_size, |  | ||||||
|                           Histogram** out) { |  | ||||||
|   int i; |   int i; | ||||||
|   // Find the best 'out' histogram for each of the raw histograms |   // Find the best 'out' histogram for each of the raw histograms | ||||||
|   for (i = 0; i < raw_size; ++i) { |   for (i = 0; i < raw_size; ++i) { | ||||||
| @@ -507,9 +501,9 @@ void RefineHistogramImage(Histogram** raw, | |||||||
|  |  | ||||||
|   // Recompute each out based on raw and symbols. |   // Recompute each out based on raw and symbols. | ||||||
|   for (i = 0; i < out_size; ++i) { |   for (i = 0; i < out_size; ++i) { | ||||||
|     HistogramClear(out[i]); |     VP8LHistogramClear(out[i]); | ||||||
|   } |   } | ||||||
|   for (i = 0; i < raw_size; ++i) { |   for (i = 0; i < raw_size; ++i) { | ||||||
|     HistogramAdd(out[symbols[i]], raw[i]); |     VP8LHistogramAdd(out[symbols[i]], raw[i]); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -36,9 +36,9 @@ typedef struct { | |||||||
|   // Backward reference prefix-code histogram. |   // Backward reference prefix-code histogram. | ||||||
|   int distance_[DISTANCE_CODES_MAX]; |   int distance_[DISTANCE_CODES_MAX]; | ||||||
|   int palette_code_bits_; |   int palette_code_bits_; | ||||||
| } Histogram; | } VP8LHistogram; | ||||||
|  |  | ||||||
| static WEBP_INLINE void HistogramClear(Histogram* const p) { | static WEBP_INLINE void VP8LHistogramClear(VP8LHistogram* const p) { | ||||||
|   memset(&p->literal_[0], 0, sizeof(p->literal_)); |   memset(&p->literal_[0], 0, sizeof(p->literal_)); | ||||||
|   memset(&p->red_[0], 0, sizeof(p->red_)); |   memset(&p->red_[0], 0, sizeof(p->red_)); | ||||||
|   memset(&p->blue_[0], 0, sizeof(p->blue_)); |   memset(&p->blue_[0], 0, sizeof(p->blue_)); | ||||||
| @@ -46,36 +46,36 @@ static WEBP_INLINE void HistogramClear(Histogram* const p) { | |||||||
|   memset(&p->distance_[0], 0, sizeof(p->distance_)); |   memset(&p->distance_[0], 0, sizeof(p->distance_)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static WEBP_INLINE void HistogramInit(Histogram* const p, | static WEBP_INLINE void VP8LHistogramInit(VP8LHistogram* const p, | ||||||
|                                       int palette_code_bits) { |                                       int palette_code_bits) { | ||||||
|   p->palette_code_bits_ = palette_code_bits; |   p->palette_code_bits_ = palette_code_bits; | ||||||
|   HistogramClear(p); |   VP8LHistogramClear(p); | ||||||
| } | } | ||||||
|  |  | ||||||
| // Create the histogram. | // Create the histogram. | ||||||
| // | // | ||||||
| // The input data is the PixOrCopy data, which models the | // The input data is the PixOrCopy data, which models the | ||||||
| // literals, stop codes and backward references (both distances and lengths) | // literals, stop codes and backward references (both distances and lengths) | ||||||
| void HistogramBuild(Histogram* const p, | void VP8LHistogramCreate(VP8LHistogram* const p, | ||||||
|                     const PixOrCopy* const literal_and_length, |                          const PixOrCopy* const literal_and_length, | ||||||
|                     int n_literal_and_length); |                          int n_literal_and_length); | ||||||
|  |  | ||||||
| void HistogramAddSinglePixOrCopy(Histogram* const p, const PixOrCopy v); | void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const p, const PixOrCopy v); | ||||||
|  |  | ||||||
| // Estimate how many bits the combined entropy of literals and distance | // Estimate how many bits the combined entropy of literals and distance | ||||||
| // approximately maps to. | // approximately maps to. | ||||||
| double HistogramEstimateBits(const Histogram* const p); | double VP8LHistogramEstimateBits(const VP8LHistogram* const p); | ||||||
|  |  | ||||||
| // This function estimates the Huffman dictionary + other block overhead | // This function estimates the Huffman dictionary + other block overhead | ||||||
| // size for creating a new deflate block. | // size for creating a new deflate block. | ||||||
| double HistogramEstimateBitsHeader(const Histogram* const p); | double VP8LHistogramEstimateBitsHeader(const VP8LHistogram* const p); | ||||||
|  |  | ||||||
| // This function estimates the cost in bits excluding the bits needed to | // This function estimates the cost in bits excluding the bits needed to | ||||||
| // represent the entropy code itself. | // represent the entropy code itself. | ||||||
| double HistogramEstimateBitsBulk(const Histogram* const p); | double VP8LHistogramEstimateBitsBulk(const VP8LHistogram* const p); | ||||||
|  |  | ||||||
| static WEBP_INLINE void HistogramAdd(Histogram* const p, | static WEBP_INLINE void VP8LHistogramAdd(VP8LHistogram* const p, | ||||||
|                                      const Histogram* const a) { |                                          const VP8LHistogram* const a) { | ||||||
|   int i; |   int i; | ||||||
|   for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) { |   for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) { | ||||||
|     p->literal_[i] += a->literal_[i]; |     p->literal_[i] += a->literal_[i]; | ||||||
| @@ -90,8 +90,8 @@ static WEBP_INLINE void HistogramAdd(Histogram* const p, | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| static WEBP_INLINE void HistogramRemove(Histogram* const p, | static WEBP_INLINE void VP8LHistogramRemove(VP8LHistogram* const p, | ||||||
|                                    const Histogram* const a) { |                                             const VP8LHistogram* const a) { | ||||||
|   int i; |   int i; | ||||||
|   for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) { |   for (i = 0; i < PIX_OR_COPY_CODES_MAX; ++i) { | ||||||
|     p->literal_[i] -= a->literal_[i]; |     p->literal_[i] -= a->literal_[i]; | ||||||
| @@ -111,39 +111,38 @@ static WEBP_INLINE void HistogramRemove(Histogram* const p, | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| static WEBP_INLINE int HistogramNumPixOrCopyCodes(const Histogram* const p) { | static WEBP_INLINE int VP8LHistogramNumCodes(const VP8LHistogram* const p) { | ||||||
|   return 256 + kLengthCodes + (1 << p->palette_code_bits_); |   return 256 + kLengthCodes + (1 << p->palette_code_bits_); | ||||||
| } | } | ||||||
|  |  | ||||||
| void ConvertPopulationCountTableToBitEstimates( | void VP8LConvertPopulationCountTableToBitEstimates( | ||||||
|     int n, const int* const population_counts, double* const output); |     int n, const int* const population_counts, double* const output); | ||||||
|  |  | ||||||
| double ShannonEntropy(const int* const array, int n); | double VP8LShannonEntropy(const int* const array, int n); | ||||||
|  |  | ||||||
| // Build a 2d image of histograms, subresolutioned by (1 << histobits) to | // Build a 2d image of histograms, subresolutioned by (1 << histobits) to | ||||||
| // the original image. | // the original image. | ||||||
| int BuildHistogramImage(int xsize, int ysize, | int VP8LHistogramBuildImage(int xsize, int ysize, | ||||||
|                         int histobits, |                             int histobits, int palette_bits, | ||||||
|                         int palette_bits, |                             const PixOrCopy* backward_refs, | ||||||
|                         const PixOrCopy* backward_refs, |                             int backward_refs_size, | ||||||
|                         int backward_refs_size, |                             VP8LHistogram*** image, | ||||||
|                         Histogram*** image, |                             int* histogram_size); | ||||||
|                         int* histogram_size); |  | ||||||
|  |  | ||||||
| // Combines several histograms into fewer histograms. | // Combines several histograms into fewer histograms. | ||||||
| int CombineHistogramImage(Histogram** in, | int VP8LHistogramCombine(VP8LHistogram** in, | ||||||
|                           int in_size, |                          int in_size, | ||||||
|                           int quality, |                          int quality, | ||||||
|                           Histogram*** out, |                          VP8LHistogram*** out, | ||||||
|                           int* out_size); |                          int* out_size); | ||||||
|  |  | ||||||
| // Moves histograms from one cluster to another if smaller entropy can | // Moves histograms from one cluster to another if smaller entropy can | ||||||
| // be achieved by doing that. | // be achieved by doing that. | ||||||
| void RefineHistogramImage(Histogram** raw, | void VP8LHistogramRefine(VP8LHistogram** raw, | ||||||
|                           int raw_size, |                          int raw_size, | ||||||
|                           uint32_t* symbols, |                          uint32_t* symbols, | ||||||
|                           int out_size, |                          int out_size, | ||||||
|                           Histogram** out); |                          VP8LHistogram** out); | ||||||
|  |  | ||||||
| #if defined(__cplusplus) || defined(c_plusplus) | #if defined(__cplusplus) || defined(c_plusplus) | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user