Commit 2ef074a3 authored by Gilles Caulier's avatar Gilles Caulier 🗼
Browse files

ExifTool support: add new method to apply list of changes operated on metadata.

A temporary EXV file constainer is computed with the list of changes to operated on Exif, Iptc, and Xmp.
This EXV file is processed with ExifTool to patch metadata.
Add new CLI test tool to try apply changes with EXV constainer. Here the file is patched with DMetadata::setImageDateTime()
which change or add new tags in Exif, Iptc, and Xmp

Exemple of changes processed to a CR3 raw image:

CR3 ORIGINAL:

exiftool -G:0:1:2:4 -exif:all -xmp:all 2020-09-22_21-27-23_0C4A1060.CR3_original
[EXIF:IFD0:Image] Image Width                   : 8192
[EXIF:IFD0:Image] Image Height                  : 5464
[EXIF:IFD0:Image] Bits Per Sample               : 8 8 8
[EXIF:IFD0:Image] Compression                   : JPEG (old-style)
[EXIF:IFD0:Camera] Make                         : Canon
[EXIF:IFD0:Camera] Camera Model Name            : Canon EOS R5
[EXIF:IFD0:Image] Orientation                   : Rotate 90 CW
[EXIF:IFD0:Image] Resolution Unit               : inches
[EXIF:IFD0:Author] Artist                       : kdmurray
[EXIF:IFD0:Author] Copyright                    :
[EXIF:ExifIFD:Image] Exposure Time              : 1/200
[EXIF:ExifIFD:Image] F Number                   : 10.0
[EXIF:ExifIFD:Camera] Exposure Program          : Manual
[EXIF:ExifIFD:Image] ISO                        : 400
[EXIF:ExifIFD:Image] Sensitivity Type           : Recommended Exposure Index
[EXIF:ExifIFD:Image] Recommended Exposure Index : 400
[EXIF:ExifIFD:Image] Exif Version               : 0231
[EXIF:ExifIFD:Time] Date/Time Original          : 2020:09:22 21:27:23
[EXIF:ExifIFD:Time] Offset Time                 : +10:00
[EXIF:ExifIFD:Time] Offset Time Original        : +10:00
[EXIF:ExifIFD:Time] Offset Time Digitized       : +10:00
[EXIF:ExifIFD:Image] Components Configuration   : Y, Cb, Cr, -
[EXIF:ExifIFD:Image] Shutter Speed Value        : 1/197
[EXIF:ExifIFD:Image] Aperture Value             : 9.9
[EXIF:ExifIFD:Camera] Flash                     : On, Fired
[EXIF:ExifIFD:Camera] Focal Length              : 90.0 mm
[EXIF:ExifIFD:Image] User Comment               :
[EXIF:ExifIFD:Time] Sub Sec Time                : 59
[EXIF:ExifIFD:Time] Sub Sec Time Original       : 59
[EXIF:ExifIFD:Time] Sub Sec Time Digitized      : 59
[EXIF:ExifIFD:Image] Flashpix Version           : 0100
[EXIF:ExifIFD:Image] Exif Image Width           : 8192
[EXIF:ExifIFD:Image] Exif Image Height          : 5464
[EXIF:ExifIFD:Camera] Focal Plane X Resolution  : 5773.079634
[EXIF:ExifIFD:Camera] Focal Plane Y Resolution  : 5769.799366
[EXIF:ExifIFD:Camera] Focal Plane Resolution Unit: inches
[EXIF:ExifIFD:Image] Custom Rendered            : Normal
[EXIF:ExifIFD:Camera] Exposure Mode             : Manual
[EXIF:ExifIFD:Camera] Scene Capture Type        : Standard
[EXIF:ExifIFD:Image] Serial Number              : 035021000124
[EXIF:ExifIFD:Image] Lens Info                  : 90mm f/0
[EXIF:ExifIFD:Image] Lens Serial Number         : 0000000000
[EXIF:GPS:Location] GPS Version ID              : 2.3.0.0
[EXIF:GPS:Location] GPS Altitude Ref            : Above Sea Level
[EXIF:GPS:Location] GPS Satellites              :
[EXIF:GPS:Location] GPS Status                  : Unknown ()
[EXIF:GPS:Location] GPS Measure Mode            : Unknown ()
[XMP:XMP-xmp:Image] Rating                      : 0

*EXV constainer generated:

exiftool -G:0:1:2:4 -exif:all -xmp:all 2020-09-22_21-27-23_0C4A1060_changes.exv
[XMP:XMP-x:Document] XMP Toolkit                : XMP Core 4.4.0-Exiv2
[XMP:XMP-exif:Time] Date/Time Original          : 2021:05:09 15:02:43
[XMP:XMP-exif:Time] Date/Time Digitized         : 2021:05:09 15:02:43
[XMP:XMP-tiff:Time] Date/Time Modified          : 2021:05:09 15:02:43
[XMP:XMP-xmp:Time] Create Date                  : 2021:05:09 15:02:43
[XMP:XMP-xmp:Time] Metadata Date                : 2021:05:09 15:02:43
[XMP:XMP-xmp:Time] Modify Date                  : 2021:05:09 15:02:43

*CR3 PATCHED:

exiftool]$ exiftool -G:0:1:2:4 -exif:all -xmp:all 2020-09-22_21-27-23_0C4A1060.CR3
[EXIF:IFD0:Image] Image Width                   : 8192
[EXIF:IFD0:Image] Image Height                  : 5464
[EXIF:IFD0:Image] Bits Per Sample               : 8 8 8
[EXIF:IFD0:Image] Compression                   : JPEG (old-style)
[EXIF:IFD0:Camera] Make                         : Canon
[EXIF:IFD0:Camera] Camera Model Name            : Canon EOS R5
[EXIF:IFD0:Image] Orientation                   : Rotate 90 CW
[EXIF:IFD0:Image] Resolution Unit               : inches
[EXIF:IFD0:Author] Artist                       : kdmurray
[EXIF:IFD0:Author] Copyright                    :
[EXIF:ExifIFD:Image] Exposure Time              : 1/200
[EXIF:ExifIFD:Image] F Number                   : 10.0
[EXIF:ExifIFD:Camera] Exposure Program          : Manual
[EXIF:ExifIFD:Image] ISO                        : 400
[EXIF:ExifIFD:Image] Sensitivity Type           : Recommended Exposure Index
[EXIF:ExifIFD:Image] Recommended Exposure Index : 400
[EXIF:ExifIFD:Image] Exif Version               : 0231
[EXIF:ExifIFD:Time] Offset Time                 : +10:00
[EXIF:ExifIFD:Time] Offset Time Original        : +10:00
[EXIF:ExifIFD:Time] Offset Time Digitized       : +10:00
[EXIF:ExifIFD:Image] Components Configuration   : Y, Cb, Cr, -
[EXIF:ExifIFD:Image] Shutter Speed Value        : 1/197
[EXIF:ExifIFD:Image] Aperture Value             : 9.9
[EXIF:ExifIFD:Camera] Flash                     : On, Fired
[EXIF:ExifIFD:Camera] Focal Length              : 90.0 mm
[EXIF:ExifIFD:Image] User Comment               :
[EXIF:ExifIFD:Time] Sub Sec Time                : 59
[EXIF:ExifIFD:Time] Sub Sec Time Original       : 59
[EXIF:ExifIFD:Time] Sub Sec Time Digitized      : 59
[EXIF:ExifIFD:Image] Flashpix Version           : 0100
[EXIF:ExifIFD:Image] Exif Image Width           : 8192
[EXIF:ExifIFD:Image] Exif Image Height          : 5464
[EXIF:ExifIFD:Camera] Focal Plane X Resolution  : 5773.079634
[EXIF:ExifIFD:Camera] Focal Plane Y Resolution  : 5769.799366
[EXIF:ExifIFD:Camera] Focal Plane Resolution Unit: inches
[EXIF:ExifIFD:Image] Custom Rendered            : Normal
[EXIF:ExifIFD:Camera] Exposure Mode             : Manual
[EXIF:ExifIFD:Camera] Scene Capture Type        : Standard
[EXIF:ExifIFD:Image] Serial Number              : 035021000124
[EXIF:ExifIFD:Image] Lens Info                  : 90mm f/0
[EXIF:ExifIFD:Image] Lens Serial Number         : 0000000000
[EXIF:GPS:Location] GPS Version ID              : 2.3.0.0
[EXIF:GPS:Location] GPS Altitude Ref            : Above Sea Level
[EXIF:GPS:Location] GPS Satellites              :
[EXIF:GPS:Location] GPS Status                  : Unknown ()
[EXIF:GPS:Location] GPS Measure Mode            : Unknown ()
[XMP:XMP-x:Document] XMP Toolkit                : Image::ExifTool 12.00
[XMP:XMP-exif:Time] Date/Time Digitized         : 2021:05:09 15:02:43           <====!
[XMP:XMP-exif:Time] Date/Time Original          : 2021:05:09 15:02:43           <====!
[XMP:XMP-photoshop:Time] Date Created           : 2021:05:09 15:02:43           <====!
[XMP:XMP-tiff:Time] Date/Time Modified          : 2021:05:09 15:02:43           <====!
[XMP:XMP-xmp:Time] Create Date                  : 2021:05:09 15:02:43           <====!
[XMP:XMP-xmp:Time] Metadata Date                : 2021:05:09 15:02:43           <====!
[XMP:XMP-xmp:Time] Modify Date                  : 2021:05:09 15:02:43           <====!
[XMP:XMP-xmp:Image] Rating                      : 0

CCBUGS: 134486, 170693, 219856, 237504, 264210, 309341, 325458, 326408, 377622, 384092, 406540, 416516, 421464, 436286
parent e7f9d69a
Pipeline #61245 canceled with stage
......@@ -123,12 +123,22 @@ public:
bool loadChunk(const QString& path);
/**
* Apply tag changes to a file with ExifTool.
* Tags can already exists in file or are new ones.
* Apply tag changes to a target file with ExifTool with a list of tag properties.
* Tags can already exists in target file or new ones can be created.
* To remove a tag, pass an empty string as value.
* 'path' is the target files to change.
* 'newTags' is the list of tag properties.
*/
bool applyChanges(const QString& path, const ExifToolData& newTags);
/**
* Apply tag changes to a target file with ExifTool with a EXV container.
* Tags can already exists in target file or new ones can be created.
* 'path' is the target files to change.
* 'exvTempFile' is the list of changes embeded in EXV constainer.
*/
bool applyChanges(const QString& path, const QString& exvTempFile);
/**
* Return a list of readable file format extensions.
* Use currentData() to get the container as QStringList.
......
......@@ -148,6 +148,38 @@ bool ExifToolParser::applyChanges(const QString& path, const ExifToolData& newTa
return (d->startProcess(cmdArgs, ExifToolProcess::APPLY_CHANGES));
}
bool ExifToolParser::applyChanges(const QString& path, const QString& exvTempFile)
{
if (exvTempFile.isEmpty())
{
qCWarning(DIGIKAM_METAENGINE_LOG) << "EXV constainer files to apply changes with ExifTool is empty";
return false;
}
QFileInfo fileInfo(path);
if (!fileInfo.exists())
{
return false;
}
if (!d->prepareProcess())
{
return false;
}
QByteArrayList cmdArgs;
cmdArgs << QByteArray("-TagsFromFile");
cmdArgs << d->filePathEncoding(exvTempFile);
cmdArgs << QByteArray("-all:all");
cmdArgs << d->filePathEncoding(fileInfo);
d->currentPath = fileInfo.path();
return (d->startProcess(cmdArgs, ExifToolProcess::APPLY_CHANGES_EXV));
}
bool ExifToolParser::readableFormats()
{
if (!d->prepareProcess())
......
......@@ -152,6 +152,12 @@ void ExifToolParser::slotCmdCompleted(int cmdAction,
break;
}
case ExifToolProcess::APPLY_CHANGES_EXV:
{
// TODO: check ExifTool feedback.
break;
}
case ExifToolProcess::READ_FORMATS:
{
// Remove first line
......
......@@ -52,6 +52,7 @@ public:
LOAD_METADATA = 0, ///< Load all metadata from a file with ExifTool.
LOAD_CHUNKS, ///< Load Exif, Iptc, and Xmp chunks from a file as bytearray for MetaEngine.
APPLY_CHANGES, ///< Apply tag changes in a file with ExifTool.
APPLY_CHANGES_EXV, ///< Apply tag changes in a file with ExifTool using an EXV constainer.
READ_FORMATS, ///< Return the list of readable ExifTool file formats.
WRITE_FORMATS, ///< Return the list of writable ExifTool file formats.
TRANSLATIONS_LIST, ///< List of ExifTool languages avaialble for translations.
......
#
# Copyright (c) 2015, by Veaceslav Munteanu, <veaceslav dot munteanu90 at gmail dot com>
# Copyright (c) 2010-2020, by Gilles Caulier, <caulier dot gilles at gmail dot com>
# Copyright (c) 2010-2021, by Gilles Caulier, <caulier dot gilles at gmail dot com>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
......@@ -42,3 +42,4 @@ EXIFTOOL_BUILD_CLITEST(exiftoolparserout_cli.cpp)
EXIFTOOL_BUILD_CLITEST(exiftoolwrite_cli.cpp)
EXIFTOOL_BUILD_CLITEST(exiftoolformats_cli.cpp)
EXIFTOOL_BUILD_CLITEST(exiftoollanguages_cli.cpp)
EXIFTOOL_BUILD_CLITEST(exiftoolapplychanges_cli.cpp)
/* ============================================================
*
* This file is a part of digiKam project
* https://www.digikam.org
*
* Date : 2013-11-28
* Description : a command line tool to write metadata with ExifTool and EXV constainer
*
* Copyright (C) 2012-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* ============================================================ */
// Qt includes
#include <QString>
#include <QCoreApplication>
#include <QDebug>
#include <QVariant>
// Local includes
#include "dmetadata.h"
#include "dpluginloader.h"
#include "metaengine.h"
#include "exiftoolparser.h"
using namespace Digikam;
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
if (argc != 2)
{
qDebug() << "exiftoolapplychanges_cli - CLI tool to write metadata with ExifTool in image using EXV constainer";
qDebug() << "Usage: <image to patch>";
return -1;
}
MetaEngine::initializeExiv2();
QFileInfo input(QString::fromUtf8(argv[1]));
DMetadata meta;
bool ret = meta.load(input.filePath());
if (!ret)
{
qWarning() << "Cannot load" << meta.getFilePath();
return -1;
}
meta.setImageDateTime(QDateTime::currentDateTime(), true);
QString exvPath = input.baseName() + QLatin1String("_changes.exv");
QStringList removedTags;
meta.exportChanges(exvPath, removedTags);
ExifToolParser* const parser = new ExifToolParser();
if (!parser->applyChanges(input.filePath(), exvPath))
{
qWarning() << "Cannot apply changes with ExifTool on" << input.filePath();
return -1;
}
return 0;
}
......@@ -44,7 +44,7 @@ int main(int argc, char** argv)
if (argc != 2)
{
qDebug() << "exiftoolwrite_cli - CLI tool to write metadata with ExifTool in image";
qDebug() << "Usage: <image to create>";
qDebug() << "Usage: <image to patch>";
return -1;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment