首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >"unable to parse“IPTC Date to XMP DateTime in exiv2

"unable to parse“IPTC Date to XMP DateTime in exiv2
EN

Stack Overflow用户
提问于 2015-04-11 23:11:55
回答 1查看 179关注 0票数 0

我对exiv2进行了一些修改,试图扩展它在EXIF、IPTC和XMP之间的日期/时间转换功能。http://dev.exiv2.org/issues/864

IPTC日期和IPTC时间存储在单独的字段中,所以我首先尝试解析IPTC日期,然后在我的代码中尝试解析时间。

我是一个编程的初学者,所以这看起来是一个非常基本的问题,但现在开始。代码将被添加到cnvIptcValue函数内的exiv2文件convert.cpp中。

我从命令行得到的确切错误是:

代码语言:javascript
复制
$ 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'

起初,我认为日期转换代码失败了:

代码语言:javascript
复制
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;
}

但进一步的测试表明,失败的是时间转换代码:

代码语言:javascript
复制
    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;
    }

所以时间代码试图解析日期字段。通过添加几行代码将其更改为时间字段:

代码语言:javascript
复制
    Exiv2::IptcData::iterator iptctime_pos = iptcData_->findKey(IptcKey(from));
    std::string value = iptctime_pos->toString();

我还展开了错误消息代码,以查看时间字段中的内容。现在的结果是:

代码语言:javascript
复制
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

它可以正确解析日期字段,但不能正确解析时间。为什么会这样呢?它是不是解析错了东西?

EN

回答 1

Stack Overflow用户

发布于 2015-04-13 09:51:56

解决了!需要做两个改变。

首先要确保扫描的密钥与之前设置的密钥相同。我的尝试和错误尝试让我从"iptctime“而不是"value”进行扫描,这给出了解析错误。

代码语言:javascript
复制
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属性被通用赋值代码重写。

完整的工作结果是:

代码语言:javascript
复制
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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29579434

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档