File indexing completed on 2025-03-09 03:52:07

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2007-11-14
0007  * Description : a presentation tool.
0008  *
0009  * SPDX-FileCopyrightText: 2007-2009 by Valerio Fuoglio <valerio dot fuoglio at gmail dot com>
0010  * SPDX-FileCopyrightText: 2012-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * Parts of this code are based on smoothslidesaver by Carsten Weinhold
0013  * <carsten dot weinhold at gmx dot de>
0014  *
0015  * SPDX-License-Identifier: GPL-2.0-or-later
0016  *
0017  * ============================================================ */
0018 
0019 #include "kbimageloader.h"
0020 
0021 // Qt includes
0022 
0023 #include <QFileInfo>
0024 
0025 // Local includes
0026 
0027 #include "dimg.h"
0028 #include "iccmanager.h"
0029 #include "iccsettings.h"
0030 #include "digikam_debug.h"
0031 #include "presentationkb.h"
0032 #include "previewloadthread.h"
0033 #include "iccsettingscontainer.h"
0034 #include "presentationcontainer.h"
0035 
0036 using namespace Digikam;
0037 
0038 namespace DigikamGenericPresentationPlugin
0039 {
0040 
0041 class Q_DECL_HIDDEN KBImageLoader::Private
0042 {
0043 
0044 public:
0045 
0046     explicit Private()
0047       : sharedData      (nullptr),
0048         fileIndex       (0),
0049         width           (0),
0050         height          (0),
0051         initialized     (false),
0052         needImage       (true),
0053         haveImages      (false),
0054         quitRequested   (false),
0055         textureAspect   (0.0)
0056     {
0057     }
0058 
0059     PresentationContainer* sharedData;
0060     int                    fileIndex;
0061 
0062     int                    width;
0063     int                    height;
0064 
0065     QWaitCondition         imageRequest;
0066     QMutex                 condLock;
0067     QMutex                 imageLock;
0068 
0069     bool                   initialized;
0070     bool                   needImage;
0071     bool                   haveImages;
0072     bool                   quitRequested;
0073 
0074     float                  textureAspect;
0075     QImage                 texture;
0076 
0077     IccProfile             iccProfile;
0078 };
0079 
0080 KBImageLoader::KBImageLoader(PresentationContainer* const sharedData, int width, int height)
0081     : QThread(),
0082       d      (new Private)
0083 {
0084     d->sharedData = sharedData;
0085     d->width      = width;
0086     d->height     = height;
0087 
0088     ICCSettingsContainer settings = IccSettings::instance()->settings();
0089 
0090     if (settings.enableCM && settings.useManagedPreviews)
0091     {
0092         d->iccProfile = IccProfile(IccManager::displayProfile(d->sharedData->display));
0093     }
0094 }
0095 
0096 KBImageLoader::~KBImageLoader()
0097 {
0098     delete d;
0099 }
0100 
0101 void KBImageLoader::quit()
0102 {
0103     QMutexLocker locker(&d->condLock);
0104 
0105     d->quitRequested = true;
0106     d->imageRequest.wakeOne();
0107 }
0108 
0109 void KBImageLoader::requestNewImage()
0110 {
0111     QMutexLocker locker(&d->condLock);
0112 
0113     if (!d->needImage)
0114     {
0115         d->needImage = true;
0116         d->imageRequest.wakeOne();
0117     }
0118 }
0119 
0120 void KBImageLoader::run()
0121 {
0122     QMutexLocker locker(&d->condLock);
0123 
0124     // we enter the loop with d->needImage==true, so we will immediately
0125     // try to load an image
0126 
0127     while (true)
0128     {
0129         if (d->quitRequested)
0130         {
0131             break;
0132         }
0133 
0134         if (d->needImage)
0135         {
0136             if (d->fileIndex == (int)d->sharedData->urlList.count())
0137             {
0138                 if (d->sharedData->loop)
0139                 {
0140                     d->fileIndex = 0;
0141                 }
0142                 else
0143                 {
0144                     d->needImage  = false;
0145                     d->haveImages = false;
0146                     continue;
0147                 }
0148             }
0149 
0150             d->needImage = false;
0151             d->condLock.unlock();
0152             bool ok;
0153 
0154             do
0155             {
0156                 ok = loadImage();
0157 
0158                 if (!ok)
0159                 {
0160                     invalidateCurrentImageName();
0161                 }
0162             }
0163             while (!ok && (d->fileIndex < (int)d->sharedData->urlList.count()));
0164 
0165             if (d->fileIndex == (int)d->sharedData->urlList.count())
0166             {
0167                 d->condLock.lock();
0168                 continue;
0169             }
0170 
0171             if (!ok)
0172             {
0173                 // generate a black dummy image
0174 
0175                 d->texture = QImage(128, 128, QImage::Format_ARGB32);
0176                 d->texture.fill(Qt::black);
0177             }
0178 
0179             d->condLock.lock();
0180 
0181             d->fileIndex++;
0182 
0183             if (!d->initialized)
0184             {
0185                 d->haveImages  = ok;
0186                 d->initialized = true;
0187             }
0188         }
0189         else
0190         {
0191             // wait for new requests from the consumer
0192 
0193             d->imageRequest.wait(&d->condLock);
0194         }
0195     }
0196 }
0197 
0198 bool KBImageLoader::loadImage()
0199 {
0200     QString path  = d->sharedData->urlList[d->fileIndex].toLocalFile();
0201     QImage  image = PreviewLoadThread::loadHighQualitySynchronously(path,
0202                                                                     PreviewSettings::RawPreviewAutomatic,
0203                                                                     d->iccProfile).copyQImage();
0204 
0205     if (image.isNull())
0206     {
0207         return false;
0208     }
0209 
0210     d->imageLock.lock();
0211 
0212     d->textureAspect = (float)image.width() / (float)image.height();
0213     d->texture       = image.scaled(d->width, d->height,
0214                                     Qt::KeepAspectRatio, Qt::SmoothTransformation);
0215 
0216     d->imageLock.unlock();
0217 
0218     return true;
0219 }
0220 
0221 void KBImageLoader::invalidateCurrentImageName()
0222 {
0223     d->sharedData->urlList.removeAll(d->sharedData->urlList[d->fileIndex]);
0224     d->fileIndex++;
0225 }
0226 
0227 bool KBImageLoader::grabImage()
0228 {
0229     d->imageLock.lock();
0230 
0231     return d->haveImages;
0232 }
0233 
0234 void KBImageLoader::ungrabImage()
0235 {
0236     d->imageLock.unlock();
0237 }
0238 
0239 bool KBImageLoader::ready() const
0240 {
0241     return d->initialized;
0242 }
0243 
0244 const QImage& KBImageLoader::image() const
0245 {
0246     return d->texture;
0247 }
0248 
0249 float KBImageLoader::imageAspect() const
0250 {
0251     return d->textureAspect;
0252 }
0253 
0254 } // namespace DigikamGenericPresentationPlugin
0255 
0256 #include "moc_kbimageloader.cpp"