& quot; невозможно проанализировать & quot; IPTC Дата до XMP DateTime в exiv2

Я немного взломал exiv2, пытаясь расширить функции преобразования даты / времени между EXIF, IPTC и XMP. http://dev.exiv2.org/issues/864

Дата IPTC и время IPTC хранятся в отдельных полях, поэтому сначала я пытаюсь проанализировать дату IPTC, затем в своем коде я пытаюсь проанализировать время.

Я новичок в программировании, так что это будет довольно простой проблемой, но здесь все. Код добавляется в файл exiv2 convert.cpp внутри функции cnvIptcValue.

Точную ошибку я получаю из командной строки:

$ exiv2 -eiX iptc.jpg
Warning: Failed to convert Iptc.Application2.DateCreated to Xmp.photoshop.DateCreated, unable to parse '1944-09-08'
Warning: Failed to convert Iptc.Application2.DigitizationDate to Xmp.xmp.CreateDate, unable to parse '2015-03-06'

Сначала я подумал, что код преобразования даты не работает:

if (std::string(from) == "Iptc.Application2.DateCreated" || std::string(from) == "Iptc.Application2.DigitizationDate")  {

int year, month, day, hour, min, sec, tzHour, tzMinute;
char tzSign;
char buf[30];if (sscanf(value.c_str(), "%d-%d-%d", &year, &month, &day) != 3) {

EXV_WARNING << "Failed to convert " << from << " to " << to
<< ", unable to parse '" << value << "'\n";
return;
}

Но дальнейшее тестирование показало, что это был код преобразования времени, который терпит неудачу:

    const char* iptcTime = 0;
if (std::string(from) == "Iptc.Application2.DateCreated") {
iptcTime = "Iptc.Application2.TimeCreated";
}
else if (std::string(from) == "Iptc.Application2.DigitizationDate") {
iptcTime = "Iptc.Application2.DigitizationTime";
}
if (iptcTime) {
if (sscanf(value.c_str(), "%d:%d:%d%1c%d:%02d", &hour, &min, &sec, &tzSign, &tzHour, &tzMinute) != 6) {

EXV_WARNING << "Failed to convert " << from << " to " << to
<< ", unable to parse '" << value << "'\n";

return;
}

Поэтому временной код пытался проанализировать поле даты. Это было изменено в поле Time, добавив пару строк кода:

    Exiv2::IptcData::iterator iptctime_pos = iptcData_->findKey(IptcKey(from));
std::string value = iptctime_pos->toString();

Я также расширил код сообщения об ошибке, чтобы увидеть, что было в поле Time. результат сейчас:

Warning: Failed to convert Iptc.Application2.TimeCreated to Xmp.photoshop.DateCreated, unable to parse '11:11:14+00:00'
Year Month Day:          1944 9 8
Hour Minute Second:      32767 36913992 1978972555
Zone Sign Hour Minute:   "U+007F"  -184143665 6457088
Warning: Failed to convert Iptc.Application2.DigitizationTime to Xmp.xmp.CreateDate, unable to parse '16:26:47+00:00'
Year Month Day:          2015 3 6
Hour Minute Second:      32767 36909480 36909144
Zone Sign Hour Minute:   "U+007F"  -184143665 6457088

Он правильно разбирает поле Date, но не Time. Почему это? Разве это неправильно?

0

Решение

Решено! Были два изменения, необходимые.

Первым делом нужно было проверить тот же ключ, который был установлен ранее. Мои попытки проб и ошибок заставляли меня сканировать из «iptctime», а не из «value», что дало ошибку разбора.

std::string value = iptctime_pos->toString();

if (sscanf(value.c_str(), "%d:%d:%d%1c%d:%d", &hour, &min, &sec, &tzSign, &tzHour, &tzMinute) != 6) {

Вторым было добавить else if предотвращение перезаписи свойств DateTime с помощью общего кода назначения.

Полный рабочий результат:

if (std::string(from) == "Iptc.Application2.DateCreated" || std::string(from) == "Iptc.Application2.DigitizationDate")  {

int year, month, day, hour, min, sec, tzHour, tzMinute;
char tzSign;
std::string iptctime;
char buf[30];(sscanf(value.c_str(), "%d-%d-%d", &year, &month, &day)

const char* iptcTime = 0;
if (std::string(from) == "Iptc.Application2.DateCreated") {
iptcTime = "Iptc.Application2.TimeCreated";
}
else if (std::string(from) == "Iptc.Application2.DigitizationDate") {
iptcTime = "Iptc.Application2.DigitizationTime";
}
if (iptcTime) {
Exiv2::IptcData::iterator iptctime_pos = iptcData_->findKey(IptcKey(iptcTime));
if (iptctime_pos == iptcData_->end()) return;
if (iptctime_pos->key() == iptcTime) {
std::string value = iptctime_pos->toString();

sscanf(value.c_str(), "%d:%d:%d%1c%d:%d", &hour, &min, &sec, &tzSign, &tzHour, &tzMinute)
}
}
snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d%1c%02d:%02d",
year, month, day, hour, min, sec, tzSign, tzHour, tzMinute);
buf[sizeof(buf) - 1] = 0;
(*xmpData_)[to] = buf;
}

else if (std::string(from) != "Iptc.Application2.DateCreated" || std::string(from) != "Iptc.Application2.DigitizationDate")  {

(*xmpData_)[to] = value;
}

Немного больше тестирования, и я выложу его в репозиторий exiv2, который будет представлен в следующем выпуске exiv2 0.25!

PS: Спасибо @tivn за вашу помощь.

0

Другие решения


По вопросам рекламы [email protected]