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

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2019-09-18
0007  * Description : UFRaw raw import plugin.
0008  *
0009  * SPDX-FileCopyrightText: 2019-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  *
0011  * SPDX-License-Identifier: GPL-2.0-or-later
0012  *
0013  * ============================================================ */
0014 
0015 #include "rawimportufrawplugin.h"
0016 
0017 // Qt includes
0018 
0019 #include <QMessageBox>
0020 #include <QApplication>
0021 #include <QPointer>
0022 #include <QDebug>
0023 #include <QByteArray>
0024 #include <QFileInfo>
0025 #include <QTemporaryFile>
0026 
0027 // KDE includes
0028 
0029 #include <klocalizedstring.h>
0030 
0031 // Local includes
0032 
0033 #include "digikam_debug.h"
0034 #include "digikam_globals_p.h"      // For KF6::Ki18n deprecated
0035 #include "dimg.h"
0036 #include "filteraction.h"
0037 #include "dfileoperations.h"
0038 #include "loadingdescription.h"
0039 
0040 namespace DigikamRawImportUFRawPlugin
0041 {
0042 
0043 class Q_DECL_HIDDEN UFRawRawImportPlugin::Private
0044 {
0045 public:
0046 
0047     explicit Private()
0048       : ufraw(nullptr)
0049     {
0050     }
0051 
0052     QProcess*          ufraw;
0053     DImg               decoded;
0054     LoadingDescription props;
0055     QFileInfo          fileInfo;
0056     QString            tempName;
0057 };
0058 
0059 UFRawRawImportPlugin::UFRawRawImportPlugin(QObject* const parent)
0060     : DPluginRawImport(parent),
0061       d               (new Private)
0062 {
0063 }
0064 
0065 UFRawRawImportPlugin::~UFRawRawImportPlugin()
0066 {
0067     delete d;
0068 }
0069 
0070 QString UFRawRawImportPlugin::name() const
0071 {
0072     return QString::fromUtf8("Raw Import using UFRaw");
0073 }
0074 
0075 QString UFRawRawImportPlugin::iid() const
0076 {
0077     return QLatin1String(DPLUGIN_IID);
0078 }
0079 
0080 QIcon UFRawRawImportPlugin::icon() const
0081 {
0082     return QIcon::fromTheme(QLatin1String("image-x-adobe-dng"));
0083 }
0084 
0085 QString UFRawRawImportPlugin::description() const
0086 {
0087     return QString::fromUtf8("A RAW import plugin based on UFRaw");
0088 }
0089 
0090 QString UFRawRawImportPlugin::details() const
0091 {
0092     return QString::fromUtf8("<p>This RAW Import plugin use UFRaw tool to pre-process file in Image Editor.</p>"
0093                              "<p>See UFRaw web site for details: "
0094                              "<a href='http://ufraw.sourceforge.net/'>http://ufraw.sourceforge.net/</a></p>");  // krazy:exclude=insecurenet
0095 }
0096 
0097 QString UFRawRawImportPlugin::handbookSection() const
0098 {
0099     return QLatin1String("setup_application");
0100 }
0101 
0102 QString UFRawRawImportPlugin::handbookChapter() const
0103 {
0104     return QLatin1String("editor_settings");
0105 }
0106 
0107 QString UFRawRawImportPlugin::handbookReference() const
0108 {
0109     return QLatin1String("setup-raw");
0110 }
0111 
0112 QList<DPluginAuthor> UFRawRawImportPlugin::authors() const
0113 {
0114     return QList<DPluginAuthor>()
0115             << DPluginAuthor(QString::fromUtf8("Gilles Caulier"),
0116                              QString::fromUtf8("caulier dot gilles at gmail dot com"),
0117                              QString::fromUtf8("(C) 2019-2022"))
0118             ;
0119 }
0120 
0121 void UFRawRawImportPlugin::setup(QObject* const /*parent*/)
0122 {
0123     // Nothing to do
0124 }
0125 
0126 QString UFRawRawImportPlugin::getRawProgram() const
0127 {
0128     return DFileOperations::findExecutable(QLatin1String("ufraw"));
0129 }
0130 
0131 bool UFRawRawImportPlugin::run(const QString& filePath, const DRawDecoding& /*def*/)
0132 {
0133     d->fileInfo = QFileInfo(filePath);
0134     d->props    = LoadingDescription(d->fileInfo.filePath(), LoadingDescription::ConvertForEditor);
0135     d->decoded  = DImg();
0136 
0137     QTemporaryFile tempFile;
0138     tempFile.open();
0139     d->tempName = tempFile.fileName();
0140 
0141     d->ufraw    = new QProcess(this);
0142     d->ufraw->setProcessChannelMode(QProcess::MergedChannels);
0143     d->ufraw->setWorkingDirectory(d->fileInfo.path());
0144     d->ufraw->setProcessEnvironment(adjustedEnvironmentForAppImage());
0145 
0146     connect(d->ufraw, SIGNAL(errorOccurred(QProcess::ProcessError)),
0147             this, SLOT(slotErrorOccurred(QProcess::ProcessError)));
0148 
0149     connect(d->ufraw, SIGNAL(finished(int,QProcess::ExitStatus)),
0150             this, SLOT(slotProcessFinished(int,QProcess::ExitStatus)));
0151 
0152     connect(d->ufraw, SIGNAL(readyRead()),
0153             this, SLOT(slotProcessReadyRead()));
0154 
0155     // --------
0156 
0157     d->fileInfo = QFileInfo(filePath);
0158 
0159     d->ufraw->setProgram(getRawProgram());
0160     d->ufraw->setArguments(QStringList() << QLatin1String("--out-depth=16")   // 16 bits per color per pixels
0161                                          << QLatin1String("--out-type=png")   // PNG output (TIFF output generate multi-layers file)
0162                                          << QLatin1String("--overwrite")      // Overwrite target temporary file
0163                                          << QString::fromUtf8("--output=%1")
0164                                             .arg(d->tempName)                 // Output file
0165                                          << filePath);                        // Input file
0166 
0167     qCDebug(DIGIKAM_GENERAL_LOG) << "UFRaw arguments:" << d->ufraw->arguments();
0168 
0169     d->ufraw->start();
0170 
0171     return d->ufraw->waitForStarted(10000);
0172 }
0173 
0174 void UFRawRawImportPlugin::slotErrorOccurred(QProcess::ProcessError error)
0175 {
0176     switch (error)
0177     {
0178         case QProcess::FailedToStart:
0179         {
0180             qCDebug(DIGIKAM_GENERAL_LOG) << "UFRaw :: Process has failed to start";
0181             break;
0182         }
0183 
0184         case QProcess::Crashed:
0185         {
0186             qCDebug(DIGIKAM_GENERAL_LOG) << "UFRaw :: Process has crashed";
0187             break;
0188         }
0189 
0190         case QProcess::Timedout:
0191         {
0192             qCDebug(DIGIKAM_GENERAL_LOG) << "UFRaw :: Process time-out";
0193             break;
0194         }
0195 
0196         case QProcess::WriteError:
0197         {
0198             qCDebug(DIGIKAM_GENERAL_LOG) << "UFRaw :: Process write error";
0199             break;
0200         }
0201 
0202         case QProcess::ReadError:
0203         {
0204             qCDebug(DIGIKAM_GENERAL_LOG) << "UFRaw :: Process read error";
0205             break;
0206         }
0207 
0208         default:
0209         {
0210             qCDebug(DIGIKAM_GENERAL_LOG) << "UFRaw :: Process error unknown";
0211             break;
0212         }
0213     }
0214 }
0215 
0216 void UFRawRawImportPlugin::slotProcessFinished(int code, QProcess::ExitStatus status)
0217 {
0218     qCDebug(DIGIKAM_GENERAL_LOG) << "UFRaw :: return code:" << code << ":: Exit status:" << status;
0219 
0220     d->decoded = DImg(d->tempName);
0221     d->decoded.setAttribute(QLatin1String("isReadOnly"), true);
0222 
0223     if (d->decoded.isNull())
0224     {
0225         QString message = i18n("Error to import RAW image with UFRaw\nClose this dialog to load RAW image with native import tool");
0226         QMessageBox::information(nullptr, qApp->applicationName(), message);
0227 
0228         qCDebug(DIGIKAM_GENERAL_LOG) << "Decoded image is null! Load with Native tool...";
0229         qCDebug(DIGIKAM_GENERAL_LOG) << d->props.filePath;
0230 
0231         Q_EMIT signalLoadRaw(d->props);
0232     }
0233     else
0234     {
0235         qCDebug(DIGIKAM_GENERAL_LOG) << "Decoded image is not null...";
0236         qCDebug(DIGIKAM_GENERAL_LOG) << d->props.filePath;
0237         d->props = LoadingDescription(d->tempName, LoadingDescription::ConvertForEditor);
0238 
0239         FilterAction action(QLatin1String("ufraw:RawConverter"), 1, FilterAction::DocumentedHistory);
0240         action.setDisplayableName(QString::fromUtf8(I18N_NOOP("UFRaw Raw Conversion")));
0241         d->decoded.addFilterAction(action);
0242 
0243         Q_EMIT signalDecodedImage(d->props, d->decoded);
0244     }
0245 
0246     delete d->ufraw;
0247     d->ufraw = nullptr;
0248 
0249     QFile::remove(d->tempName);
0250 }
0251 
0252 void UFRawRawImportPlugin::slotProcessReadyRead()
0253 {
0254     QByteArray data   = d->ufraw->readAllStandardError();
0255     QStringList lines = QString::fromUtf8(data).split(QLatin1Char('\n'), QT_SKIP_EMPTY_PARTS);
0256 
0257     Q_FOREACH (const QString& one, lines)
0258     {
0259         qCDebug(DIGIKAM_GENERAL_LOG) << "UFRaw ::" << one;
0260     }
0261 }
0262 
0263 } // namespace DigikamRawImportUFRawPlugin
0264 
0265 #include "moc_rawimportufrawplugin.cpp"