| 712 | } |
| 713 | |
| 714 | unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, |
| 715 | size_t numcodes, unsigned maxbitlen) |
| 716 | { |
| 717 | unsigned i, j; |
| 718 | size_t sum = 0, numpresent = 0; |
| 719 | unsigned error = 0; |
| 720 | Coin* coins; /*the coins of the currently calculated row*/ |
| 721 | Coin* prev_row; /*the previous row of coins*/ |
| 722 | unsigned numcoins; |
| 723 | unsigned coinmem; |
| 724 | |
| 725 | if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ |
| 726 | |
| 727 | for(i = 0; i < numcodes; i++) |
| 728 | { |
| 729 | if(frequencies[i] > 0) |
| 730 | { |
| 731 | numpresent++; |
| 732 | sum += frequencies[i]; |
| 733 | } |
| 734 | } |
| 735 | |
| 736 | for(i = 0; i < numcodes; i++) lengths[i] = 0; |
| 737 | |
| 738 | /*ensure at least two present symbols. There should be at least one symbol |
| 739 | according to RFC 1951 section 3.2.7. To decoders incorrectly require two. To |
| 740 | make these work as well ensure there are at least two symbols. The |
| 741 | Package-Merge code below also doesn't work correctly if there's only one |
| 742 | symbol, it'd give it the theoritical 0 bits but in practice zlib wants 1 bit*/ |
| 743 | if(numpresent == 0) |
| 744 | { |
| 745 | lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/ |
| 746 | } |
| 747 | else if(numpresent == 1) |
| 748 | { |
| 749 | for(i = 0; i < numcodes; i++) |
| 750 | { |
| 751 | if(frequencies[i]) |
| 752 | { |
| 753 | lengths[i] = 1; |
| 754 | lengths[i == 0 ? 1 : 0] = 1; |
| 755 | break; |
| 756 | } |
| 757 | } |
| 758 | } |
| 759 | else |
| 760 | { |
| 761 | /*Package-Merge algorithm represented by coin collector's problem |
| 762 | For every symbol, maxbitlen coins will be created*/ |
| 763 | |
| 764 | coinmem = numpresent * 2; /*max amount of coins needed with the current algo*/ |
| 765 | coins = (Coin*)lodepng_malloc(sizeof(Coin) * coinmem); |
| 766 | prev_row = (Coin*)lodepng_malloc(sizeof(Coin) * coinmem); |
| 767 | if(!coins || !prev_row) |
| 768 | { |
| 769 | lodepng_free(coins); |
| 770 | lodepng_free(prev_row); |
| 771 | return 83; /*alloc fail*/ |
no test coverage detected