1999.06.17 00:07 "Controlling Rational Values", by Tom Denny

1999.06.20 21:19 "Re: Controlling Rational Values", by Niles Ritter

Does anyone know of a way to explicitly set which numerator and denominator get used when setting rational TIFF Tags?

For example, I'm setting the YRESOLUTION tag to 200 which I pass to TIFFSetField as a float. Libtiff stores the value 419430400 as the numerator and 2097152 as the denominator in the YRESOLUTION tag. This, of course, is correct; however, I was hoping I could store 200 as the numerator and 1 as the denominator.

Explicitly setting the denominator to some value sounds like a bad idea; what you really want is the "best" representation, which for anything sufficiently close to an integer gives (x,1).

The libtiff code for generating RATIONAL values from float is correct but not optimal mathematically. I had to improve on it a while back but don't have the code in-hand at the current moment, but can describe it to help you get there.

libtiff code only gives you an integer pair (p,q) such that p/q approximates the rational tag value x to order O(q). Approximation theory says you can always find a (p,q) that does the job to order O(q ^ 2); such an algorithm for integers x should just return (x,1).

To do this you create what's called a continued-fraction expansion of x, which is to say a sequence of integers n1, n2, n3,... such that nk are positive for k>1 and

    x  = n1 + 1  /  (n2 + 1 / (n3 + 1 / (n4 ....... ))))).

You can create the sequence as far you as you like by starting with x, then successively taking the greatest integer part less than or equal to x then inverting the remainder. Obviously, if the remainder hits zero (as any rational number would), stop.

For example, if you were given PI = 3.14159265... and you go for four iterations

3                            =  3 + 0.1415926...   -->  n1 = 3
1/(0.1415926..)  =  7 + 0.0625159...   -->  n2 = 7
1/(0.0625159..)  =  15  + 0.9959104...   --> n3 = 15
1/ (0.9959104..) =  1 + 0.004                  --> n4 = 1

This gives PI = 3 + 1/(7 + 1/(15 + 1/1) )  = 3 + 1/(113/16)  = 355/113

Which is the famous chinese value for PI, accurate to over six decimal places.

This algorithm is about as fast as the libtiff algorithm, and quickly converges on a very close approximation for most numbers. The worst case situation is when x = golden ratio = ( 1 + squareroot(5)) / 2, in which case n1 = n2 =.. = 1; but even that case is not too bad.

You now know more about approximation theory than you ever wanted to know...

I found a reader which incorrectly assumes the denominator is 1 and I would like to make compatible TIFF images if it's easy enough to control.

What reader program would that be? That is such hideous bug that the company needs immediate naming & public rebuke, especially if they actually charge money for such rubbish. There is a reason the tag was called rational, after all...

--Niles.