mirror of
				https://github.com/webmproject/libwebp.git
				synced 2025-10-31 18:35:41 +01:00 
			
		
		
		
	split StoreHuffmanCode() into smaller functions
Change-Id: Iaa715f4997505eebabee1e92e964a5d7ee6f3e7d
This commit is contained in:
		
				
					committed by
					
						 James Zern
						James Zern
					
				
			
			
				
	
			
			
			
						parent
						
							d0d88990d8
						
					
				
				
					commit
					e8d3d6a018
				
			
							
								
								
									
										168
									
								
								src/enc/vp8l.c
									
									
									
									
									
								
							
							
						
						
									
										168
									
								
								src/enc/vp8l.c
									
									
									
									
									
								
							| @@ -432,9 +432,11 @@ static void ClearHuffmanTreeIfOnlyOneSymbol(const int num_symbols, | |||||||
|   int k; |   int k; | ||||||
|   int count = 0; |   int count = 0; | ||||||
|   for (k = 0; k < num_symbols; ++k) { |   for (k = 0; k < num_symbols; ++k) { | ||||||
|     if (lengths[k] != 0) ++count; |     if (lengths[k] != 0) { | ||||||
|  |       ++count; | ||||||
|       if (count > 1) return; |       if (count > 1) return; | ||||||
|     } |     } | ||||||
|  |   } | ||||||
|   for (k = 0; k < num_symbols; ++k) { |   for (k = 0; k < num_symbols; ++k) { | ||||||
|     lengths[k] = 0; |     lengths[k] = 0; | ||||||
|     symbols[k] = 0; |     symbols[k] = 0; | ||||||
| @@ -490,34 +492,105 @@ static void StoreHuffmanTreeToBitMask( | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static int StoreFullHuffmanCode(VP8LBitWriter* const bw, | ||||||
|  |                                 const uint8_t* const bit_lengths, | ||||||
|  |                                 int bit_lengths_size) { | ||||||
|  |   int ok = 0; | ||||||
|  |   int huffman_tree_size = 0; | ||||||
|  |   uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 }; | ||||||
|  |   uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 }; | ||||||
|  |   uint8_t* huffman_tree_extra_bits; | ||||||
|  |   uint8_t* const huffman_tree = | ||||||
|  |       (uint8_t*)malloc(bit_lengths_size * sizeof(*huffman_tree) + | ||||||
|  |                        bit_lengths_size * sizeof(*huffman_tree_extra_bits)); | ||||||
|  |  | ||||||
|  |   if (huffman_tree == NULL) return 0; | ||||||
|  |   huffman_tree_extra_bits = | ||||||
|  |       huffman_tree + bit_lengths_size * sizeof(*huffman_tree); | ||||||
|  |  | ||||||
|  |   VP8LWriteBits(bw, 1, 0); | ||||||
|  |   VP8LCreateCompressedHuffmanTree(bit_lengths, bit_lengths_size, | ||||||
|  |                                   &huffman_tree_size, huffman_tree, | ||||||
|  |                                   huffman_tree_extra_bits); | ||||||
|  |   { | ||||||
|  |     int histogram[CODE_LENGTH_CODES] = { 0 }; | ||||||
|  |     int i; | ||||||
|  |     for (i = 0; i < huffman_tree_size; ++i) { | ||||||
|  |       ++histogram[huffman_tree[i]]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!VP8LCreateHuffmanTree(histogram, CODE_LENGTH_CODES, | ||||||
|  |                                7, code_length_bitdepth)) { | ||||||
|  |       goto End; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   VP8LConvertBitDepthsToSymbols(code_length_bitdepth, CODE_LENGTH_CODES, | ||||||
|  |                                 code_length_bitdepth_symbols); | ||||||
|  |   StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth); | ||||||
|  |   ClearHuffmanTreeIfOnlyOneSymbol(CODE_LENGTH_CODES, | ||||||
|  |                                   code_length_bitdepth, | ||||||
|  |                                   code_length_bitdepth_symbols); | ||||||
|  |   { | ||||||
|  |     int trailing_zero_bits = 0; | ||||||
|  |     int trimmed_length = huffman_tree_size; | ||||||
|  |     int write_trimmed_length; | ||||||
|  |     int length; | ||||||
|  |     int i = huffman_tree_size; | ||||||
|  |     while (i-- > 0) { | ||||||
|  |       const int ix = huffman_tree[i]; | ||||||
|  |       if (ix == 0 || ix == 17 || ix == 18) { | ||||||
|  |         --trimmed_length;   // discount trailing zeros | ||||||
|  |         trailing_zero_bits += code_length_bitdepth[ix]; | ||||||
|  |         if (ix == 17) { | ||||||
|  |           trailing_zero_bits += 3; | ||||||
|  |         } else if (ix == 18) { | ||||||
|  |           trailing_zero_bits += 7; | ||||||
|  |         } | ||||||
|  |       } else { | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     write_trimmed_length = (trimmed_length > 1 && trailing_zero_bits > 12); | ||||||
|  |     length = write_trimmed_length ? trimmed_length : huffman_tree_size; | ||||||
|  |     VP8LWriteBits(bw, 1, write_trimmed_length); | ||||||
|  |     if (write_trimmed_length) { | ||||||
|  |       const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1); | ||||||
|  |       const int nbitpairs = (nbits == 0) ? 1 : (nbits + 1) / 2; | ||||||
|  |       VP8LWriteBits(bw, 3, nbitpairs - 1); | ||||||
|  |       VP8LWriteBits(bw, nbitpairs * 2, trimmed_length - 2); | ||||||
|  |     } | ||||||
|  |     StoreHuffmanTreeToBitMask(bw, huffman_tree, huffman_tree_extra_bits, | ||||||
|  |                               length, code_length_bitdepth, | ||||||
|  |                               code_length_bitdepth_symbols); | ||||||
|  |   } | ||||||
|  |   ok = 1; | ||||||
|  |  End: | ||||||
|  |   free(huffman_tree); | ||||||
|  |   return ok; | ||||||
|  | } | ||||||
|  |  | ||||||
| static int StoreHuffmanCode(VP8LBitWriter* const bw, | static int StoreHuffmanCode(VP8LBitWriter* const bw, | ||||||
|                             const uint8_t* const bit_lengths, |                             const uint8_t* const bit_lengths, | ||||||
|                             int bit_lengths_size) { |                             int bit_lengths_size) { | ||||||
|   int i; |   int i; | ||||||
|   int ok = 0; |  | ||||||
|   int count = 0; |   int count = 0; | ||||||
|   int symbols[2] = { 0, 0 }; |   int symbols[2] = { 0, 0 }; | ||||||
|   int huffman_tree_size = 0; |   const int kMaxBits = 8; | ||||||
|   uint8_t code_length_bitdepth[CODE_LENGTH_CODES]; |   const int kMaxSymbol = 1 << kMaxBits; | ||||||
|   uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES]; |  | ||||||
|   int huffman_tree_histogram[CODE_LENGTH_CODES]; |  | ||||||
|   uint8_t* huffman_tree_extra_bits; |  | ||||||
|   uint8_t* huffman_tree = (uint8_t*)malloc(bit_lengths_size * |  | ||||||
|                                            (sizeof(*huffman_tree) + |  | ||||||
|                                             sizeof(*huffman_tree_extra_bits))); |  | ||||||
|  |  | ||||||
|   if (huffman_tree == NULL) goto End; |   // Check whether it's a small tree. | ||||||
|   huffman_tree_extra_bits = |   for (i = 0; i < bit_lengths_size && count < 3; ++i) { | ||||||
|       huffman_tree + (bit_lengths_size * sizeof(*huffman_tree)); |  | ||||||
|  |  | ||||||
|   for (i = 0; i < bit_lengths_size; ++i) { |  | ||||||
|     if (bit_lengths[i] != 0) { |     if (bit_lengths[i] != 0) { | ||||||
|       if (count < 2) symbols[count] = i; |       if (count < 2) symbols[count] = i; | ||||||
|       ++count; |       ++count; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (count == 0) count = 1; |  | ||||||
|   if (count <= 2 && symbols[0] < 256 && symbols[1] < 256) { |   if (count == 0) {   // emit minimal tree for empty cases | ||||||
|  |     // bits: small tree marker: 1, count-1: 0, large 8-bit code: 0, code: 0 | ||||||
|  |     VP8LWriteBits(bw, 4, 0x01); | ||||||
|  |     return 1; | ||||||
|  |   } else if (count <= 2 && symbols[0] < kMaxSymbol && symbols[1] < kMaxSymbol) { | ||||||
|     VP8LWriteBits(bw, 1, 1);  // Small tree marker to encode 1 or 2 symbols. |     VP8LWriteBits(bw, 1, 1);  // Small tree marker to encode 1 or 2 symbols. | ||||||
|     VP8LWriteBits(bw, 1, count - 1); |     VP8LWriteBits(bw, 1, count - 1); | ||||||
|     if (symbols[0] <= 1) { |     if (symbols[0] <= 1) { | ||||||
| @@ -530,68 +603,11 @@ static int StoreHuffmanCode(VP8LBitWriter* const bw, | |||||||
|     if (count == 2) { |     if (count == 2) { | ||||||
|       VP8LWriteBits(bw, 8, symbols[1]); |       VP8LWriteBits(bw, 8, symbols[1]); | ||||||
|     } |     } | ||||||
|     ok = 1; |     return 1; | ||||||
|     goto End; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   VP8LWriteBits(bw, 1, 0); |  | ||||||
|   VP8LCreateCompressedHuffmanTree(bit_lengths, bit_lengths_size, |  | ||||||
|                                   &huffman_tree_size, huffman_tree, |  | ||||||
|                                   huffman_tree_extra_bits); |  | ||||||
|   memset(huffman_tree_histogram, 0, sizeof(huffman_tree_histogram)); |  | ||||||
|   for (i = 0; i < huffman_tree_size; ++i) { |  | ||||||
|     ++huffman_tree_histogram[huffman_tree[i]]; |  | ||||||
|   } |  | ||||||
|   memset(code_length_bitdepth, 0, sizeof(code_length_bitdepth)); |  | ||||||
|   memset(code_length_bitdepth_symbols, 0, sizeof(code_length_bitdepth_symbols)); |  | ||||||
|  |  | ||||||
|   if (!VP8LCreateHuffmanTree(huffman_tree_histogram, CODE_LENGTH_CODES, |  | ||||||
|                              7, code_length_bitdepth)) { |  | ||||||
|     goto End; |  | ||||||
|   } |  | ||||||
|   VP8LConvertBitDepthsToSymbols(code_length_bitdepth, CODE_LENGTH_CODES, |  | ||||||
|                                 code_length_bitdepth_symbols); |  | ||||||
|   StoreHuffmanTreeOfHuffmanTreeToBitMask(bw, code_length_bitdepth); |  | ||||||
|   ClearHuffmanTreeIfOnlyOneSymbol(CODE_LENGTH_CODES, |  | ||||||
|                                   code_length_bitdepth, |  | ||||||
|                                   code_length_bitdepth_symbols); |  | ||||||
|   { |  | ||||||
|     int num_trailing_zeros = 0; |  | ||||||
|     int trailing_zero_bits = 0; |  | ||||||
|     int trimmed_length; |  | ||||||
|     int write_length; |  | ||||||
|     int length; |  | ||||||
|     for (i = huffman_tree_size; i > 0; --i) { |  | ||||||
|       int ix = huffman_tree[i - 1]; |  | ||||||
|       if (ix == 0 || ix == 17 || ix == 18) { |  | ||||||
|         ++num_trailing_zeros; |  | ||||||
|         trailing_zero_bits += code_length_bitdepth[ix]; |  | ||||||
|         if (ix == 17) trailing_zero_bits += 3; |  | ||||||
|         if (ix == 18) trailing_zero_bits += 7; |  | ||||||
|   } else { |   } else { | ||||||
|         break; |     return StoreFullHuffmanCode(bw, bit_lengths, bit_lengths_size); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|     trimmed_length = huffman_tree_size - num_trailing_zeros; |  | ||||||
|     write_length = (trimmed_length > 1 && trailing_zero_bits > 12); |  | ||||||
|     length = write_length ? trimmed_length : huffman_tree_size; |  | ||||||
|     VP8LWriteBits(bw, 1, write_length); |  | ||||||
|     if (write_length) { |  | ||||||
|       const int nbits = VP8LBitsLog2Ceiling(trimmed_length - 1); |  | ||||||
|       const int nbitpairs = nbits == 0 ? 1 : (nbits + 1) / 2; |  | ||||||
|       VP8LWriteBits(bw, 3, nbitpairs - 1); |  | ||||||
|       VP8LWriteBits(bw, nbitpairs * 2, trimmed_length - 2); |  | ||||||
|     } |  | ||||||
|     StoreHuffmanTreeToBitMask(bw, huffman_tree, huffman_tree_extra_bits, |  | ||||||
|                               length, code_length_bitdepth, |  | ||||||
|                               code_length_bitdepth_symbols); |  | ||||||
|   } |  | ||||||
|   ok = 1; |  | ||||||
|  |  | ||||||
|  End: |  | ||||||
|   free(huffman_tree); |  | ||||||
|   return ok; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void StoreImageToBitMask( | static void StoreImageToBitMask( | ||||||
|     VP8LBitWriter* const bw, int width, int histo_bits, |     VP8LBitWriter* const bw, int width, int histo_bits, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user