Ejemplo n.º 1
0
    bool getXmpDateTime(Exiv2::XmpData &xmpData, QDateTime &dateTime) {
        bool anyFound = false;

        try {
            Exiv2::XmpKey psKey(XMP_PS_DATECREATED);
            Exiv2::XmpData::iterator xmpIt = xmpData.findKey(psKey);

            if (xmpIt != xmpData.end()) {
                dateTime = QDateTime::fromString(QString::fromLatin1(xmpIt->toString().c_str()), Qt::ISODate);
                anyFound = dateTime.isValid();
            }
        }
        catch (Exiv2::Error &e) {
            LOG_WARNING << "Exiv2 error:" << e.what();
            anyFound = false;
        }
        catch (...) {
            LOG_WARNING << "Exception";
            anyFound = false;
#ifdef QT_DEBUG
            throw;
#endif
        }

        return anyFound;
    }
Ejemplo n.º 2
0
    bool getXmpTagStringBag(Exiv2::XmpData &xmpData, const char *propertyName, QStringList &bag) {
        bool found = false;

        Exiv2::XmpKey key(propertyName);
        Exiv2::XmpData::iterator it = xmpData.findKey(key);

        if ((it != xmpData.end()) && (it->typeId() == Exiv2::xmpBag)) {
            found = true;
            int count = it->count();
            bag.reserve(count);

            if (count == 1) {
                QString bagValue = QString::fromUtf8(it->toString(0).c_str());
                if (bagValue.contains(',')) {
                    LOG_DEBUG << "processing legacy saved keywords";
                    bag += decomposeKeyword(bagValue);
                } else {
                    bag.append(bagValue);
                }
            } else {
                for (int i = 0; i < count; i++) {
                    QString bagValue = QString::fromUtf8(it->toString(i).c_str());
                    bag.append(bagValue);
                }
            }
        }

        return found;
    }
Ejemplo n.º 3
0
    bool getXmpDescription(Exiv2::XmpData &xmpData, const QString &langAlt, QString &description) {
        bool anyFound = false;

        try {
            anyFound = getXmpLangAltValue(xmpData, XMP_DESCRIPTION, langAlt, description);

            if (!anyFound || description.isEmpty()) {
                Exiv2::XmpKey psKey(XMP_PS_HEADLINE);
                Exiv2::XmpData::iterator xmpIt = xmpData.findKey(psKey);
                if (xmpIt != xmpData.end()) {
                    const Exiv2::XmpTextValue &value = static_cast<const Exiv2::XmpTextValue &>(xmpIt->value());
                    QString headline = QString::fromUtf8(value.value_.c_str()).trimmed();

                    if (!headline.isEmpty()) {
                        anyFound = true;
                        description = headline;
                    }
                }
            }
        }
        catch (Exiv2::Error &e) {
            LOG_WARNING << "Exiv2 error:" << e.what();
            anyFound = false;
        }
        catch (...) {
            LOG_WARNING << "Exception";
            anyFound = false;
#ifdef QT_DEBUG
            throw;
#endif
        }

        return anyFound;
    }
Ejemplo n.º 4
0
void KExiv2::Private::mergeXmpData(const Exiv2::XmpData& src, Exiv2::XmpData& dest)
{
    for (Exiv2::XmpData::const_iterator it = src.begin(); it != src.end(); ++it)
    {
        Exiv2::XmpData::iterator destIt = dest.findKey(Exiv2::XmpKey(it->key()));

        if (destIt == dest.end())
        {
            dest.add(*it);
        }
        else
        {
            *destIt = *it;
        }
    }
}
Ejemplo n.º 5
0
int main(int argc, char* const argv[])
try {
    if (argc != 2) {
        std::cout << "Usage: " << argv[0] << " file\n";
        return 1;
    }
    std::string filename(argv[1]);
    Exiv2::DataBuf buf = Exiv2::readFile(filename);
    std::string xmpPacket;
    xmpPacket.assign(reinterpret_cast<char*>(buf.pData_), buf.size_);
    std::cerr << "-----> Decoding XMP data read from " << filename << " <-----\n";
    Exiv2::XmpData xmpData;
    if (0 != Exiv2::XmpParser::decode(xmpData, xmpPacket)) {
        std::string error(argv[1]);
        error += ": Failed to parse file contents (XMP packet)";
        throw Exiv2::Error(Exiv2::kerErrorMessage, error);
    }
    if (xmpData.empty()) {
        std::string error(argv[1]);
        error += ": No XMP properties found in the XMP packet";
        throw Exiv2::Error(Exiv2::kerErrorMessage, error);
    }
    for (Exiv2::XmpData::const_iterator md = xmpData.begin();
         md != xmpData.end(); ++md) {
        std::cout << std::setfill(' ') << std::left
                  << std::setw(44)
                  << md->key() << " "
                  << std::setw(9) << std::setfill(' ') << std::left
                  << md->typeName() << " "
                  << std::dec << std::setw(3)
                  << std::setfill(' ') << std::right
                  << md->count() << "  "
                  << std::dec << md->value()
                  << std::endl;
    }
    filename += "-new";
    std::cerr << "-----> Encoding XMP data to write to " << filename << " <-----\n";
    if (0 != Exiv2::XmpParser::encode(xmpPacket, xmpData)) {
        std::string error(argv[1]);
        error += ": Failed to encode the XMP data";
        throw Exiv2::Error(Exiv2::kerErrorMessage, error);
    }
    Exiv2::FileIo file(filename);
    if (file.open("wb") != 0) {
        throw Exiv2::Error(Exiv2::kerFileOpenFailed, filename, "wb", Exiv2::strError());
    }
    if (file.write(reinterpret_cast<const Exiv2::byte*>(xmpPacket.data()), static_cast<long>(xmpPacket.size())) == 0) {
        throw Exiv2::Error(Exiv2::kerCallFailed, filename, Exiv2::strError(), "FileIo::write");
    }
    Exiv2::XmpParser::terminate();
    return 0;
}
catch (Exiv2::AnyError& e) {
    std::cout << "Caught Exiv2 exception '" << e << "'\n";
    return -1;
}
Ejemplo n.º 6
0
int main(int argc, char* const argv[])
try {
    if (argc != 2) {
        std::cout << "Usage: " << argv[0] << " file\n";
        return 1;
    }
    Exiv2::DataBuf buf = Exiv2::readFile(argv[1]);
    std::string xmpPacket;
    xmpPacket.assign(reinterpret_cast<char*>(buf.pData_), buf.size_);
    Exiv2::XmpData xmpData;
    if (0 != Exiv2::XmpParser::decode(xmpData, xmpPacket)) {
        std::string error(argv[1]);
        error += ": Failed to parse file contents (XMP packet)";
        throw Exiv2::Error(1, error);
    }
    if (xmpData.empty()) {
        std::string error(argv[1]);
        error += ": No XMP properties found in the XMP packet";
        throw Exiv2::Error(1, error);
    }
    for (Exiv2::XmpData::const_iterator md = xmpData.begin(); 
         md != xmpData.end(); ++md) {
        std::cout << std::setfill(' ') << std::left
                  << std::setw(44)
                  << md->key() << " "
                  << std::setw(9) << std::setfill(' ') << std::left
                  << md->typeName() << " "
                  << std::dec << std::setw(3)
                  << std::setfill(' ') << std::right
                  << md->count() << "  "
                  << std::dec << md->value()
                  << std::endl;
    }
    Exiv2::XmpParser::terminate();
    return 0;
}
catch (Exiv2::AnyError& e) {
    std::cout << "Caught Exiv2 exception '" << e << "'\n";
    return -1;
}
Ejemplo n.º 7
0
    bool getXmpLangAltValue(Exiv2::XmpData &xmpData, const char *propertyName,
                            const QString &langAlt, QString &resultValue) {
        bool anyFound = false;

        Exiv2::XmpKey key(propertyName);
        Exiv2::XmpData::iterator it = xmpData.findKey(key);
        if ((it != xmpData.end()) && (it->typeId() == Exiv2::langAlt)) {
            const Exiv2::LangAltValue &value = static_cast<const Exiv2::LangAltValue &>(it->value());

            QString anyValue;

            Exiv2::LangAltValue::ValueType::const_iterator it2 = value.value_.begin();
            Exiv2::LangAltValue::ValueType::const_iterator end = value.value_.end();
            for (; it2 != end; ++it2) {
                QString lang = QString::fromUtf8(it2->first.c_str());

                if (langAlt == lang) {
                    QString text = QString::fromUtf8(it2->second.c_str()).trimmed();
                    if (!text.isEmpty()) {
                        anyFound = true;
                        resultValue = text.trimmed();
                        break;
                    }
                }

                if (anyValue.isEmpty()) {
                    QString text = QString::fromUtf8(it2->second.c_str());
                    anyValue = text.trimmed();
                }
            }

            if (!anyFound && !anyValue.isEmpty()) {
                anyFound = true;
                resultValue = anyValue;
            }
        }

        return anyFound;
    }
Ejemplo n.º 8
0
int main()
try {
    // The XMP property container
    Exiv2::XmpData xmpData;

    // -------------------------------------------------------------------------
    // Teaser: Setting XMP properties doesn't get much easier than this:

    xmpData["Xmp.dc.source"]  = "xmpsample.cpp";    // a simple text value
    xmpData["Xmp.dc.subject"] = "Palmtree";         // an array item
    xmpData["Xmp.dc.subject"] = "Rubbertree";       // add a 2nd array item
    // a language alternative with two entries and without default
    xmpData["Xmp.dc.title"]   = "lang=de-DE Sonnenuntergang am Strand";
    xmpData["Xmp.dc.title"]   = "lang=en-US Sunset on the beach";

    // -------------------------------------------------------------------------
    // Any properties can be set provided the namespace is known. Values of any
    // type can be assigned to an Xmpdatum, if they have an output operator. The
    // default XMP value type for unknown properties is a simple text value.

    xmpData["Xmp.dc.one"]     = -1;
    xmpData["Xmp.dc.two"]     = 3.1415;
    xmpData["Xmp.dc.three"]   = Exiv2::Rational(5, 7);
    xmpData["Xmp.dc.four"]    = uint16_t(255);
    xmpData["Xmp.dc.five"]    = int32_t(256);
    xmpData["Xmp.dc.six"]     = false;

    // In addition, there is a dedicated assignment operator for Exiv2::Value
    Exiv2::XmpTextValue val("Seven");
    xmpData["Xmp.dc.seven"]   = val;
    xmpData["Xmp.dc.eight"]   = true;

    // Extracting values
    assert(xmpData["Xmp.dc.one"].toLong() == -1);
    assert(xmpData["Xmp.dc.one"].value().ok());

    const Exiv2::Value &getv1 = xmpData["Xmp.dc.one"].value();
    assert(isEqual(getv1.toFloat(), -1)); 
    assert(getv1.ok());
    assert(getv1.toRational() == Exiv2::Rational(-1, 1));
    assert(getv1.ok());

    const Exiv2::Value &getv2 = xmpData["Xmp.dc.two"].value();
    assert(isEqual(getv2.toFloat(), 3.1415f)); 
    assert(getv2.ok());
    assert(getv2.toLong() == 3);
    assert(getv2.ok());
    Exiv2::Rational R = getv2.toRational();
    assert(getv2.ok());
    assert(isEqual(static_cast<float>(R.first) / R.second, 3.1415f ));

    const Exiv2::Value &getv3 = xmpData["Xmp.dc.three"].value();
    assert(isEqual(getv3.toFloat(), 5.0f/7.0f)); 
    assert(getv3.ok());
    assert(getv3.toLong() == 0);  // long(5.0 / 7.0) 
    assert(getv3.ok());
    assert(getv3.toRational() == Exiv2::Rational(5, 7));
    assert(getv3.ok());
    
    const Exiv2::Value &getv6 = xmpData["Xmp.dc.six"].value();
    assert(getv6.toLong() == 0);
    assert(getv6.ok());
    assert(getv6.toFloat() == 0.0);
    assert(getv6.ok());
    assert(getv6.toRational() == Exiv2::Rational(0, 1));
    assert(getv6.ok());
    
    const Exiv2::Value &getv7 = xmpData["Xmp.dc.seven"].value();
    getv7.toLong(); // this should fail
    assert(!getv7.ok()); 

    const Exiv2::Value &getv8 = xmpData["Xmp.dc.eight"].value();
    assert(getv8.toLong() == 1);
    assert(getv8.ok());
    assert(getv8.toFloat() == 1.0);
    assert(getv8.ok());
    assert(getv8.toRational() == Exiv2::Rational(1, 1));
    assert(getv8.ok());

    // Deleting an XMP property
    Exiv2::XmpData::iterator pos = xmpData.findKey(Exiv2::XmpKey("Xmp.dc.eight"));
    if (pos == xmpData.end()) throw Exiv2::Error(1, "Key not found");
    xmpData.erase(pos);

    // -------------------------------------------------------------------------
    // Exiv2 has specialized values for simple XMP properties, arrays of simple
    // properties and language alternatives.

    // Add a simple XMP property in a known namespace    
    Exiv2::Value::AutoPtr v = Exiv2::Value::create(Exiv2::xmpText);
    v->read("image/jpeg");
    xmpData.add(Exiv2::XmpKey("Xmp.dc.format"), v.get());

    // Add an ordered array of text values.
    v = Exiv2::Value::create(Exiv2::xmpSeq); // or xmpBag or xmpAlt.
    v->read("1) The first creator");         // The sequence in which the array
    v->read("2) The second creator");        // elements are added is their
    v->read("3) And another one");           // order in the array.
    xmpData.add(Exiv2::XmpKey("Xmp.dc.creator"), v.get());

    // Add a language alternative property
    v = Exiv2::Value::create(Exiv2::langAlt);
    v->read("lang=de-DE Hallo, Welt");       // The default doesn't need a 
    v->read("Hello, World");                 // qualifier
    xmpData.add(Exiv2::XmpKey("Xmp.dc.description"), v.get());

    // According to the XMP specification, Xmp.tiff.ImageDescription is an
    // alias for Xmp.dc.description. Exiv2 treats an alias just like any
    // other property and leaves it to the application to implement specific
    // behaviour if desired.
    xmpData["Xmp.tiff.ImageDescription"] = "TIFF image description";
    xmpData["Xmp.tiff.ImageDescription"] = "lang=de-DE TIFF Bildbeschreibung";

    // -------------------------------------------------------------------------
    // Register a namespace which Exiv2 doesn't know yet. This is only needed
    // when properties are added manually. If the XMP metadata is read from an
    // image, namespaces are decoded and registered at the same time.
    Exiv2::XmpProperties::registerNs("myNamespace/", "ns");

    // -------------------------------------------------------------------------
    // Add a property in the new custom namespace.
    xmpData["Xmp.ns.myProperty"] = "myValue";

    // -------------------------------------------------------------------------
    // There are no specialized values for structures, qualifiers and nested
    // types. However, these can be added by using an XmpTextValue and a path as
    // the key.

    // Add a structure
    Exiv2::XmpTextValue tv("16");
    xmpData.add(Exiv2::XmpKey("Xmp.xmpDM.videoFrameSize/stDim:w"), &tv);
    tv.read("9");
    xmpData.add(Exiv2::XmpKey("Xmp.xmpDM.videoFrameSize/stDim:h"), &tv);
    tv.read("inch");
    xmpData.add(Exiv2::XmpKey("Xmp.xmpDM.videoFrameSize/stDim:unit"), &tv);

    // Add an element with a qualifier (using the namespace registered above)
    xmpData["Xmp.dc.publisher"] = "James Bond";  // creates an unordered array
    xmpData["Xmp.dc.publisher[1]/?ns:role"] = "secret agent";

    // Add a qualifer to an array element of Xmp.dc.creator (added above)
    tv.read("programmer");
    xmpData.add(Exiv2::XmpKey("Xmp.dc.creator[2]/?ns:role"), &tv);

    // Add an array of structures
    tv.read("");                                         // Clear the value
    tv.setXmpArrayType(Exiv2::XmpValue::xaBag);
    xmpData.add(Exiv2::XmpKey("Xmp.xmpBJ.JobRef"), &tv); // Set the array type.

    tv.setXmpArrayType(Exiv2::XmpValue::xaNone);
    tv.read("Birthday party");
    xmpData.add(Exiv2::XmpKey("Xmp.xmpBJ.JobRef[1]/stJob:name"), &tv);
    tv.read("Photographer");
    xmpData.add(Exiv2::XmpKey("Xmp.xmpBJ.JobRef[1]/stJob:role"), &tv);

    tv.read("Wedding ceremony");
    xmpData.add(Exiv2::XmpKey("Xmp.xmpBJ.JobRef[2]/stJob:name"), &tv);
    tv.read("Best man");
    xmpData.add(Exiv2::XmpKey("Xmp.xmpBJ.JobRef[2]/stJob:role"), &tv);

    // -------------------------------------------------------------------------
    // Output XMP properties
    for (Exiv2::XmpData::const_iterator md = xmpData.begin(); 
         md != xmpData.end(); ++md) {
        std::cout << std::setfill(' ') << std::left
                  << std::setw(44)
                  << md->key() << " "
                  << std::setw(9) << std::setfill(' ') << std::left
                  << md->typeName() << " "
                  << std::dec << std::setw(3)
                  << std::setfill(' ') << std::right
                  << md->count() << "  "
                  << std::dec << md->value()
                  << std::endl;
    }

    // -------------------------------------------------------------------------
    // Serialize the XMP data and output the XMP packet
    std::string xmpPacket;
    if (0 != Exiv2::XmpParser::encode(xmpPacket, xmpData)) {
        throw Exiv2::Error(1, "Failed to serialize XMP data");
    }
    std::cout << xmpPacket << "\n";

    // Cleanup
    Exiv2::XmpParser::terminate();

    return 0;
}
catch (Exiv2::AnyError& e) {
    std::cout << "Caught Exiv2 exception '" << e << "'\n";
    return -1;
}