Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/LibPNG/png.c view on Meta::CPAN
* log (about 1.2 as opposed to 0.7 absolute error in the final value). To
* use these all the shifts below must be adjusted appropriately.
*/
65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054,
57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803,
50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068,
43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782,
37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887,
31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339,
25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098,
20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132,
15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415,
10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523,
6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495,
1119, 744, 372
#endif
};
static png_int_32
png_log8bit(unsigned int x)
{
unsigned int lg2 = 0;
/* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
* because the log is actually negate that means adding 1. The final
* returned value thus has the range 0 (for 255 input) to 7.994 (for 1
* input), return -1 for the overflow (log 0) case, - so the result is
* always at most 19 bits.
*/
if ((x &= 0xff) == 0)
return -1;
if ((x & 0xf0) == 0)
lg2 = 4, x <<= 4;
if ((x & 0xc0) == 0)
lg2 += 2, x <<= 2;
if ((x & 0x80) == 0)
lg2 += 1, x <<= 1;
/* result is at most 19 bits, so this cast is safe: */
return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16));
}
/* The above gives exact (to 16 binary places) log2 values for 8-bit images,
* for 16-bit images we use the most significant 8 bits of the 16-bit value to
* get an approximation then multiply the approximation by a correction factor
* determined by the remaining up to 8 bits. This requires an additional step
* in the 16-bit case.
*
* We want log2(value/65535), we have log2(v'/255), where:
*
* value = v' * 256 + v''
* = v' * f
*
* So f is value/v', which is equal to (256+v''/v') since v' is in the range 128
* to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less
* than 258. The final factor also needs to correct for the fact that our 8-bit
* value is scaled by 255, whereas the 16-bit values must be scaled by 65535.
*
* This gives a final formula using a calculated value 'x' which is value/v' and
* scaling by 65536 to match the above table:
*
* log2(x/257) * 65536
*
* Since these numbers are so close to '1' we can use simple linear
* interpolation between the two end values 256/257 (result -368.61) and 258/257
* (result 367.179). The values used below are scaled by a further 64 to give
* 16-bit precision in the interpolation:
*
* Start (256): -23591
* Zero (257): 0
* End (258): 23499
*/
#ifdef PNG_16BIT_SUPPORTED
static png_int_32
png_log16bit(png_uint_32 x)
{
unsigned int lg2 = 0;
/* As above, but now the input has 16 bits. */
if ((x &= 0xffff) == 0)
return -1;
if ((x & 0xff00) == 0)
lg2 = 8, x <<= 8;
if ((x & 0xf000) == 0)
lg2 += 4, x <<= 4;
if ((x & 0xc000) == 0)
lg2 += 2, x <<= 2;
if ((x & 0x8000) == 0)
lg2 += 1, x <<= 1;
/* Calculate the base logarithm from the top 8 bits as a 28-bit fractional
* value.
*/
lg2 <<= 28;
lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4;
/* Now we need to interpolate the factor, this requires a division by the top
* 8 bits. Do this with maximum precision.
*/
x = ((x << 16) + (x >> 9)) / (x >> 8);
/* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24,
* the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly
* 16 bits to interpolate to get the low bits of the result. Round the
* answer. Note that the end point values are scaled by 64 to retain overall
* precision and that 'lg2' is current scaled by an extra 12 bits, so adjust
* the overall scaling by 6-12. Round at every step.
*/
x -= 1U << 24;
if (x <= 65536U) /* <= '257' */
lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12);
else
lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12);
( run in 0.767 second using v1.01-cache-2.11-cpan-d0baa829c65 )