[ 
https://issues.apache.org/jira/browse/IMAGING-285?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17396933#comment-17396933
 ] 

Gary Lucas commented on IMAGING-285:
------------------------------------

I think that the suggestion of using Commons Numbers really belongs in a 
separate Jira item as an "enhancement".  For now I'm going to limit my changes 
to the issue that I understand and save any undertakings of a broader scope for 
future work.

As an addendum, it turns out that there are some clear pro's and con's for 
Gilles Sadowski's position. I will start with the con.

It turns out that the Commons Numbers API shares the same problem as the 
Commons Imaging code.  The problem is that the TIFF specification for Rational 
elements calls for rational numbers based on two _*unsigned*_ 32-bit integers.  
But both Imaging's current RationalNumber class and Number's Fraction class 
both assume inputs as signed integers.  So computing the latitude using the 
parameters from the sample EXIF data in the original post, we find:

 

 
{code:java}
 int numerator   = -174884066; // 0xf5937b1e
 int denominator = 70000000;
 Fraction frac = Fraction.of(numerator, denominator);
 System.out.println("frac="+frac.doubleValue());
 // The "unsigned" approach---------
 long     n = numerator  &0xffffffffL;
 long     d = denominator&0xffffffffL;
 double lat = (double)n/(double)d;
 System.out.println("latitude = "+lat);
Results:
    frac     = -2.4983438
    latitude = 58.85833185714286
{code}
 

 

Thus we see that Numbers has its own variation of the problem.  Numbers does 
have a class called BigInteger which could be used to deal with this. But to me 
it seems a little bit over complicated for this requirement.

On the pro side of Mr. Sadowski's suggestion, it looks like the code in Numbers 
has received a lot more focused development than the code in Imaging's 
RationalNumber class. For example, looking at the code for the Imaging's 
RationalNumber class,  I spotted a shortcoming:
{code:java}
 @Override
 public float floatValue() {
    return (float) numerator / (float) divisor;
 }{code}
The shortcoming here is that an IEEE-754 standard 32-bit floating point value 
has only 24 bits of precision in its mantissa while an unsigned integer has 32. 
 So some of that low-order digits in the numerator and denominator could be 
thrown away by the cast even before the division operation is performed.  A 
better solution would be to do things the way Commons Numbers does, which would 
be basically the following:

 
{code:java}
@Override
 public float floatValue() {
     return (float) doubleValue();
 }
@Override
 public double doubleValue() {
     return (double) numerator / (double) divisor;
 }
{code}
 

 

 

> Decoding of Rational Numbers broken when large values present
> -------------------------------------------------------------
>
>                 Key: IMAGING-285
>                 URL: https://issues.apache.org/jira/browse/IMAGING-285
>             Project: Commons Imaging
>          Issue Type: Bug
>          Components: imaging.common.*
>    Affects Versions: 1.0-alpha2
>            Reporter: John Andrade
>            Priority: Major
>         Attachments: DJI_0267 cropped.JPG
>
>   Original Estimate: 1h
>  Remaining Estimate: 1h
>
> Decoding Lat/Long EXIF data from JPEGs does not work for some values.  I have 
> attached a file where the conversion fails.  I used the 
> getLatitudeAsDegreesNorth and getLongitudeAsDegreesEast methods from the 
> TiffImageMetaData.GPSInfo class.  The values are close, but seemingly off by 
> a few miles.
> I've traced the source and I believe the issue is with how the RationalNumber 
> class uses two 32-bit signed integers for the numerator and denominator.  The 
> definition of a RATIONAL data type uses 32-bit unsigned numbers.  It seems as 
> if the RationalNumber class already expects this as it has a non-public 
> static method called factoryMethod to create a RationalNumber from two 64-bit 
> numbers.
> This error is introduced in the ByteConversions class, specifically the 
> toRational method where it uses the regular RationalNumber constructor and 
> thus ensures any rational numbers that have numerator or denominator greater 
> than the max signed 32-bit value will produce invalid values.
> I am attaching a JPEG that has this problem.  I had to crop it to reduce the 
> size, but the EXIF data was preserved.
> The EXIF GPS data contained in the JPEG is:
> GpsLatitudeRef: "N"
> GpsLatitude: 38, 1, 36, 1, 4120083230, 70000000
> GpsLongitudeRef: "W"
> GpsLongitude: 90, 1, 12, 1, 2379156648, 70000000
> According to the properties of the image (right-clicking on Windows 10), the 
> L/L of the image is:
> Latitude: 38: 36: 58.85833....
> Longitude: 90: 12: 33.98795... (Windows doesn't show E/W)
> These values convert to:
> 38.616349536627
> -90.2094410978095
> When I use the getLatitudeAsDegreesNorth  and getLongitudeAsDegreesEast 
> methods, I get the following values:
> 38.59930601561111
> -90.19239757679365
>  



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to