bool ptImageHelper::ReadExif(const QString &AFileName, Exiv2::ExifData &AExifData, std::vector<uint8_t> &AExifBuffer) { if (AFileName.trimmed().isEmpty()) return false; try { if (Exiv2::ImageFactory::getType(AFileName.toLocal8Bit().data()) == Exiv2::ImageType::none) return false; Exiv2::Image::AutoPtr hImage = Exiv2::ImageFactory::open(AFileName.toLocal8Bit().data()); if (!hImage.get()) return false; hImage->readMetadata(); AExifData = hImage->exifData(); if (AExifData.empty()) { ptLogWarning(ptWarning_Argument, "No Exif data found in %s", AFileName.toLocal8Bit().data()); return false; } Exiv2::ExifData::iterator Pos; size_t Size; #if EXIV2_TEST_VERSION(0,17,91) /* Exiv2 0.18-pre1 */ Exiv2::Blob Blob; Exiv2::ExifParser::encode(Blob, Exiv2::bigEndian, AExifData); Size = Blob.size(); #else Exiv2::DataBuf Buf(AExifData.copy()); Size = Buf.size_; #endif /* If buffer too big for JPEG, try deleting some stuff. */ if (Size + CExifHeader.size() > CMaxHeaderLength) { if ((Pos = AExifData.findKey(Exiv2::ExifKey("Exif.Photo.MakerNote"))) != AExifData.end() ) { AExifData.erase(Pos); ptLogWarning(ptWarning_Argument, "Exif buffer too big, erasing Exif.Photo.MakerNote"); #if EXIV2_TEST_VERSION(0,17,91) /* Exiv2 0.18-pre1 */ Exiv2::ExifParser::encode(Blob, Exiv2::bigEndian, AExifData); Size = Blob.size(); #else Buf = AExifData.copy(); Size = Buf.size_; #endif } } // Erase embedded thumbnail if needed if (Settings->GetInt("EraseExifThumbnail") || (Size + CExifHeader.size()) > CMaxHeaderLength ) { #if EXIV2_TEST_VERSION(0,17,91) /* Exiv2 0.18-pre1 */ Exiv2::ExifThumb Thumb(AExifData); Thumb.erase(); #else AExifData.eraseThumbnail(); #endif if (!Settings->GetInt("EraseExifThumbnail")) ptLogWarning(ptWarning_Argument, "Exif buffer too big, erasing Thumbnail"); #if EXIV2_TEST_VERSION(0,17,91) /* Exiv2 0.18-pre1 */ Exiv2::ExifParser::encode(Blob, Exiv2::bigEndian, AExifData); Size = Blob.size(); #else Buf = AExifData.copy(); Size = Buf.size_; #endif } AExifBuffer.clear(); AExifBuffer.insert(AExifBuffer.end(), CExifHeader.begin(), CExifHeader.end()); #if EXIV2_TEST_VERSION(0,17,91) /* Exiv2 0.18-pre1 */ AExifBuffer.insert(AExifBuffer.end(), Blob.begin(), Blob.end()); #else // old code will currently not compile memcpy(AExifBuffer+sizeof(ExifHeader), Buf.pData_, Buf.size_); #endif return true; } catch(Exiv2::Error& Error) { // Exiv2 errors are in this context hopefully harmless // (unsupported tags etc.) ptLogWarning(ptWarning_Exiv2,"Exiv2 : %s\n",Error.what()); } return false; }
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; }