2015-04-11 8 views
0

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

Дата 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; 
    } 

Таким образом, код времени пытался проанализировать поле «Дата». Это было изменено на поле времени, добавив пару строк кода:

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

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

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 

Он правильно разбирает поле «Дата», но не «Время». Почему это? Разбирает ли он неправильную вещь?

+0

Я проверяю с http://dev.exiv2.org/projects/exiv2/repository/entry/trunk/src/convert.cpp, я обнаружил, что он использует двоеточие ':', а не dash '-':' if (sscanf (значение.c_str(), "% d:% d:% d", & year, & month, & day)! = 3) '. Но ваш код использует '-'. Какой из них правильный? – tivn

+0

EXIF ​​использует двоеточие, IPTC использует тире. – asp

+0

Вы уверены, что предупреждение запускается внутри 'Converter :: cnvIptcValue()', а не внутри 'Converter :: cnvExifDate()'? – tivn

ответ

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 за помощь.