John Bowler | 405a398 | 2011-11-28 23:57:45 -0600 | [diff] [blame] | 1 | #!/bin/sh |
| 2 | # |
| 3 | # intgamma.sh |
| 4 | # |
Glenn Randers-Pehrson | 871b1d0 | 2013-03-02 14:58:22 -0600 | [diff] [blame] | 5 | # Last changed in libpng 1.6.0 [February 14, 2013] |
John Bowler | 405a398 | 2011-11-28 23:57:45 -0600 | [diff] [blame] | 6 | # |
Glenn Randers-Pehrson | 871b1d0 | 2013-03-02 14:58:22 -0600 | [diff] [blame] | 7 | # COPYRIGHT: Written by John Cunningham Bowler, 2013. |
John Bowler | 405a398 | 2011-11-28 23:57:45 -0600 | [diff] [blame] | 8 | # To the extent possible under law, the author has waived all copyright and |
| 9 | # related or neighboring rights to this work. This work is published from: |
| 10 | # United States. |
| 11 | # |
Glenn Randers-Pehrson | 6bdefdd | 2011-11-29 07:44:48 -0600 | [diff] [blame] | 12 | # Shell script to generate png.c 8-bit and 16-bit log tables (see the code in |
| 13 | # png.c for details). |
John Bowler | 405a398 | 2011-11-28 23:57:45 -0600 | [diff] [blame] | 14 | # |
Glenn Randers-Pehrson | 6bdefdd | 2011-11-29 07:44:48 -0600 | [diff] [blame] | 15 | # This script uses the "bc" arbitrary precision calculator to calculate 32-bit |
John Bowler | 405a398 | 2011-11-28 23:57:45 -0600 | [diff] [blame] | 16 | # fixed point values of logarithms appropriate to finding the log of an 8-bit |
| 17 | # (0..255) value and a similar table for the exponent calculation. |
| 18 | # |
Glenn Randers-Pehrson | 6bdefdd | 2011-11-29 07:44:48 -0600 | [diff] [blame] | 19 | # "bc" must be on the path when the script is executed, and the math library |
| 20 | # (-lm) must be available |
John Bowler | 405a398 | 2011-11-28 23:57:45 -0600 | [diff] [blame] | 21 | # |
| 22 | # function to print out a list of numbers as integers; the function truncates |
| 23 | # the integers which must be one-per-line |
| 24 | function print(){ |
| 25 | awk 'BEGIN{ |
| 26 | str = "" |
| 27 | } |
| 28 | { |
| 29 | sub("\\.[0-9]*$", "") |
| 30 | if ($0 == "") |
| 31 | $0 = "0" |
| 32 | |
| 33 | if (str == "") |
| 34 | t = " " $0 "U" |
| 35 | else |
| 36 | t = str ", " $0 "U" |
| 37 | |
| 38 | if (length(t) >= 80) { |
| 39 | print str "," |
| 40 | str = " " $0 "U" |
| 41 | } else |
| 42 | str = t |
| 43 | } |
| 44 | END{ |
| 45 | print str |
| 46 | }' |
| 47 | } |
| 48 | # |
| 49 | # The logarithm table. |
| 50 | cat <<END |
| 51 | /* 8-bit log table: png_8bit_l2[128] |
| 52 | * This is a table of -log(value/255)/log(2) for 'value' in the range 128 to |
| 53 | * 255, so it's the base 2 logarithm of a normalized 8-bit floating point |
| 54 | * mantissa. The numbers are 32-bit fractions. |
| 55 | */ |
| 56 | static const png_uint_32 |
| 57 | png_8bit_l2[128] = |
| 58 | { |
| 59 | END |
| 60 | # |
| 61 | bc -lqws <<END | print |
| 62 | f=65536*65536/l(2) |
| 63 | for (i=128;i<256;++i) { .5 - l(i/255)*f; } |
| 64 | END |
| 65 | echo '};' |
| 66 | echo |
| 67 | # |
| 68 | # The exponent table. |
| 69 | cat <<END |
| 70 | /* The 'exp()' case must invert the above, taking a 20-bit fixed point |
| 71 | * logarithmic value and returning a 16 or 8-bit number as appropriate. In |
| 72 | * each case only the low 16 bits are relevant - the fraction - since the |
| 73 | * integer bits (the top 4) simply determine a shift. |
| 74 | * |
Glenn Randers-Pehrson | 6bdefdd | 2011-11-29 07:44:48 -0600 | [diff] [blame] | 75 | * The worst case is the 16-bit distinction between 65535 and 65534; this |
| 76 | * requires perhaps spurious accuracy in the decoding of the logarithm to |
John Bowler | 405a398 | 2011-11-28 23:57:45 -0600 | [diff] [blame] | 77 | * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance |
| 78 | * of getting this accuracy in practice. |
| 79 | * |
| 80 | * To deal with this the following exp() function works out the exponent of the |
| 81 | * frational part of the logarithm by using an accurate 32-bit value from the |
| 82 | * top four fractional bits then multiplying in the remaining bits. |
| 83 | */ |
| 84 | static const png_uint_32 |
| 85 | png_32bit_exp[16] = |
| 86 | { |
| 87 | END |
| 88 | # |
| 89 | bc -lqws <<END | print |
| 90 | f=l(2)/16 |
| 91 | for (i=0;i<16;++i) { |
| 92 | x = .5 + e(-i*f)*2^32; |
| 93 | if (x >= 2^32) x = 2^32-1; |
| 94 | x; |
| 95 | } |
| 96 | END |
| 97 | echo '};' |
| 98 | echo |
| 99 | # |
| 100 | # And the table of adjustment values. |
| 101 | cat <<END |
| 102 | /* Adjustment table; provided to explain the numbers in the code below. */ |
| 103 | #if 0 |
| 104 | END |
| 105 | bc -lqws <<END | awk '{ printf "%5d %s\n", 12-NR, $0 }' |
| 106 | for (i=11;i>=0;--i){ |
| 107 | (1 - e(-(2^i)/65536*l(2))) * 2^(32-i) |
| 108 | } |
| 109 | END |
| 110 | echo '#endif' |