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;
}