File indexing completed on 2025-01-05 03:53:10
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2012-03-15 0007 * Description : a tool to create panorama by fusion of several images. 0008 * 0009 * SPDX-FileCopyrightText: 2012-2016 by Benjamin Girault <benjamin dot girault at gmail dot com> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "preprocesstask.h" 0016 0017 // Qt includes 0018 0019 #include <QFileInfo> 0020 #include <QScopedPointer> 0021 0022 // KDE includes 0023 0024 #include <klocalizedstring.h> 0025 #include <ksharedconfig.h> 0026 #include <kconfiggroup.h> 0027 0028 // Local includes 0029 0030 #include "dbinarysearch.h" 0031 #include "digikam_debug.h" 0032 #include "drawdecoder.h" 0033 #include "dimg.h" 0034 #include "dimgloaderobserver.h" 0035 #include "drawdecoderwidget.h" 0036 #include "drawdecoding.h" 0037 0038 namespace DigikamGenericPanoramaPlugin 0039 { 0040 0041 class PanoObserver; 0042 0043 class Q_DECL_HIDDEN PreProcessTask::Private 0044 { 0045 public: 0046 0047 // cppcheck-suppress constParameter 0048 explicit Private(PanoramaPreprocessedUrls& urls, 0049 const QUrl& url) 0050 : fileUrl (url), 0051 preProcessedUrl(urls), 0052 observer (nullptr) 0053 { 0054 } 0055 0056 const QUrl fileUrl; 0057 PanoramaPreprocessedUrls& preProcessedUrl; 0058 PanoObserver* observer; 0059 }; 0060 0061 class Q_DECL_HIDDEN PanoObserver : public DImgLoaderObserver 0062 { 0063 public: 0064 0065 explicit PanoObserver(PreProcessTask* const p) 0066 : DImgLoaderObserver(), 0067 parent (p) 0068 { 0069 } 0070 0071 ~PanoObserver() override 0072 { 0073 } 0074 0075 bool continueQuery() override 0076 { 0077 return (!parent->isAbortedFlag); 0078 } 0079 0080 private: 0081 0082 PreProcessTask* const parent; 0083 }; 0084 0085 PreProcessTask::PreProcessTask(const QString& workDirPath, 0086 int id, 0087 PanoramaPreprocessedUrls& targetUrls, 0088 const QUrl& sourceUrl) 0089 : PanoTask(PANO_PREPROCESS_INPUT, workDirPath), 0090 id(id), 0091 d (new Private(targetUrls, sourceUrl)) 0092 { 0093 d->observer = new PanoObserver(this); 0094 } 0095 0096 PreProcessTask::~PreProcessTask() 0097 { 0098 } 0099 0100 void PreProcessTask::requestAbort() 0101 { 0102 PanoTask::requestAbort(); 0103 } 0104 0105 void PreProcessTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) 0106 { 0107 // check if its a RAW file. 0108 0109 if (DRawDecoder::isRawFile(d->fileUrl)) 0110 { 0111 d->preProcessedUrl.preprocessedUrl = tmpDir; 0112 0113 if (!convertRaw()) 0114 { 0115 successFlag = false; 0116 0117 return; 0118 } 0119 } 0120 else 0121 { 0122 // NOTE: in this case, preprocessed Url is the original file Url. 0123 0124 d->preProcessedUrl.preprocessedUrl = d->fileUrl; 0125 } 0126 0127 d->preProcessedUrl.previewUrl = tmpDir; 0128 0129 if (!computePreview(d->preProcessedUrl.preprocessedUrl)) 0130 { 0131 successFlag = false; 0132 0133 return; 0134 } 0135 0136 successFlag = true; 0137 } 0138 0139 bool PreProcessTask::computePreview(const QUrl& inUrl) 0140 { 0141 QUrl& outUrl = d->preProcessedUrl.previewUrl; 0142 0143 QFileInfo fi(inUrl.toLocalFile()); 0144 outUrl.setPath(outUrl.path() + fi.completeBaseName().replace(QLatin1Char('.'), QLatin1String("_")) 0145 + QLatin1String("-preview.jpg")); 0146 0147 DImg img; 0148 0149 if (img.load(inUrl.toLocalFile())) 0150 { 0151 DImg preview = img.smoothScale(1280, 1024, Qt::KeepAspectRatio); 0152 bool saved = preview.save(outUrl.toLocalFile(), DImg::JPEG); 0153 0154 // save exif information also to preview image for auto rotation 0155 0156 if (saved) 0157 { 0158 QScopedPointer<DMetadata> meta(new DMetadata); 0159 0160 if (meta->load(inUrl.toLocalFile())) 0161 { 0162 MetaEngine::ImageOrientation orientation = meta->getItemOrientation(); 0163 0164 if (meta->load(outUrl.toLocalFile())) 0165 { 0166 meta->setItemOrientation(orientation); 0167 meta->setItemDimensions(QSize(preview.width(), preview.height())); 0168 meta->applyChanges(true); 0169 } 0170 } 0171 } 0172 0173 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Preview Image url: " << outUrl << ", saved: " << saved; 0174 0175 return saved; 0176 } 0177 else 0178 { 0179 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Error during preview generation of: " << inUrl; 0180 errString = i18n("Input image cannot be loaded for preview generation."); 0181 } 0182 0183 return false; 0184 } 0185 0186 bool PreProcessTask::convertRaw() 0187 { 0188 const QUrl& inUrl = d->fileUrl; 0189 QUrl& outUrl = d->preProcessedUrl.preprocessedUrl; 0190 DImg img; 0191 0192 DRawDecoding settings; 0193 KSharedConfig::Ptr config = KSharedConfig::openConfig(); 0194 KConfigGroup group = config->group(QLatin1String("ImageViewer Settings")); 0195 DRawDecoderWidget::readSettings(settings.rawPrm, group); 0196 0197 if (img.load(inUrl.toLocalFile(), d->observer, settings)) 0198 { 0199 QFileInfo fi(inUrl.toLocalFile()); 0200 QDir outDir(outUrl.toLocalFile()); 0201 outDir.cdUp(); 0202 QString path = outDir.path() + QLatin1Char('/'); 0203 outUrl.setPath(path + fi.completeBaseName().replace(QLatin1Char('.'), QLatin1String("_")) 0204 + QLatin1String(".tif")); 0205 0206 if (!img.save(outUrl.toLocalFile(), QLatin1String("TIF"))) 0207 { 0208 errString = i18n("Tiff image creation failed."); 0209 0210 return false; 0211 } 0212 0213 QScopedPointer<DMetadata> meta(new DMetadata); 0214 0215 if (meta->load(outUrl.toLocalFile())) 0216 { 0217 DMetadata::MetaDataMap m = meta->getExifTagsDataList(QStringList() << QLatin1String("Photo")); 0218 0219 if (!m.isEmpty()) 0220 { 0221 for (DMetadata::MetaDataMap::iterator it = m.begin() ; it != m.end() ; ++it) 0222 { 0223 meta->removeExifTag(it.key().toLatin1().constData()); 0224 } 0225 } 0226 0227 meta->setItemDimensions(img.size()); 0228 meta->setExifTagString("Exif.Image.DocumentName", inUrl.fileName()); 0229 meta->setXmpTagString("Xmp.tiff.Make", meta->getExifTagString("Exif.Image.Make")); 0230 meta->setXmpTagString("Xmp.tiff.Model", meta->getExifTagString("Exif.Image.Model")); 0231 meta->setItemOrientation(DMetadata::ORIENTATION_NORMAL); 0232 meta->applyChanges(true); 0233 } 0234 } 0235 else 0236 { 0237 errString = i18n("Raw file conversion failed."); 0238 return false; 0239 } 0240 0241 qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Convert RAW output url: " << outUrl; 0242 0243 return true; 0244 } 0245 0246 } // namespace DigikamGenericPanoramaPlugin