File indexing completed on 2025-01-05 03:56:23

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2006-02-23
0007  * Description : item metadata interface - file I/O helpers.
0008  *
0009  * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0011  * SPDX-FileCopyrightText: 2011      by Leif Huhn <leif at dkstat dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "dmetadata.h"
0018 
0019 // Qt includes
0020 
0021 #include <QString>
0022 #include <QFile>
0023 #include <QFileInfo>
0024 #include <QLocale>
0025 #include <QUuid>
0026 #include <QMimeDatabase>
0027 
0028 // Local includes
0029 
0030 #include "filereadwritelock.h"
0031 #include "metaenginesettings.h"
0032 #include "digikam_version.h"
0033 #include "digikam_globals.h"
0034 #include "digikam_debug.h"
0035 
0036 namespace Digikam
0037 {
0038 
0039 bool DMetadata::load(const QString& filePath, Backend* backend)
0040 {
0041     FileReadLocker lock(filePath);
0042 
0043     Backend usedBackend = NoBackend;
0044     bool hasLoaded      = false;
0045     QFileInfo info(filePath);
0046     QMimeDatabase mimeDB;
0047 
0048     if (
0049         !mimeDB.mimeTypeForFile(info).name().startsWith(QLatin1String("video/")) &&
0050         !mimeDB.mimeTypeForFile(info).name().startsWith(QLatin1String("audio/")) &&
0051         (info.suffix().toUpper() != QLatin1String("INSV"))                       &&
0052         (info.suffix().toUpper() != QLatin1String("H264"))
0053        )
0054     {
0055         // Process images only with Exiv2 backend first, or Exiftool in 2nd, or libraw for RAW files,
0056         // or with libheif, or at end with ImageMagick.
0057         // Never process video files with Exiv2, the backend is very unstable and this feature will be removed.
0058 
0059         if (!(hasLoaded = MetaEngine::load(filePath)))
0060         {
0061             if (!(hasLoaded = loadUsingExifTool(filePath)))
0062             {
0063                 if (!(hasLoaded = loadUsingRawEngine(filePath)))
0064                 {
0065 
0066                     if (!(hasLoaded =
0067 #ifdef HAVE_HEIF
0068                         loadUsingLibheif(filePath)
0069 #else
0070                         false
0071 #endif
0072                         ))
0073                     {
0074                         if (!(hasLoaded = false/*loadUsingImageMagick(filePath)*/))
0075                         {
0076                             usedBackend = NoBackend;
0077                         }
0078                         else
0079                         {
0080                             usedBackend = ImageMagickBackend;
0081                         }
0082                     }
0083                     else
0084                     {
0085                         usedBackend = LibHeifBackend;
0086                     }
0087                 }
0088                 else
0089                 {
0090                     usedBackend = LibRawBackend;
0091                 }
0092             }
0093             else
0094             {
0095                 usedBackend = ExifToolBackend;
0096             }
0097         }
0098         else
0099         {
0100             // Special case when Exiv2 has empty metadata container
0101             // but no loading error, give ExifTool a chance.
0102 
0103             if (isEmpty() && loadUsingExifTool(filePath))
0104             {
0105                 usedBackend = ExifToolBackend;
0106             }
0107             else
0108             {
0109                 usedBackend = Exiv2Backend;
0110             }
0111         }
0112     }
0113     else
0114     {
0115         // No image files (aka video or audio), process with ExifTool or ffmpeg backends.
0116 
0117         if (!(hasLoaded = loadUsingFFmpeg(filePath)))
0118         {
0119             if (!(hasLoaded = loadUsingExifTool(filePath)))
0120             {
0121                 usedBackend = NoBackend;
0122             }
0123             else
0124             {
0125                 usedBackend = ExifToolBackend;
0126             }
0127         }
0128         else
0129         {
0130             if (loadUsingExifTool(filePath, true))
0131             {
0132                 usedBackend = VideoMergeBackend;
0133             }
0134             else
0135             {
0136                 usedBackend = FFMpegBackend;
0137             }
0138         }
0139 
0140         hasLoaded |= loadFromSidecarAndMerge(filePath);
0141     }
0142 
0143     qCDebug(DIGIKAM_METAENGINE_LOG) << "Loading metadata with"
0144                                     << backendName(usedBackend)
0145                                     << "backend from" << filePath;
0146 
0147     if (backend)
0148     {
0149         *backend = usedBackend;
0150     }
0151 
0152     return hasLoaded;
0153 }
0154 
0155 bool DMetadata::save(const QString& filePath, bool setVersion) const
0156 {
0157     FileWriteLocker lock(filePath);
0158 
0159     return MetaEngine::save(filePath, setVersion);
0160 }
0161 
0162 bool DMetadata::applyChanges(bool setVersion) const
0163 {
0164     FileWriteLocker lock(getFilePath());
0165 
0166     return MetaEngine::applyChanges(setVersion);
0167 }
0168 
0169 } // namespace Digikam