Beispiel #1
0
// Always creates a new metadata entry.
// Passing invalidTypeId causes the type to be guessed.
// Guessing types is accurate for IPTC, but not for EXIF.
// Returns 0 on success
EXIVSIMPLE_API int AddMeta(HIMAGE img, const char *key, const char *val, DllTypeId type)
{
    assert(img && key && val);
    if (img==0 || key==0 || val==0) return -1;
    ImageWrapper *imgWrap = (ImageWrapper*)img;
    int rc = 2;

    Exiv2::IptcData &iptcData = imgWrap->image->iptcData();
    Exiv2::ExifData &exifData = imgWrap->image->exifData();

    std::string data(val);
    {
        size_t dataLen = data.length();
        // if data starts and ends with quotes, remove them
        if (dataLen > 1 && *(data.begin()) == '\"' && *(data.rbegin()) == '\"') {
            data = data.substr(1, dataLen-2);
        }
    }

    try {
        Exiv2::IptcKey iptcKey(key);
        rc = 1;

        if (type == invalidTypeId)
            type = (DllTypeId)Exiv2::IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record());
        Exiv2::Value::AutoPtr value = Exiv2::Value::create((Exiv2::TypeId)type);
        value->read(data);

        rc = iptcData.add(iptcKey, value.get());
    }
    catch(const Exiv2::AnyError&) {
    }

    if (rc) {
        // Failed with iptc, so try exif
        try {
            Exiv2::ExifKey exifKey(key);
            rc = 1;

            // No way to get value type for exif... string is the most common
            if (type == invalidTypeId)
                type = asciiString;
            Exiv2::Value::AutoPtr value = Exiv2::Value::create((Exiv2::TypeId)type);
            value->read(data);

            exifData.add(exifKey, value.get());
            rc = 0;
        }
        catch(const Exiv2::AnyError&) {
        }
    }

    return rc;
}
Beispiel #2
0
// This is weird because iptc and exif have not been "unified". Once
// they are unified, this DLL should not have to know
// about either... just generic images, keys, values, etc.
//
// buffsize should be the total size of *buff (including space for null)
// Note that if there is more than one entry (for some IPTC datasets) this
// returns the first one found. Currently no way to get the others.
// Returns 0 on success
EXIVSIMPLE_API int ReadMeta(HIMAGE img, const char *key, char *buff, int buffsize)
{
    assert(img && key && buff);
    if (img==0 || key==0 || buff==0 || buffsize==0) return -1;
    ImageWrapper *imgWrap = (ImageWrapper*)img;
    int rc = 2;

    Exiv2::IptcData &iptcData = imgWrap->image->iptcData();
    Exiv2::ExifData &exifData = imgWrap->image->exifData();

    try {
        // First try iptc
        Exiv2::IptcKey iptcKey(key);
        rc = 1;
        Exiv2::IptcData::const_iterator iter = iptcData.findKey(iptcKey);
        if (iter != iptcData.end()) {
            strncpy(buff, iter->value().toString().c_str(), buffsize);
            buff[buffsize-1] = 0;
            rc = 0;
        }
    } 
    catch(const Exiv2::AnyError&) {
    }

    if (rc) {
        // No iptc value, so try exif
        try {
            Exiv2::ExifKey exifKey(key);
            rc = 1;
            Exiv2::ExifData::const_iterator iter = exifData.findKey(exifKey);
            if (iter != exifData.end()) {
                strncpy(buff, iter->value().toString().c_str(), buffsize);
                buff[buffsize-1] = 0;
                rc = 0;
            }
        }
        catch(const Exiv2::AnyError&) {
        }
    }

    return rc;
}
Beispiel #3
0
// If multiple entires exist, this only remove the first one
// found. Call multiple times to remove many.
// Returns 0 on success
EXIVSIMPLE_API int RemoveMeta(HIMAGE img, const char *key)
{
    assert(img && key);
    if (img==0 || key==0) return -1;
    ImageWrapper *imgWrap = (ImageWrapper*)img;
    int rc = 2;

    Exiv2::IptcData &iptcData = imgWrap->image->iptcData();
    Exiv2::ExifData &exifData = imgWrap->image->exifData();

    try {
        Exiv2::IptcKey iptcKey(key);
        rc = 1;
        Exiv2::IptcData::iterator iter = iptcData.findKey(iptcKey);
        if (iter != iptcData.end()) {
            iptcData.erase(iter);
            rc = 0;
        }
    } 
    catch(const Exiv2::AnyError&) {
    }

    if (rc) {
        // No iptc value, so try exif
        try {
            Exiv2::ExifKey exifKey(key);
            rc = 1;
            Exiv2::ExifData::iterator iter = exifData.findKey(exifKey);
            if (iter != exifData.end()) {
                exifData.erase(iter);
                rc = 0;
            }
        }
        catch(const Exiv2::AnyError&) {
        }
    }

    return rc;
}
bool ExtendedPhoto::findExifKey(const std::string& key, String& value) const
{
    const Exiv2::ExifData& exifData = pImage->exifData();

    try
    {
        Exiv2::ExifKey exifKey(key);
        Exiv2::ExifData::const_iterator citer = exifData.findKey(exifKey);

        if (citer != exifData.end())
        {
            value = citer->value().toString();
            value.trim();
            return true;
        }

        return false;
    }
    catch (...)
    {
        return false;
    }
}
Beispiel #5
0
// Overwrites existing value if found, otherwise creates a new one.
// Passing invalidTypeId causes the type to be guessed.
// Guessing types is accurate for IPTC, but not for EXIF.
// Returns 0 on success
EXIVSIMPLE_API int ModifyMeta(HIMAGE img, const char *key, const char *val, DllTypeId type)
{
    assert(img && key && val);
    if (img==0 || key==0 || val==0) return -1;
    ImageWrapper *imgWrap = (ImageWrapper*)img;
    int rc = 2;

    Exiv2::IptcData &iptcData = imgWrap->image->iptcData();
    Exiv2::ExifData &exifData = imgWrap->image->exifData();

    std::string data(val);
    // if data starts and ends with quotes, remove them
    if (data.at(0) == '\"' && data.at(data.size()-1) == '\"') {
        data = data.substr(1, data.size()-2);
    }

    try {
        Exiv2::IptcKey iptcKey(key);
        rc = 1;

        if (type == invalidTypeId)
            type = (DllTypeId)Exiv2::IptcDataSets::dataSetType(iptcKey.tag(), iptcKey.record());
        Exiv2::Value::AutoPtr value = Exiv2::Value::create((Exiv2::TypeId)type);
        value->read(data);

        Exiv2::IptcData::iterator iter = iptcData.findKey(iptcKey);
        if (iter != iptcData.end()) {
            iter->setValue(value.get());
            rc = 0;
        }
        else {
            rc = iptcData.add(iptcKey, value.get());
        }
    } 
    catch(const Exiv2::AnyError&) {
    }

    if (rc) {
        // Failed with iptc, so try exif
        try {
            Exiv2::ExifKey exifKey(key);
            rc = 1;

            // No way to get value type for exif... string is the most common
            if (type == invalidTypeId)
                type = asciiString;
            Exiv2::Value::AutoPtr value = Exiv2::Value::create((Exiv2::TypeId)type);
            value->read(data);

            Exiv2::ExifData::iterator iter = exifData.findKey(exifKey);
            if (iter != exifData.end()) {
                iter->setValue(value.get());
                rc = 0;
            }
            else {
                exifData.add(exifKey, value.get());
                rc = 0;
            }
        }
        catch(const Exiv2::AnyError&) {
        }
    }

    return rc;
}
Beispiel #6
0
bool KisExifIO::saveTo(KisMetaData::Store* store, QIODevice* ioDevice, HeaderType headerType) const
{
    ioDevice->open(QIODevice::WriteOnly);
    Exiv2::ExifData exifData;
    if (headerType == KisMetaData::IOBackend::JpegHeader) {
        QByteArray header(6, 0);
        header[0] = 0x45;
        header[1] = 0x78;
        header[2] = 0x69;
        header[3] = 0x66;
        header[4] = 0x00;
        header[5] = 0x00;
        ioDevice->write(header);
    }

    for (QHash<QString, KisMetaData::Entry>::const_iterator it = store->begin();
            it != store->end(); ++it) {
        try {
            const KisMetaData::Entry& entry = *it;
            dbgFile << "Trying to save: " << entry.name() << " of " << entry.schema()->prefix() << ":" << entry.schema()->uri();
            QString exivKey;
            if (entry.schema()->uri() == KisMetaData::Schema::TIFFSchemaUri) {
                exivKey = "Exif.Image." + entry.name();
            } else if (entry.schema()->uri() == KisMetaData::Schema::EXIFSchemaUri) { // Distinguish between exif and gps
                if (entry.name().left(3) == "GPS") {
                    exivKey = "Exif.GPS." + entry.name();
                } else {
                    exivKey = "Exif.Photo." + entry.name();
                }
            } else if (entry.schema()->uri() == KisMetaData::Schema::DublinCoreSchemaUri) {
                if (entry.name() == "description") {
                    exivKey = "Exif.Image.ImageDescription";
                } else if (entry.name() == "creator") {
                    exivKey = "Exif.Image.Artist";
                } else if (entry.name() == "rights") {
                    exivKey = "Exif.Image.Copyright";
                }
            } else if (entry.schema()->uri() == KisMetaData::Schema::XMPSchemaUri) {
                if (entry.name() == "ModifyDate") {
                    exivKey = "Exif.Image.DateTime";
                } else if (entry.name() == "CreatorTool") {
                    exivKey = "Exif.Image.Software";
                }
            } else if (entry.schema()->uri() == KisMetaData::Schema::MakerNoteSchemaUri) {
                if (entry.name() == "RawData") {
                    exivKey = "Exif.Photo.MakerNote";
                }
            }
            dbgFile << "Saving " << entry.name() << " to " << exivKey;
            if (exivKey.isEmpty()) {
                dbgFile << entry.qualifiedName() << " is unsavable to EXIF";
            } else {
                Exiv2::ExifKey exifKey(qPrintable(exivKey));
                Exiv2::Value* v = 0;
                if (exivKey == "Exif.Photo.ExifVersion" || exivKey == "Exif.Photo.FlashpixVersion") {
                    v = kmdValueToExifVersion(entry.value());
                } else if (exivKey == "Exif.Photo.FileSource") {
                    char s[] = { 0x03 };
                    v = new Exiv2::DataValue((const Exiv2::byte*)s, 1);
                } else if (exivKey == "Exif.Photo.SceneType") {
                    char s[] = { 0x01 };
                    v = new Exiv2::DataValue((const Exiv2::byte*)s, 1);
                } else if (exivKey == "Exif.Photo.ComponentsConfiguration") {
                    v = kmdIntOrderedArrayToExifArray(entry.value());
                } else if (exivKey == "Exif.Image.Artist") { // load as dc:creator
                    KisMetaData::Value creator = entry.value().asArray()[0];
#if EXIV2_MAJOR_VERSION == 0 && EXIV2_MINOR_VERSION <= 20
                    v = kmdValueToExivValue(creator, Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId()));
#else
                    v = kmdValueToExivValue(creator, exifKey.defaultTypeId());
#endif
                } else if (exivKey == "Exif.Photo.OECF") {
                    v = kmdOECFStructureToExifOECF(entry.value());
                } else if (exivKey == "Exif.Photo.DeviceSettingDescription") {
                    v = deviceSettingDescriptionKMDToExif(entry.value());
                } else if (exivKey == "Exif.Photo.CFAPattern") {
                    v = cfaPatternKMDToExif(entry.value());
                } else if (exivKey == "Exif.Photo.Flash") {
                    v = flashKMDToExif(entry.value());
                } else if (exivKey == "Exif.Photo.UserComment") {
                    Q_ASSERT(entry.value().type() == KisMetaData::Value::LangArray);
                    QMap<QString, KisMetaData::Value> langArr = entry.value().asLangArray();
                    if (langArr.contains("x-default")) {
#if EXIV2_MAJOR_VERSION == 0 && EXIV2_MINOR_VERSION <= 20
                        v = kmdValueToExivValue(langArr.value("x-default"), Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId()));
#else
                        v = kmdValueToExivValue(langArr.value("x-default"), exifKey.defaultTypeId());
#endif
                    } else if (langArr.size() > 0) {
#if EXIV2_MAJOR_VERSION == 0 && EXIV2_MINOR_VERSION <= 20
                        v = kmdValueToExivValue(langArr.begin().value(), Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId()));
#else
                        v = kmdValueToExivValue(langArr.begin().value(), exifKey.defaultTypeId());
#endif
                    }
                } else {
                    dbgFile << exifKey.tag();
#if EXIV2_MAJOR_VERSION == 0 && EXIV2_MINOR_VERSION <= 20
                    v = kmdValueToExivValue(entry.value(), Exiv2::ExifTags::tagType(exifKey.tag(), exifKey.ifdId()));
#else
                    v = kmdValueToExivValue(entry.value(), exifKey.defaultTypeId());
#endif
                }
                if (v && v->typeId() != Exiv2::invalidTypeId) {
                    dbgFile << "Saving key" << exivKey << " of KMD value" << entry.value();
                    exifData.add(exifKey, v);
                } else {
                    dbgFile << "No exif value was created for" << entry.qualifiedName() << " as" << exivKey;// << " of KMD value" << entry.value();
                }
            }
        } catch (Exiv2::AnyError& e) {
            dbgFile << "exiv error " << e.what();
        }
    }
#if EXIV2_MAJOR_VERSION == 0 && EXIV2_MINOR_VERSION <= 17
    Exiv2::DataBuf rawData = exifData.copy();
    ioDevice->write((const char*) rawData.pData_, rawData.size_);
#else
    Exiv2::Blob rawData;
    Exiv2::ExifParser::encode(rawData, Exiv2::littleEndian, exifData);
    ioDevice->write((const char*) &*rawData.begin(), rawData.size());
#endif
    ioDevice->close();
    return true;
}