android: jpeg: exif: Expand setString to support different encodings
GPSProcessingMethod and UserComment in EXIF tags can be in UTF-16. Expand setString to take an encoding when the field type is undefined. Update callers accordingly. Signed-off-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
parent
34897234d1
commit
d81e26d360
2 changed files with 84 additions and 4 deletions
|
@ -7,6 +7,9 @@
|
||||||
|
|
||||||
#include "exif.h"
|
#include "exif.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <uchar.h>
|
||||||
|
|
||||||
#include "libcamera/internal/log.h"
|
#include "libcamera/internal/log.h"
|
||||||
#include "libcamera/internal/utils.h"
|
#include "libcamera/internal/utils.h"
|
||||||
|
|
||||||
|
@ -178,11 +181,18 @@ void Exif::setRational(ExifIfd ifd, ExifTag tag, ExifRational item)
|
||||||
exif_entry_unref(entry);
|
exif_entry_unref(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Exif::setString(ExifIfd ifd, ExifTag tag, ExifFormat format, const std::string &item)
|
static const std::map<Exif::StringEncoding, std::array<uint8_t, 8>> stringEncodingCodes = {
|
||||||
|
{ Exif::ASCII, { 0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00 } },
|
||||||
|
{ Exif::Unicode, { 0x55, 0x4e, 0x49, 0x43, 0x4f, 0x44, 0x45, 0x00 } },
|
||||||
|
};
|
||||||
|
|
||||||
|
void Exif::setString(ExifIfd ifd, ExifTag tag, ExifFormat format,
|
||||||
|
const std::string &item, StringEncoding encoding)
|
||||||
{
|
{
|
||||||
std::string ascii;
|
std::string ascii;
|
||||||
size_t length;
|
size_t length;
|
||||||
const char *str;
|
const char *str;
|
||||||
|
std::vector<uint8_t> buf;
|
||||||
|
|
||||||
if (format == EXIF_FORMAT_ASCII) {
|
if (format == EXIF_FORMAT_ASCII) {
|
||||||
ascii = utils::toAscii(item);
|
ascii = utils::toAscii(item);
|
||||||
|
@ -191,13 +201,46 @@ void Exif::setString(ExifIfd ifd, ExifTag tag, ExifFormat format, const std::str
|
||||||
/* Pad 1 extra byte to null-terminate the ASCII string. */
|
/* Pad 1 extra byte to null-terminate the ASCII string. */
|
||||||
length = ascii.length() + 1;
|
length = ascii.length() + 1;
|
||||||
} else {
|
} else {
|
||||||
str = item.c_str();
|
std::u16string u16str;
|
||||||
|
|
||||||
|
auto encodingString = stringEncodingCodes.find(encoding);
|
||||||
|
if (encodingString != stringEncodingCodes.end()) {
|
||||||
|
buf = {
|
||||||
|
encodingString->second.begin(),
|
||||||
|
encodingString->second.end()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (encoding) {
|
||||||
|
case Unicode:
|
||||||
|
u16str = utf8ToUtf16(item);
|
||||||
|
|
||||||
|
buf.resize(8 + u16str.size() * 2);
|
||||||
|
for (size_t i = 0; i < u16str.size(); i++) {
|
||||||
|
if (order_ == EXIF_BYTE_ORDER_INTEL) {
|
||||||
|
buf[8 + 2 * i] = u16str[i] & 0xff;
|
||||||
|
buf[8 + 2 * i + 1] = (u16str[i] >> 8) & 0xff;
|
||||||
|
} else {
|
||||||
|
buf[8 + 2 * i] = (u16str[i] >> 8) & 0xff;
|
||||||
|
buf[8 + 2 * i + 1] = u16str[i] & 0xff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ASCII:
|
||||||
|
case NoEncoding:
|
||||||
|
buf.insert(buf.end(), item.begin(), item.end());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = reinterpret_cast<const char *>(buf.data());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Strings stored in different formats (EXIF_FORMAT_UNDEFINED)
|
* Strings stored in different formats (EXIF_FORMAT_UNDEFINED)
|
||||||
* are not null-terminated.
|
* are not null-terminated.
|
||||||
*/
|
*/
|
||||||
length = item.length();
|
length = buf.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
ExifEntry *entry = createEntry(ifd, tag, format, length, length);
|
ExifEntry *entry = createEntry(ifd, tag, format, length, length);
|
||||||
|
@ -290,6 +333,34 @@ void Exif::setThumbnail(Span<const unsigned char> thumbnail,
|
||||||
setShort(EXIF_IFD_0, EXIF_TAG_COMPRESSION, compression);
|
setShort(EXIF_IFD_0, EXIF_TAG_COMPRESSION, compression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Convert UTF-8 string to UTF-16 string
|
||||||
|
* \param[in] str String to convert
|
||||||
|
*
|
||||||
|
* \return \a str in UTF-16
|
||||||
|
*/
|
||||||
|
std::u16string Exif::utf8ToUtf16(const std::string &str)
|
||||||
|
{
|
||||||
|
mbstate_t state{};
|
||||||
|
char16_t c16;
|
||||||
|
const char *ptr = str.data();
|
||||||
|
const char *end = ptr + str.size();
|
||||||
|
|
||||||
|
std::u16string ret;
|
||||||
|
while (size_t rc = mbrtoc16(&c16, ptr, end - ptr + 1, &state)) {
|
||||||
|
if (rc == static_cast<size_t>(-2) ||
|
||||||
|
rc == static_cast<size_t>(-1))
|
||||||
|
break;
|
||||||
|
|
||||||
|
ret.push_back(c16);
|
||||||
|
|
||||||
|
if (rc > 0)
|
||||||
|
ptr += rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] int Exif::generate()
|
[[nodiscard]] int Exif::generate()
|
||||||
{
|
{
|
||||||
if (exifData_) {
|
if (exifData_) {
|
||||||
|
|
|
@ -26,6 +26,12 @@ public:
|
||||||
JPEG = 6,
|
JPEG = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum StringEncoding {
|
||||||
|
NoEncoding = 0,
|
||||||
|
ASCII = 1,
|
||||||
|
Unicode = 2,
|
||||||
|
};
|
||||||
|
|
||||||
void setMake(const std::string &make);
|
void setMake(const std::string &make);
|
||||||
void setModel(const std::string &model);
|
void setModel(const std::string &model);
|
||||||
|
|
||||||
|
@ -46,9 +52,12 @@ private:
|
||||||
void setShort(ExifIfd ifd, ExifTag tag, uint16_t item);
|
void setShort(ExifIfd ifd, ExifTag tag, uint16_t item);
|
||||||
void setLong(ExifIfd ifd, ExifTag tag, uint32_t item);
|
void setLong(ExifIfd ifd, ExifTag tag, uint32_t item);
|
||||||
void setString(ExifIfd ifd, ExifTag tag, ExifFormat format,
|
void setString(ExifIfd ifd, ExifTag tag, ExifFormat format,
|
||||||
const std::string &item);
|
const std::string &item,
|
||||||
|
StringEncoding encoding = NoEncoding);
|
||||||
void setRational(ExifIfd ifd, ExifTag tag, ExifRational item);
|
void setRational(ExifIfd ifd, ExifTag tag, ExifRational item);
|
||||||
|
|
||||||
|
std::u16string utf8ToUtf16(const std::string &str);
|
||||||
|
|
||||||
bool valid_;
|
bool valid_;
|
||||||
|
|
||||||
ExifData *data_;
|
ExifData *data_;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue