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"