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