rtexif: Fix conversion from RATIONAL to int, double or string
RATIONAL tags are defined as a ratio of two LONG, themselves defined as 32-bit unsigned integers. The value is misinterpreted when converting to an int, double or string, as the numerator and the denominator are interpreted as signed values. The problem has been noticed with the ExposureTime tag generated by libtiff, which sets the denominator to 0xffffffff for exposure times lower than 1. Fix it. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
@@ -1510,8 +1510,6 @@ int Tag::toInt (int ofs, TagType astype) const
|
||||
return attrib->interpreter->toInt (this, ofs, astype);
|
||||
}
|
||||
|
||||
int a;
|
||||
|
||||
if (astype == INVALID) {
|
||||
astype = type;
|
||||
}
|
||||
@@ -1537,10 +1535,15 @@ int Tag::toInt (int ofs, TagType astype) const
|
||||
case LONG:
|
||||
return (int)sget4 (value + ofs, getOrder());
|
||||
|
||||
case SRATIONAL:
|
||||
case RATIONAL:
|
||||
a = (int)sget4 (value + ofs + 4, getOrder());
|
||||
case SRATIONAL: {
|
||||
int a = (int)sget4 (value + ofs + 4, getOrder());
|
||||
return a == 0 ? 0 : (int)sget4 (value + ofs, getOrder()) / a;
|
||||
}
|
||||
|
||||
case RATIONAL: {
|
||||
uint32_t a = (uint32_t)sget4 (value + ofs + 4, getOrder());
|
||||
return a == 0 ? 0 : (uint32_t)sget4 (value + ofs, getOrder()) / a;
|
||||
}
|
||||
|
||||
case FLOAT:
|
||||
return (int)toDouble (ofs);
|
||||
@@ -1589,10 +1592,14 @@ double Tag::toDouble (int ofs) const
|
||||
return (double) ((int)sget4 (value + ofs, getOrder()));
|
||||
|
||||
case SRATIONAL:
|
||||
case RATIONAL:
|
||||
ud = (int)sget4 (value + ofs, getOrder());
|
||||
dd = (int)sget4 (value + ofs + 4, getOrder());
|
||||
return dd == 0. ? 0. : (double)ud / (double)dd;
|
||||
return dd == 0. ? 0. : ud / dd;
|
||||
|
||||
case RATIONAL:
|
||||
ud = (uint32_t)sget4 (value + ofs, getOrder());
|
||||
dd = (uint32_t)sget4 (value + ofs + 4, getOrder());
|
||||
return dd == 0. ? 0. : ud / dd;
|
||||
|
||||
case FLOAT:
|
||||
conv.i = sget4 (value + ofs, getOrder());
|
||||
@@ -1735,10 +1742,13 @@ void Tag::toString (char* buffer, int ofs) const
|
||||
break;
|
||||
|
||||
case SRATIONAL:
|
||||
case RATIONAL:
|
||||
sprintf (b, "%d/%d", (int)sget4 (value + 8 * i + ofs, getOrder()), (int)sget4 (value + 8 * i + ofs + 4, getOrder()));
|
||||
break;
|
||||
|
||||
case RATIONAL:
|
||||
sprintf (b, "%u/%u", (uint32_t)sget4 (value + 8 * i + ofs, getOrder()), (uint32_t)sget4 (value + 8 * i + ofs + 4, getOrder()));
|
||||
break;
|
||||
|
||||
case FLOAT:
|
||||
sprintf (b, "%g", toDouble (8 * i + ofs));
|
||||
break;
|
||||
|
@@ -434,13 +434,18 @@ public:
|
||||
case LONG:
|
||||
return (double) ((int)sget4 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
case SRATIONAL:
|
||||
case RATIONAL: {
|
||||
case SRATIONAL: {
|
||||
const double dividend = (int)sget4 (t->getValue() + ofs, t->getOrder());
|
||||
const double divisor = (int)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return divisor == 0. ? 0. : dividend / divisor;
|
||||
}
|
||||
|
||||
case RATIONAL: {
|
||||
const double dividend = (uint32_t)sget4 (t->getValue() + ofs, t->getOrder());
|
||||
const double divisor = (uint32_t)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return divisor == 0. ? 0. : dividend / divisor;
|
||||
}
|
||||
|
||||
case FLOAT:
|
||||
return double (sget4 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
@@ -454,8 +459,6 @@ public:
|
||||
// Get the value as an int
|
||||
virtual int toInt (const Tag* t, int ofs = 0, TagType astype = INVALID)
|
||||
{
|
||||
int a;
|
||||
|
||||
if (astype == INVALID || astype == AUTO) {
|
||||
astype = t->getType();
|
||||
}
|
||||
@@ -480,10 +483,15 @@ public:
|
||||
case LONG:
|
||||
return (int)sget4 (t->getValue() + ofs, t->getOrder());
|
||||
|
||||
case SRATIONAL:
|
||||
case RATIONAL:
|
||||
a = (int)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
case SRATIONAL: {
|
||||
int a = (int)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return a == 0 ? 0 : (int)sget4 (t->getValue() + ofs, t->getOrder()) / a;
|
||||
}
|
||||
|
||||
case RATIONAL: {
|
||||
uint32_t a = (uint32_t)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return a == 0 ? 0 : (uint32_t)sget4 (t->getValue() + ofs, t->getOrder()) / a;
|
||||
}
|
||||
|
||||
case FLOAT:
|
||||
return (int)toDouble (t, ofs);
|
||||
|
Reference in New Issue
Block a user