File indexing completed on 2024-05-05 04:22:00
0001 /* SPDX-FileCopyrightText: 2003-2020 The KPhotoAlbum Development Team 0002 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "ImageLoaderThread.h" 0007 0008 #include "AsyncLoader.h" 0009 #include "ImageDecoder.h" 0010 #include "ImageEvent.h" 0011 #include "RawImageDecoder.h" 0012 0013 #include <Utilities/FastJpeg.h> 0014 #include <Utilities/ImageUtil.h> 0015 #include <kpabase/Logging.h> 0016 #include <kpathumbnails/ThumbnailCache.h> 0017 0018 #include <QApplication> 0019 #include <QFileInfo> 0020 #include <QLoggingCategory> 0021 0022 #include <qmatrix.h> 0023 0024 namespace ImageManager 0025 { 0026 // Create a global instance. Its constructor will itself register it. 0027 RAWImageDecoder rawdecoder; 0028 } 0029 0030 ImageManager::ImageLoaderThread::ImageLoaderThread(size_t bufsize) 0031 : m_imageLoadBuffer(new char[bufsize]) 0032 , m_bufSize(bufsize) 0033 { 0034 } 0035 0036 ImageManager::ImageLoaderThread::~ImageLoaderThread() 0037 { 0038 delete[] m_imageLoadBuffer; 0039 } 0040 0041 void ImageManager::ImageLoaderThread::run() 0042 { 0043 while (true) { 0044 ImageRequest *request = AsyncLoader::instance()->next(); 0045 Q_ASSERT(request); 0046 if (request->isExitRequest()) { 0047 return; 0048 } 0049 bool ok; 0050 0051 QImage img = loadImage(request, ok); 0052 0053 if (ok) { 0054 img = scaleAndRotate(request, img); 0055 } 0056 0057 request->setLoadedOK(ok); 0058 ImageEvent *iew = new ImageEvent(request, img); 0059 QApplication::postEvent(AsyncLoader::instance(), iew); 0060 } 0061 } 0062 0063 QImage ImageManager::ImageLoaderThread::loadImage(ImageRequest *request, bool &ok) 0064 { 0065 int dim = calcLoadSize(request); 0066 QSize fullSize; 0067 0068 ok = false; 0069 if (!request->fileSystemFileName().exists()) 0070 return QImage(); 0071 0072 QImage img; 0073 if (Utilities::isJPEG(request->fileSystemFileName())) { 0074 ok = Utilities::loadJPEG(&img, request->fileSystemFileName(), &fullSize, dim, 0075 m_imageLoadBuffer, m_bufSize); 0076 if (ok == true) 0077 request->setFullSize(fullSize); 0078 } 0079 0080 else { 0081 // At first, we have to give our RAW decoders a try. If we allowed 0082 // QImage's load() method, it'd for example load a tiny thumbnail from 0083 // NEF files, which is not what we want. 0084 ok = ImageDecoder::decode(&img, request, &fullSize, dim); 0085 if (ok) 0086 request->setFullSize(img.size()); 0087 } 0088 0089 if (!ok) { 0090 // Now we can try QImage's stuff as a fallback... 0091 ok = img.load(request->fileSystemFileName().absolute()); 0092 if (ok) 0093 request->setFullSize(img.size()); 0094 } 0095 0096 return img; 0097 } 0098 0099 int ImageManager::ImageLoaderThread::calcLoadSize(ImageRequest *request) 0100 { 0101 return qMax(request->width(), request->height()); 0102 } 0103 0104 QImage ImageManager::ImageLoaderThread::scaleAndRotate(ImageRequest *request, QImage img) 0105 { 0106 if (request->angle() != 0 && !request->imageIsPreRotated()) { 0107 QTransform matrix; 0108 matrix.rotate(request->angle()); 0109 img = img.transformed(matrix); 0110 int angle = (request->angle() + 360) % 360; 0111 Q_ASSERT(angle >= 0 && angle <= 360); 0112 qCDebug(ImageManagerLog) << "Rotating image to" << angle << "degrees:" << request->fileSystemFileName().relative(); 0113 if (angle == 90 || angle == 270) 0114 request->setFullSize(QSize(request->fullSize().height(), request->fullSize().width())); 0115 } 0116 0117 // If we are looking for a scaled version, then scale 0118 if (shouldImageBeScale(img, request)) 0119 img = Utilities::scaleImage(img, request->size(), Qt::KeepAspectRatio); 0120 0121 return img; 0122 } 0123 0124 bool ImageManager::ImageLoaderThread::shouldImageBeScale(const QImage &img, ImageRequest *request) 0125 { 0126 // No size specified, meaning we want it full size. 0127 if (request->width() == -1) 0128 return false; 0129 0130 if (img.width() < request->width() && img.height() < request->height()) { 0131 // The image is smaller than the requets. 0132 return request->doUpScale(); 0133 } 0134 0135 return true; 0136 } 0137 // vi:expandtab:tabstop=4 shiftwidth=4: