android: jpeg: exif: Fix and expand setRational

setRational was not working properly for EXIF tags in the GPS IFD due to
libexif not supporting those tags in exif_entry_initialize().  Manually
specify the size of the EXIF entry to fix this. While at it, add support
for setting multiple rationals, as that is a common use case for
rational EXIF tags.

As Rational types are no longer initialized by libexif directly, the
EXIF_TAG_{X,Y}_RESOLUTION exif tags will not have their default values
populated.

This allows the GPS altitude to be set properly, and is part of the fix
to allow the following CTS test to pass:
- android.hardware.cts.CameraTest#testJpegExif

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
Paul Elder 2021-03-08 18:52:44 +09:00
parent eb5a9d822f
commit fd3faf7b60
2 changed files with 13 additions and 2 deletions

View file

@ -187,11 +187,20 @@ void Exif::setLong(ExifIfd ifd, ExifTag tag, uint32_t item)
void Exif::setRational(ExifIfd ifd, ExifTag tag, ExifRational item)
{
ExifEntry *entry = createEntry(ifd, tag);
setRational(ifd, tag, { &item, 1 });
}
void Exif::setRational(ExifIfd ifd, ExifTag tag, Span<const ExifRational> items)
{
ExifEntry *entry = createEntry(ifd, tag, EXIF_FORMAT_RATIONAL,
items.size(),
items.size() * sizeof(ExifRational));
if (!entry)
return;
exif_set_rational(entry->data, order_, item);
for (size_t i = 0; i < items.size(); i++)
exif_set_rational(entry->data + i * sizeof(ExifRational),
order_, items[i]);
exif_entry_unref(entry);
}

View file

@ -89,6 +89,8 @@ private:
const std::string &item,
StringEncoding encoding = NoEncoding);
void setRational(ExifIfd ifd, ExifTag tag, ExifRational item);
void setRational(ExifIfd ifd, ExifTag tag,
libcamera::Span<const ExifRational> items);
std::tuple<int, int, int> degreesToDMS(double decimalDegrees);
void setGPSDMS(ExifIfd ifd, ExifTag tag, int deg, int min, int sec);