File indexing completed on 2025-01-19 03:56:02

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2006-09-15
0007  * Description : Exiv2 library interface.
0008  *               Embedded preview loading.
0009  *
0010  * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  * SPDX-FileCopyrightText: 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 // Local includes
0018 
0019 #include "metaengine_previews.h"
0020 #include "metaengine_p.h"
0021 #include "digikam_debug.h"
0022 #include "digikam_config.h"
0023 
0024 #if defined(Q_CC_CLANG)
0025 #   pragma clang diagnostic push
0026 #   pragma clang diagnostic ignored "-Wdeprecated-declarations"
0027 #endif
0028 
0029 namespace Digikam
0030 {
0031 
0032 class Q_DECL_HIDDEN MetaEnginePreviews::Private
0033 {
0034 public:
0035 
0036     explicit Private()
0037         : manager(nullptr)
0038     {
0039     }
0040 
0041     ~Private()
0042     {
0043         delete manager;
0044     }
0045 
0046     void load(Exiv2::Image::AutoPtr image_)     // clazy:exclude=function-args-by-ref
0047     {
0048         QMutexLocker lock(&s_metaEngineMutex);
0049 
0050         try
0051         {
0052 
0053 #if EXIV2_TEST_VERSION(0,27,99)
0054 
0055             image                              = std::move(image_);
0056 
0057 #else
0058 
0059             image                              = image_;
0060 
0061 #endif
0062             image->readMetadata();
0063 
0064             manager                            = new Exiv2::PreviewManager(*image);
0065             Exiv2::PreviewPropertiesList props = manager->getPreviewProperties();
0066 
0067             // reverse order of list, which is smallest-first
0068 
0069             Exiv2::PreviewPropertiesList::reverse_iterator it;
0070 
0071             for (it = props.rbegin() ; it != props.rend() ; ++it)
0072             {
0073                 properties << *it;
0074             }
0075         }
0076         catch (Exiv2::AnyError& e)
0077         {
0078             MetaEngine::Private::printExiv2ExceptionError(QLatin1String("Cannot load preview data with Exiv2:"), e);
0079         }
0080         catch (...)
0081         {
0082             qCCritical(DIGIKAM_METAENGINE_LOG) << "Default exception from Exiv2";
0083         }
0084     }
0085 
0086 public:
0087 
0088     Exiv2::Image::AutoPtr           image;
0089     Exiv2::PreviewManager*          manager;
0090     QList<Exiv2::PreviewProperties> properties;
0091 };
0092 
0093 MetaEnginePreviews::MetaEnginePreviews(const QString& filePath)
0094     : d(new Private)
0095 {
0096     QMutexLocker lock(&s_metaEngineMutex);
0097 
0098     try
0099     {
0100 
0101 #if defined Q_OS_WIN && defined EXV_UNICODE_PATH
0102 
0103         Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((const wchar_t*)filePath.utf16());
0104 
0105 #elif defined Q_OS_WIN
0106 
0107         Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(QFile::encodeName(filePath).constData());
0108 
0109 #else
0110 
0111         Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filePath.toUtf8().constData());
0112 
0113 #endif
0114 
0115 #if EXIV2_TEST_VERSION(0,27,99)
0116 
0117         d->load(std::move(image));
0118 
0119 #else
0120 
0121         d->load(image);
0122 
0123 #endif
0124 
0125     }
0126     catch (Exiv2::AnyError& e)
0127     {
0128         MetaEngine::Private::printExiv2ExceptionError(QLatin1String("Cannot load metadata with Exiv2:"), e);
0129     }
0130     catch (...)
0131     {
0132         qCCritical(DIGIKAM_METAENGINE_LOG) << "Default exception from Exiv2";
0133     }
0134 }
0135 
0136 MetaEnginePreviews::MetaEnginePreviews(const QByteArray& imgData)
0137     : d(new Private)
0138 {
0139     QMutexLocker lock(&s_metaEngineMutex);
0140 
0141     try
0142     {
0143         Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((Exiv2::byte*)imgData.data(), imgData.size());
0144 
0145 #if EXIV2_TEST_VERSION(0,27,99)
0146 
0147         d->load(std::move(image));
0148 
0149 #else
0150 
0151         d->load(image);
0152 
0153 #endif
0154 
0155     }
0156     catch (Exiv2::AnyError& e)
0157     {
0158         MetaEngine::Private::printExiv2ExceptionError(QLatin1String("Cannot load metadata with Exiv2:"), e);
0159     }
0160     catch (...)
0161     {
0162         qCCritical(DIGIKAM_METAENGINE_LOG) << "Default exception from Exiv2";
0163     }
0164 }
0165 
0166 MetaEnginePreviews::~MetaEnginePreviews()
0167 {
0168     delete d;
0169 }
0170 
0171 bool MetaEnginePreviews::isEmpty()
0172 {
0173     return d->properties.isEmpty();
0174 }
0175 
0176 QSize MetaEnginePreviews::originalSize() const
0177 {
0178     if (d->image.get())
0179     {
0180         return QSize(d->image->pixelWidth(), d->image->pixelHeight());
0181     }
0182 
0183     return QSize();
0184 }
0185 
0186 QString MetaEnginePreviews::originalMimeType() const
0187 {
0188     if (d->image.get())
0189     {
0190        return QString::fromStdString(d->image->mimeType());
0191     }
0192 
0193     return QString();
0194 }
0195 
0196 int MetaEnginePreviews::count() const
0197 {
0198     return d->properties.size();
0199 }
0200 
0201 int MetaEnginePreviews::size() const
0202 {
0203     return count();
0204 }
0205 
0206 int MetaEnginePreviews::dataSize(int index)
0207 {
0208     if ((index < 0) || (index >= size()))
0209     {
0210         return 0;
0211     }
0212 
0213     return d->properties[index].size_;
0214 }
0215 
0216 int MetaEnginePreviews::width(int index)
0217 {
0218     if ((index < 0) || (index >= size()))
0219     {
0220         return 0;
0221     }
0222 
0223     return d->properties[index].width_;
0224 }
0225 
0226 int MetaEnginePreviews::height(int index)
0227 {
0228     if ((index < 0) || (index >= size()))
0229     {
0230         return 0;
0231     }
0232 
0233     return d->properties[index].height_;
0234 }
0235 
0236 QString MetaEnginePreviews::mimeType(int index)
0237 {
0238     if ((index < 0) || (index >= size()))
0239     {
0240         return QString();
0241     }
0242 
0243     return QString::fromStdString(d->properties[index].mimeType_);
0244 }
0245 
0246 QString MetaEnginePreviews::fileExtension(int index)
0247 {
0248     if ((index < 0) || (index >= size()))
0249     {
0250         return QString();
0251     }
0252 
0253     return QString::fromStdString(d->properties[index].extension_);
0254 }
0255 
0256 QByteArray MetaEnginePreviews::data(int index)
0257 {
0258     if ((index < 0) || (index >= size()))
0259     {
0260         return QByteArray();
0261     }
0262 
0263     qCDebug(DIGIKAM_METAENGINE_LOG) << "index     : " << index;
0264     qCDebug(DIGIKAM_METAENGINE_LOG) << "properties: " << count();
0265 
0266     QMutexLocker lock(&s_metaEngineMutex);
0267 
0268     try
0269     {
0270         Exiv2::PreviewImage image = d->manager->getPreviewImage(d->properties[index]);
0271 
0272         return QByteArray((const char*)image.pData(), image.size());
0273     }
0274     catch (Exiv2::AnyError& e)
0275     {
0276         MetaEngine::Private::printExiv2ExceptionError(QLatin1String("Cannot load metadata with Exiv2:"), e);
0277 
0278         return QByteArray();
0279     }
0280     catch (...)
0281     {
0282         qCCritical(DIGIKAM_METAENGINE_LOG) << "Default exception from Exiv2";
0283 
0284         return QByteArray();
0285     }
0286 }
0287 
0288 QImage MetaEnginePreviews::image(int index)
0289 {
0290     QByteArray previewData = data(index);
0291     QImage     image;
0292 
0293     if (previewData.isEmpty() || !image.loadFromData(previewData))
0294     {
0295         return QImage();
0296     }
0297 
0298     return image;
0299 }
0300 
0301 } // namespace Digikam
0302 
0303 #if defined(Q_CC_CLANG)
0304 #   pragma clang diagnostic pop
0305 #endif