diff --git a/core/dplugins/generic/tools/panorama/tasks/autocroptask.cpp b/core/dplugins/generic/tools/panorama/tasks/autocroptask.cpp index 34e4a97c8a..c3e411e1b1 100644 --- a/core/dplugins/generic/tools/panorama/tasks/autocroptask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/autocroptask.cpp @@ -1,73 +1,78 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "autocroptask.h" // Qt includes #include namespace DigikamGenericPanoramaPlugin { AutoCropTask::AutoCropTask(const QString& workDirPath, - const QUrl& autoOptimiserPtoUrl, QUrl& viewCropPtoUrl, - bool /*buildGPano*/, const QString& panoModifyPath) + const QUrl& autoOptimiserPtoUrl, + QUrl& viewCropPtoUrl, + bool /*buildGPano*/, + const QString& panoModifyPath) : CommandTask(PANO_AUTOCROP, workDirPath, panoModifyPath), autoOptimiserPtoUrl(autoOptimiserPtoUrl), - viewCropPtoUrl(viewCropPtoUrl)/*, - buildGPano(buildGPano),*/ + viewCropPtoUrl(viewCropPtoUrl) +/* , buildGPano(buildGPano) +*/ { } AutoCropTask::~AutoCropTask() { } void AutoCropTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { viewCropPtoUrl = tmpDir; viewCropPtoUrl.setPath(viewCropPtoUrl.path() + QLatin1String("view_crop_pano.pto")); QStringList args; args << QLatin1String("-c"); // Center the panorama args << QLatin1String("-s"); // Straighten the panorama args << QLatin1String("--canvas=AUTO"); // Automatic size args << QLatin1String("--crop=AUTO"); // Automatic crop args << QLatin1String("-o"); args << viewCropPtoUrl.toLocalFile(); args << autoOptimiserPtoUrl.toLocalFile(); runProcess(args); // PanoModify does not return an error code when something went wrong... + QFile ptoOutput(viewCropPtoUrl.toLocalFile()); + if (!ptoOutput.exists()) { successFlag = false; errString = getProcessError(); } printDebug(QLatin1String("pano_modify")); } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/autocroptask.h b/core/dplugins/generic/tools/panorama/tasks/autocroptask.h index 051737800c..e59c241077 100644 --- a/core/dplugins/generic/tools/panorama/tasks/autocroptask.h +++ b/core/dplugins/generic/tools/panorama/tasks/autocroptask.h @@ -1,58 +1,60 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2015 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_AUTO_CROP_TASK_H #define DIGIKAM_AUTO_CROP_TASK_H // Local includes #include "commandtask.h" namespace DigikamGenericPanoramaPlugin { class AutoCropTask : public CommandTask { public: explicit AutoCropTask(const QString& workDirPath, const QUrl& autoOptimiserPtoUrl, QUrl& viewCropPtoUrl, - bool buildGPano, + bool buildGPano, const QString& panoModifyPath); ~AutoCropTask(); protected: void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread* thread) override; private: const QUrl& autoOptimiserPtoUrl; QUrl& viewCropPtoUrl; -// const bool buildGPano; +/* + const bool buildGPano; +*/ }; } // namespace DigikamGenericPanoramaPlugin #endif // DIGIKAM_AUTO_CROP_TASK_H diff --git a/core/dplugins/generic/tools/panorama/tasks/commandtask.cpp b/core/dplugins/generic/tools/panorama/tasks/commandtask.cpp index 267c5578cc..89a2c85434 100644 --- a/core/dplugins/generic/tools/panorama/tasks/commandtask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/commandtask.cpp @@ -1,121 +1,138 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2015-06-07 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2015-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "commandtask.h" // Qt includes #include // KDE includes #include // Local includes #include "digikam_debug.h" #include "digikam_globals.h" namespace DigikamGenericPanoramaPlugin { CommandTask::CommandTask(PanoAction action, const QString& workDirPath, const QString& commandPath) : PanoTask(action, workDirPath), process(nullptr), commandPath(commandPath) { } CommandTask::~CommandTask() { } void CommandTask::requestAbort() { PanoTask::requestAbort(); if (!process.isNull()) + { process->kill(); + } } void CommandTask::runProcess(QStringList& args) { if (isAbortedFlag) + { return; + } process.reset(new QProcess()); process->setWorkingDirectory(tmpDir.toLocalFile()); process->setProcessChannelMode(QProcess::MergedChannels); QProcessEnvironment env = Digikam::adjustedEnvironmentForAppImage(); env.insert(QLatin1String("OMP_NUM_THREADS"), QString::number(QThread::idealThreadCount())); process->setProcessEnvironment(env); process->setProgram(commandPath); process->setArguments(args); process->start(); successFlag = process->waitForFinished(-1) && process->exitStatus() == QProcess::NormalExit; output = QString::fromLocal8Bit(process->readAll()); if (!successFlag) + { errString = getProcessError(); + } } QString CommandTask::getProgram() { if (process.isNull()) + { return QString(); + } return process->program(); } QString CommandTask::getCommandLine() { if (process.isNull()) + { return QString(); + } return (process->program() + QLatin1Char(' ') + process->arguments().join(QLatin1Char(' '))); } QString CommandTask::getProcessError() { if (isAbortedFlag) + { return i18n("Canceled"); + } if (process.isNull()) + { return QString(); + } - return (i18n("Cannot run %1:

%2

", + return ( + i18n("Cannot run %1:

%2

", getProgram(), - output.toHtmlEscaped().replace(QLatin1Char('\n'), QLatin1String("
")))); + output.toHtmlEscaped().replace(QLatin1Char('\n'), QLatin1String("
"))) + ); } void CommandTask::printDebug(const QString& binaryName) { qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << binaryName << "command line: " << getCommandLine(); - qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << binaryName << "output:" << endl << qPrintable(QLatin1String(" >>\t") + - output.replace(QLatin1Char('\n'), QLatin1String("\n >>\t"))); + qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << binaryName << "output:" << endl + << qPrintable(QLatin1String(" >>\t") + + output.replace(QLatin1Char('\n'), QLatin1String("\n >>\t"))); } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/compilemksteptask.h b/core/dplugins/generic/tools/panorama/tasks/compilemksteptask.h index d26c97a68c..d0f61d9a06 100644 --- a/core/dplugins/generic/tools/panorama/tasks/compilemksteptask.h +++ b/core/dplugins/generic/tools/panorama/tasks/compilemksteptask.h @@ -1,63 +1,63 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2015 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_COMPILE_MK_STEP_TASK_H #define DIGIKAM_COMPILE_MK_STEP_TASK_H // Local includes #include "commandtask.h" namespace DigikamGenericPanoramaPlugin { class CompileMKStepTask : public CommandTask { public: explicit CompileMKStepTask(const QString& workDirPath, int id, const QUrl& mkUrl, const QString& nonaPath, const QString& enblendPath, const QString& makePath, bool preview); ~CompileMKStepTask(); public: - const int id; + const int id; protected: - void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread *thread) override; + void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread* thread) override; private: const QUrl& mkUrl; const QString nonaPath; const QString enblendPath; }; } // namespace DigikamGenericPanoramaPlugin #endif // DIGIKAM_COMPILE_MK_STEP_TASK_H diff --git a/core/dplugins/generic/tools/panorama/tasks/compilemktask.cpp b/core/dplugins/generic/tools/panorama/tasks/compilemktask.cpp index 638d567fab..c9c7270b85 100644 --- a/core/dplugins/generic/tools/panorama/tasks/compilemktask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/compilemktask.cpp @@ -1,63 +1,68 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "compilemktask.h" // Local includes #include "digikam_debug.h" namespace DigikamGenericPanoramaPlugin { CompileMKTask::CompileMKTask(const QString& workDirPath, - const QUrl& mkUrl, const QUrl& /*panoUrl*/, - const QString& nonaPath, const QString& enblendPath, - const QString& makePath, bool preview) + const QUrl& mkUrl, + const QUrl& /*panoUrl*/, + const QString& nonaPath, + const QString& enblendPath, + const QString& makePath, + bool preview) : CommandTask(preview ? PANO_STITCHPREVIEW : PANO_STITCH, workDirPath, makePath), - /*panoUrl(&panoUrl),*/ +/* + panoUrl(&panoUrl), +*/ mkUrl(mkUrl), nonaPath(nonaPath), enblendPath(enblendPath) { } CompileMKTask::~CompileMKTask() { } void CompileMKTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { QStringList args; args << QLatin1String("-f"); args << mkUrl.toLocalFile(); args << QString::fromLatin1("ENBLEND='%1'").arg(enblendPath); args << QString::fromLatin1("NONA='%1'").arg(nonaPath); runProcess(args); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "make command line: " << getCommandLine(); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "make output:" << endl << output; } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/compilemktask.h b/core/dplugins/generic/tools/panorama/tasks/compilemktask.h index 6aef972657..5c69ee70fc 100644 --- a/core/dplugins/generic/tools/panorama/tasks/compilemktask.h +++ b/core/dplugins/generic/tools/panorama/tasks/compilemktask.h @@ -1,60 +1,62 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2015 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_COMPILE_MK_TASK_H #define DIGIKAM_COMPILE_MK_TASK_H // Local includes #include "commandtask.h" namespace DigikamGenericPanoramaPlugin { class CompileMKTask : public CommandTask { public: explicit CompileMKTask(const QString& workDirPath, const QUrl& mkUrl, const QUrl& panoUrl, const QString& nonaPath, const QString& enblendPath, const QString& makePath, bool preview); ~CompileMKTask(); protected: void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread* thread) override; private: -// const QUrl* const panoUrl; +/* + const QUrl* const panoUrl; +*/ const QUrl& mkUrl; const QString nonaPath; const QString enblendPath; }; } // namespace DigikamGenericPanoramaPlugin #endif // DIGIKAM_COMPILE_MK_TASK_H diff --git a/core/dplugins/generic/tools/panorama/tasks/copyfilestask.cpp b/core/dplugins/generic/tools/panorama/tasks/copyfilestask.cpp index f86e103e63..d1a1943c42 100644 --- a/core/dplugins/generic/tools/panorama/tasks/copyfilestask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/copyfilestask.cpp @@ -1,221 +1,231 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "copyfilestask.h" // Qt includes #include #include // KDE includes #include // Local includes #include "digikam_debug.h" #include "drawdecoder.h" #include "panomanager.h" namespace DigikamGenericPanoramaPlugin { -CopyFilesTask::CopyFilesTask(const QString& workDirPath, const QUrl& panoUrl, const QUrl& finalPanoUrl, - const QUrl& ptoUrl, const PanoramaItemUrlsMap& urls, bool sPTO, bool GPlusMetadata) +CopyFilesTask::CopyFilesTask(const QString& workDirPath, + const QUrl& panoUrl, + const QUrl& finalPanoUrl, + const QUrl& ptoUrl, + const PanoramaItemUrlsMap& urls, + bool sPTO, + bool GPlusMetadata) : PanoTask(PANO_COPY, workDirPath), panoUrl(panoUrl), finalPanoUrl(finalPanoUrl), ptoUrl(ptoUrl), urlList(&urls), savePTO(sPTO), addGPlusMetadata(GPlusMetadata) { } CopyFilesTask::~CopyFilesTask() { } void CopyFilesTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { QFile panoFile(panoUrl.toLocalFile()); QFile finalPanoFile(finalPanoUrl.toLocalFile()); QFileInfo fi(finalPanoUrl.toLocalFile()); QUrl finalPTOUrl = finalPanoUrl.adjusted(QUrl::RemoveFilename); finalPTOUrl.setPath(finalPTOUrl.path() + fi.completeBaseName() + QLatin1String(".pto")); QFile ptoFile(ptoUrl.toLocalFile()); QFile finalPTOFile(finalPTOUrl.toLocalFile()); if (!panoFile.exists()) { errString = i18n("Temporary panorama file does not exists."); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Temporary panorama file does not exists: " << panoUrl; successFlag = false; return; } if (finalPanoFile.exists()) { errString = i18n("A panorama file named %1 already exists.", finalPanoUrl.fileName()); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Final panorama file already exists: " << finalPanoUrl; successFlag = false; return; } if (savePTO && !ptoFile.exists()) { errString = i18n("Temporary project file does not exist."); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Temporary project file does not exists: " << ptoUrl; successFlag = false; return; } if (savePTO && finalPTOFile.exists()) { errString = i18n("A project file named %1 already exists.", finalPTOUrl.fileName()); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Final project file already exists: " << finalPTOUrl; successFlag = false; return; } qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Copying GPS info..."; // Find first src image which contain geolocation and save it to target pano file. double lat, lng, alt; for (PanoramaItemUrlsMap::const_iterator i = urlList->constBegin() ; i != urlList->constEnd() ; ++i) { qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << i.key(); m_meta.load(i.key().toLocalFile()); if (m_meta.getGPSInfo(alt, lat, lng)) { qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "GPS info found and saved in " << panoUrl; m_meta.load(panoUrl.toLocalFile()); m_meta.setGPSInfo(alt, lat, lng); m_meta.applyChanges(true); break; } } // Restore usual and common metadata from first shot. m_meta.load(urlList->constBegin().key().toLocalFile()); QByteArray iptc = m_meta.getIptc(); QByteArray xmp = m_meta.getXmp(); QString make = m_meta.getExifTagString("Exif.Image.Make"); QString model = m_meta.getExifTagString("Exif.Image.Model"); QDateTime dt = m_meta.getItemDateTime(); m_meta.load(panoUrl.toLocalFile()); m_meta.setIptc(iptc); m_meta.setXmp(xmp); m_meta.setXmpTagString("Xmp.tiff.Make", make); m_meta.setXmpTagString("Xmp.tiff.Model", model); m_meta.setImageDateTime(dt); QString filesList; for (PanoramaItemUrlsMap::const_iterator i = urlList->constBegin() ; i != urlList->constEnd() ; ++i) + { filesList.append(i.key().fileName() + QLatin1String(" ; ")); + } filesList.truncate(filesList.length()-3); m_meta.setXmpTagString("Xmp.digiKam.PanoramaInputFiles", filesList); // NOTE : See https://developers.google.com/photo-sphere/metadata/ for details + if (addGPlusMetadata) { qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Adding PhotoSphere metadata..."; m_meta.registerXmpNameSpace(QLatin1String("http://ns.google.com/photos/1.0/panorama/"), QLatin1String("GPano")); m_meta.setXmpTagString("Xmp.GPano.UsePanoramaViewer", QLatin1String("True")); m_meta.setXmpTagString("Xmp.GPano.StitchingSoftware", QLatin1String("Panorama digiKam tool with Hugin")); m_meta.setXmpTagString("Xmp.GPano.ProjectionType", QLatin1String("equirectangular")); } m_meta.applyChanges(true); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Copying panorama file..."; if (!panoFile.copy(finalPanoUrl.toLocalFile()) || !panoFile.remove()) { - errString = i18n("Cannot move panorama from %1 to %2.", - panoUrl.toLocalFile(), - finalPanoUrl.toLocalFile()); + errString = i18n("Cannot move panorama from %1 to %2.", + panoUrl.toLocalFile(), + finalPanoUrl.toLocalFile()); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Cannot move panorama: QFile error = " << panoFile.error(); successFlag = false; + return; } if (savePTO) { qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Copying project file..."; if (!ptoFile.copy(finalPTOUrl.toLocalFile())) { - errString = i18n("Cannot move project file from %1 to %2.", - panoUrl.toLocalFile(), - finalPanoUrl.toLocalFile()); + errString = i18n("Cannot move project file from %1 to %2.", + panoUrl.toLocalFile(), + finalPanoUrl.toLocalFile()); successFlag = false; + return; } qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Copying converted RAW files..."; for (PanoramaItemUrlsMap::const_iterator i = urlList->constBegin() ; i != urlList->constEnd() ; ++i) { if (DRawDecoder::isRawFile(i.key())) { QUrl finalImgUrl = finalPanoUrl.adjusted(QUrl::RemoveFilename); finalImgUrl.setPath(finalImgUrl.path() + i->preprocessedUrl.fileName()); QFile finalImgFile(finalImgUrl.toLocalFile()); QFile imgFile(i->preprocessedUrl.toLocalFile()); if (finalImgFile.exists()) { continue; } if (!imgFile.copy(finalImgUrl.toLocalFile())) { - errString = i18n("Cannot copy converted image file from %1 to %2.", - i->preprocessedUrl.toLocalFile(), - finalImgUrl.toLocalFile()); + errString = i18n("Cannot copy converted image file from %1 to %2.", + i->preprocessedUrl.toLocalFile(), + finalImgUrl.toLocalFile()); successFlag = false; + return; } } } } emit PanoManager::instance()->updateHostApp(finalPanoUrl); successFlag = true; - return; } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/copyfilestask.h b/core/dplugins/generic/tools/panorama/tasks/copyfilestask.h index d364bffe84..85c41e5945 100644 --- a/core/dplugins/generic/tools/panorama/tasks/copyfilestask.h +++ b/core/dplugins/generic/tools/panorama/tasks/copyfilestask.h @@ -1,71 +1,71 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2015 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_COPY_FILES_TASK_H #define DIGIKAM_COPY_FILES_TASK_H // Qt includes #include // Local includes #include "panotask.h" #include "dmetadata.h" using namespace Digikam; namespace DigikamGenericPanoramaPlugin { class CopyFilesTask : public PanoTask { public: explicit CopyFilesTask(const QString& workDirPath, const QUrl& panoUrl, const QUrl& finalPanoUrl, const QUrl& ptoUrl, const PanoramaItemUrlsMap& urls, bool sPTO, bool GPlusMetadata); ~CopyFilesTask(); protected: - void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread *thread) override; + void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread* thread) override; private: const QUrl& panoUrl; const QUrl finalPanoUrl; const QUrl& ptoUrl; const PanoramaItemUrlsMap* const urlList; const bool savePTO; const bool addGPlusMetadata; DMetadata m_meta; }; } // namespace DigikamGenericPanoramaPlugin #endif // DIGIKAM_COPY_FILES_TASK_H diff --git a/core/dplugins/generic/tools/panorama/tasks/cpcleantask.cpp b/core/dplugins/generic/tools/panorama/tasks/cpcleantask.cpp index 2d5c1afa3e..bc73cc0dab 100644 --- a/core/dplugins/generic/tools/panorama/tasks/cpcleantask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/cpcleantask.cpp @@ -1,67 +1,69 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "cpcleantask.h" // Qt includes #include namespace DigikamGenericPanoramaPlugin { CpCleanTask::CpCleanTask(const QString& workDirPath, const QUrl& input, QUrl& cpCleanPtoUrl, const QString& cpCleanPath) : CommandTask(PANO_CPCLEAN, workDirPath, cpCleanPath), cpCleanPtoUrl(cpCleanPtoUrl), cpFindPtoUrl(input) { } CpCleanTask::~CpCleanTask() { } void CpCleanTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { cpCleanPtoUrl = tmpDir; cpCleanPtoUrl.setPath(cpCleanPtoUrl.path()+ QLatin1String("cp_pano_clean.pto")); QStringList args; args << QLatin1String("-o"); args << cpCleanPtoUrl.toLocalFile(); args << cpFindPtoUrl.toLocalFile(); runProcess(args); // CPClean does not return an error code when something went wrong... + QFile ptoOutput(cpCleanPtoUrl.toLocalFile()); + if (!ptoOutput.exists()) { successFlag = false; - errString = getProcessError(); + errString = getProcessError(); } printDebug(QLatin1String("cpclean")); } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/cpfindtask.cpp b/core/dplugins/generic/tools/panorama/tasks/cpfindtask.cpp index 8a46ad170a..bd64402d34 100644 --- a/core/dplugins/generic/tools/panorama/tasks/cpfindtask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/cpfindtask.cpp @@ -1,71 +1,81 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "cpfindtask.h" // Qt includes #include namespace DigikamGenericPanoramaPlugin { -CpFindTask::CpFindTask(const QString& workDirPath, const QUrl& input, - QUrl& cpFindUrl, bool celeste, const QString& cpFindPath) +CpFindTask::CpFindTask(const QString& workDirPath, + const QUrl& input, + QUrl& cpFindUrl, + bool celeste, + const QString& cpFindPath) : CommandTask(PANO_CPFIND, workDirPath, cpFindPath), cpFindPtoUrl(cpFindUrl), celeste(celeste), ptoUrl(input) { } CpFindTask::~CpFindTask() { } void CpFindTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { // Run CPFind to get control points and order the images + cpFindPtoUrl = tmpDir; cpFindPtoUrl.setPath(cpFindPtoUrl.path() + QLatin1String("cp_pano.pto")); QStringList args; + if (celeste) + { args << QLatin1String("--celeste"); + } + args << QLatin1String("-o"); args << cpFindPtoUrl.toLocalFile(); args << ptoUrl.toLocalFile(); runProcess(args); // CPFind does not return an error code when something went wrong... + QFile ptoOutput(cpFindPtoUrl.toLocalFile()); + if (!ptoOutput.exists()) { successFlag = false; - errString = getProcessError(); + errString = getProcessError(); } printDebug(QLatin1String("cpfind")); } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/createfinalptotask.cpp b/core/dplugins/generic/tools/panorama/tasks/createfinalptotask.cpp index 1f043b77b6..a982abd416 100644 --- a/core/dplugins/generic/tools/panorama/tasks/createfinalptotask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/createfinalptotask.cpp @@ -1,78 +1,81 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-12-05 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "createfinalptotask.h" // Qt includes #include // KDE includes #include namespace DigikamGenericPanoramaPlugin { -CreateFinalPtoTask::CreateFinalPtoTask(const QString& workDirPath, QSharedPointer ptoData, QUrl& finalPtoUrl, const QRect& crop) +CreateFinalPtoTask::CreateFinalPtoTask(const QString& workDirPath, + QSharedPointer ptoData, + QUrl& finalPtoUrl, + const QRect& crop) : PanoTask(PANO_CREATEFINALPTO, workDirPath), ptoData(*ptoData), finalPtoUrl(finalPtoUrl), crop(crop) { } CreateFinalPtoTask::~CreateFinalPtoTask() { } void CreateFinalPtoTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { finalPtoUrl = tmpDir; finalPtoUrl.setPath(finalPtoUrl.path() + QLatin1String("final.pto")); QFile pto(finalPtoUrl.toLocalFile()); if (pto.exists()) { errString = i18n("PTO file already created in the temporary directory."); successFlag = false; return; } if (!pto.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { errString = i18n("PTO file cannot be created in the temporary directory."); successFlag = false; return; } pto.close(); ptoData.project.crop = crop; ptoData.createFile(finalPtoUrl.toLocalFile()); successFlag = true; return; } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/createmktask.cpp b/core/dplugins/generic/tools/panorama/tasks/createmktask.cpp index ab23a09a15..842ea087c0 100644 --- a/core/dplugins/generic/tools/panorama/tasks/createmktask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/createmktask.cpp @@ -1,85 +1,87 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "createmktask.h" // Qt includes #include // Local includes #include "digikam_debug.h" namespace DigikamGenericPanoramaPlugin { CreateMKTask::CreateMKTask(const QString& workDirPath, const QUrl& input, QUrl& mkUrl, QUrl& panoUrl, PanoramaFileType fileType, const QString& pto2mkPath, bool preview) : CommandTask(preview ? PANO_CREATEMKPREVIEW : PANO_CREATEMK, workDirPath, pto2mkPath), ptoUrl(input), mkUrl(mkUrl), panoUrl(panoUrl), fileType(fileType) { } CreateMKTask::~CreateMKTask() { } void CreateMKTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { panoUrl = tmpDir; mkUrl = tmpDir; QFileInfo fi(ptoUrl.toLocalFile()); mkUrl.setPath(mkUrl.path() + fi.completeBaseName() + QLatin1String(".mk")); switch (fileType) { case JPEG: panoUrl.setPath(panoUrl.path() + fi.completeBaseName() + QLatin1String(".jpg")); break; + case TIFF: panoUrl.setPath(panoUrl.path() + fi.completeBaseName() + QLatin1String(".tif")); break; + case HDR: panoUrl.setPath(panoUrl.path() + fi.completeBaseName() + QLatin1String(".hdr")); break; } QStringList args; args << QLatin1String("-o"); args << mkUrl.toLocalFile(); args << QLatin1String("-p"); args << fi.completeBaseName(); args << ptoUrl.toLocalFile(); runProcess(args); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "pto2mk command line: " << getCommandLine(); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "pto2mk output:" << endl << output; } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/createmktask.h b/core/dplugins/generic/tools/panorama/tasks/createmktask.h index 6ebd491c6c..86f480eeb8 100644 --- a/core/dplugins/generic/tools/panorama/tasks/createmktask.h +++ b/core/dplugins/generic/tools/panorama/tasks/createmktask.h @@ -1,60 +1,60 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2015 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_CREATE_MK_TASK_H #define DIGIKAM_CREATE_MK_TASK_H // Local includes #include "commandtask.h" namespace DigikamGenericPanoramaPlugin { class CreateMKTask : public CommandTask { public: explicit CreateMKTask(const QString& workDirPath, const QUrl& input, QUrl& mkUrl, QUrl& panoUrl, PanoramaFileType fileType, const QString& pto2mkPath, bool preview); ~CreateMKTask(); protected: - void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread *thread) override; + void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread* thread) override; private: const QUrl& ptoUrl; QUrl& mkUrl; QUrl& panoUrl; const PanoramaFileType fileType; }; } // namespace DigikamGenericPanoramaPlugin #endif // DIGIKAM_CREATE_MK_TASK_H diff --git a/core/dplugins/generic/tools/panorama/tasks/createpreviewtask.cpp b/core/dplugins/generic/tools/panorama/tasks/createpreviewtask.cpp index f2deb8e5b0..913012db6f 100644 --- a/core/dplugins/generic/tools/panorama/tasks/createpreviewtask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/createpreviewtask.cpp @@ -1,120 +1,127 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "createpreviewtask.h" // Qt includes #include // KDE includes #include // Local includes #include "digikam_debug.h" namespace DigikamGenericPanoramaPlugin { -CreatePreviewTask::CreatePreviewTask(const QString& workDirPath, QSharedPointer inputPTO, - QUrl& previewPtoUrl, const PanoramaItemUrlsMap& preProcessedUrlsMap) +CreatePreviewTask::CreatePreviewTask(const QString& workDirPath, + QSharedPointer inputPTO, + QUrl& previewPtoUrl, + const PanoramaItemUrlsMap& preProcessedUrlsMap) : PanoTask(PANO_CREATEMKPREVIEW, workDirPath), previewPtoUrl(previewPtoUrl), ptoData(inputPTO), preProcessedUrlsMap(preProcessedUrlsMap) { } CreatePreviewTask::~CreatePreviewTask() { } void CreatePreviewTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { PTOType data(*ptoData); if (data.images.size() != preProcessedUrlsMap.size()) { - errString = i18n("Project file parsing failed."); + errString = i18n("Project file parsing failed."); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Missing parsing data!"; successFlag = false; return; } m_meta.load(preProcessedUrlsMap.begin().value().preprocessedUrl.toLocalFile()); - double wIn = (double)m_meta.getPixelSize().width(); + double wIn = (double)m_meta.getPixelSize().width(); m_meta.load(preProcessedUrlsMap.begin().value().previewUrl.toLocalFile()); - double wOut = (double)m_meta.getPixelSize().width(); + double wOut = (double)m_meta.getPixelSize().width(); - double scalingFactor = wOut / wIn; + double scalingFactor = wOut / wIn; data.project.fileFormat.fileType = PTOType::Project::FileFormat::JPEG; data.project.fileFormat.quality = 90; data.project.size.setHeight(data.project.size.height() * scalingFactor); data.project.size.setWidth(data.project.size.width() * scalingFactor); data.project.crop = QRect(); for (auto& image : data.images) { - QUrl imgUrl = QUrl::fromLocalFile(image.fileName); + QUrl imgUrl = QUrl::fromLocalFile(image.fileName); PanoramaItemUrlsMap::const_iterator it; const PanoramaItemUrlsMap* const ppum = &preProcessedUrlsMap; - for (it = ppum->constBegin(); it != ppum->constEnd() && it.value().preprocessedUrl.toLocalFile() != imgUrl.toLocalFile(); ++it); + for (it = ppum->constBegin() ; + it != ppum->constEnd() && (it.value().preprocessedUrl.toLocalFile() != imgUrl.toLocalFile()) ; + ++it); if (it == ppum->constEnd()) { - errString = i18n("Unknown input file in the project file: %1", image.fileName); + errString = i18n("Unknown input file in the project file: %1", image.fileName); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Unknown input File in the PTO: " << image.fileName; qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "IMG: " << imgUrl.toLocalFile(); successFlag = false; + return; } image.fileName = it.value().previewUrl.toLocalFile(); m_meta.load(image.fileName); image.size = m_meta.getPixelSize(); image.optimizationParameters.clear(); } // Remove unnecessary stuff + data.controlPoints.clear(); // Add two commented line for a JPEG output + data.lastComments.clear(); data.lastComments << QLatin1String("#hugin_outputImageType jpg"); data.lastComments << QLatin1String("#hugin_outputJPEGQuality 90"); previewPtoUrl = tmpDir; previewPtoUrl.setPath(previewPtoUrl.path() + QLatin1String("preview.pto")); data.createFile(previewPtoUrl.toLocalFile()); qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Preview PTO File created: " << previewPtoUrl.fileName(); successFlag = true; } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/createpreviewtask.h b/core/dplugins/generic/tools/panorama/tasks/createpreviewtask.h index 1c974052c2..2bb867d869 100644 --- a/core/dplugins/generic/tools/panorama/tasks/createpreviewtask.h +++ b/core/dplugins/generic/tools/panorama/tasks/createpreviewtask.h @@ -1,65 +1,65 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2015 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_CREATE_PREVIEW_TASK_H #define DIGIKAM_CREATE_PREVIEW_TASK_H // Qt includes #include // Local includes #include "panotask.h" #include "ptotype.h" #include "metaengine.h" using namespace Digikam; namespace DigikamGenericPanoramaPlugin { class CreatePreviewTask : public PanoTask { public: explicit CreatePreviewTask(const QString& workDirPath, QSharedPointer inputPTO, QUrl& previewPtoUrl, const PanoramaItemUrlsMap& preProcessedUrlsMap); ~CreatePreviewTask(); protected: - void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread *thread) override; + void run(ThreadWeaver::JobPointer self, ThreadWeaver::Thread* thread) override; private: QUrl& previewPtoUrl; QSharedPointer ptoData; const PanoramaItemUrlsMap preProcessedUrlsMap; MetaEngine m_meta; }; } // namespace DigikamGenericPanoramaPlugin #endif // DIGIKAM_CREATE_PREVIEW_TASK_H diff --git a/core/dplugins/generic/tools/panorama/tasks/createptotask.cpp b/core/dplugins/generic/tools/panorama/tasks/createptotask.cpp index 648a49423b..8befd7b007 100644 --- a/core/dplugins/generic/tools/panorama/tasks/createptotask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/createptotask.cpp @@ -1,223 +1,236 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "createptotask.h" #include "ptotype.h" // Qt includes #include // KDE includes #include namespace DigikamGenericPanoramaPlugin { -CreatePtoTask::CreatePtoTask(const QString& workDirPath, PanoramaFileType fileType, - QUrl& ptoUrl, const QList& inputFiles, const PanoramaItemUrlsMap& preProcessedMap, - bool addGPlusMetadata, const QString& huginVersion) +CreatePtoTask::CreatePtoTask(const QString& workDirPath, + PanoramaFileType fileType, + QUrl& ptoUrl, + const QList& inputFiles, + const PanoramaItemUrlsMap& preProcessedMap, + bool addGPlusMetadata, + const QString& huginVersion) : PanoTask(PANO_CREATEPTO, workDirPath), ptoUrl(ptoUrl), preProcessedMap(&preProcessedMap), fileType(addGPlusMetadata ? JPEG : fileType), inputFiles(inputFiles), addGPlusMetadata(addGPlusMetadata), huginVersion(huginVersion) { } CreatePtoTask::~CreatePtoTask() { } void CreatePtoTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { ptoUrl = tmpDir; ptoUrl.setPath(ptoUrl.path() + QLatin1String("pano_base.pto")); QFile pto(ptoUrl.toLocalFile()); if (pto.exists()) { - errString = i18n("PTO file already created in the temporary directory."); + errString = i18n("PTO file already created in the temporary directory."); successFlag = false; + return; } if (!pto.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { errString = i18n("PTO file cannot be created in the temporary directory."); successFlag = false; + return; } pto.close(); // 1. Project parameters + PTOType panoBase(huginVersion); if (addGPlusMetadata) { panoBase.project.projection = PTOType::Project::EQUIRECTANGULAR; } else { panoBase.project.projection = PTOType::Project::CYLINDRICAL; } panoBase.project.fieldOfView = 0; panoBase.project.hdr = false; switch (fileType) { case JPEG: panoBase.project.fileFormat.fileType = PTOType::Project::FileFormat::JPEG; panoBase.project.fileFormat.quality = 90; break; + case TIFF: panoBase.project.fileFormat.fileType = PTOType::Project::FileFormat::TIFF_m; panoBase.project.fileFormat.compressionMethod = PTOType::Project::FileFormat::LZW; panoBase.project.fileFormat.savePositions = false; panoBase.project.fileFormat.cropped = false; break; + case HDR: panoBase.project.hdr = true; // TODO HDR break; } - -// panoBase.project.bitDepth = PTOType::Project::FLOAT; -// panoBase.project.crop.setLeft(X_left); -// panoBase.project.crop.setRight(X_right); -// panoBase.project.crop.setTop(X_top); -// panoBase.project.crop.setBottom(X_bottom); +/* + panoBase.project.bitDepth = PTOType::Project::FLOAT; + panoBase.project.crop.setLeft(X_left); + panoBase.project.crop.setRight(X_right); + panoBase.project.crop.setTop(X_top); + panoBase.project.crop.setBottom(X_bottom); +*/ panoBase.project.photometricReferenceId = 0; // 2. Images + panoBase.images.reserve(inputFiles.size()); panoBase.images.resize(inputFiles.size()); int i = 0; - for (i = 0; i < inputFiles.size(); ++i) + for (i = 0 ; i < inputFiles.size() ; ++i) { QUrl inputFile(inputFiles.at(i)); QUrl preprocessedUrl(preProcessedMap->value(inputFile).preprocessedUrl); m_meta.load(preprocessedUrl.toLocalFile()); - QSize size = m_meta.getPixelSize(); + QSize size = m_meta.getPixelSize(); panoBase.images[i] = PTOType::Image(); panoBase.images[i].lensProjection = PTOType::Image::RECTILINEAR; panoBase.images[i].size = size; if (i > 0) { // We suppose that the pictures are all taken with the same camera and lens + panoBase.images[i].lensBarrelCoefficientA.referenceId = 0; panoBase.images[i].lensBarrelCoefficientB.referenceId = 0; panoBase.images[i].lensBarrelCoefficientC.referenceId = 0; panoBase.images[i].lensCenterOffsetX.referenceId = 0; panoBase.images[i].lensCenterOffsetY.referenceId = 0; panoBase.images[i].lensShearX.referenceId = 0; panoBase.images[i].lensShearY.referenceId = 0; panoBase.images[i].vignettingCorrectionI.referenceId = 0; panoBase.images[i].vignettingCorrectionJ.referenceId = 0; panoBase.images[i].vignettingCorrectionK.referenceId = 0; panoBase.images[i].vignettingCorrectionL.referenceId = 0; panoBase.images[i].vignettingOffsetX.referenceId = 0; panoBase.images[i].vignettingOffsetY.referenceId = 0; } else { panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSA; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSB; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSC; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSD; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSE; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VA; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VB; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VC; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VD; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VX; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VY; } panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::RA; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::RB; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::RC; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::RD; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::RE; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::EXPOSURE; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::WBR; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::WBB; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSYAW; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSPITCH; panoBase.images[i].optimizationParameters.append(PTOType::Optimization()); panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSROLL; panoBase.images[i].fileName = preprocessedUrl.toLocalFile(); } switch (fileType) { case TIFF: panoBase.lastComments << QLatin1String("#hugin_outputImageType tif"); panoBase.lastComments << QLatin1String("#hugin_outputImageTypeCompression LZW"); break; + case JPEG: panoBase.lastComments << QLatin1String("#hugin_outputImageType jpg"); panoBase.lastComments << QLatin1String("#hugin_outputJPEGQuality 90"); break; + case HDR: // TODO: HDR break; } panoBase.createFile(ptoUrl.toLocalFile()); successFlag = true; - return; } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/huginexecutortask.cpp b/core/dplugins/generic/tools/panorama/tasks/huginexecutortask.cpp index c77dd0e3cc..7f432981dc 100644 --- a/core/dplugins/generic/tools/panorama/tasks/huginexecutortask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/huginexecutortask.cpp @@ -1,85 +1,91 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2015-11-04 * Description : interface to hugin_executor * * Copyright (C) 2015-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "huginexecutortask.h" // Qt includes #include #include namespace DigikamGenericPanoramaPlugin { -HuginExecutorTask::HuginExecutorTask(const QString& workDirPath, const QUrl& input, - QUrl& panoUrl, PanoramaFileType fileType, - const QString& huginExecutorPath, bool preview) +HuginExecutorTask::HuginExecutorTask(const QString& workDirPath, + const QUrl& input, + QUrl& panoUrl, + PanoramaFileType fileType, + const QString& huginExecutorPath, + bool preview) : CommandTask(preview ? PANO_HUGINEXECUTORPREVIEW : PANO_HUGINEXECUTOR, workDirPath, huginExecutorPath), ptoUrl(input), panoUrl(panoUrl), fileType(fileType) { } HuginExecutorTask::~HuginExecutorTask() { } void HuginExecutorTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { panoUrl = tmpDir; QFileInfo fi(ptoUrl.toLocalFile()); switch (fileType) { case JPEG: panoUrl.setPath(panoUrl.path() + fi.completeBaseName() + QLatin1String(".jpg")); break; + case TIFF: panoUrl.setPath(panoUrl.path() + fi.completeBaseName() + QLatin1String(".tif")); break; + case HDR: panoUrl.setPath(panoUrl.path() + fi.completeBaseName() + QLatin1String(".hdr")); break; } QStringList args; args << QLatin1String("-s"); args << QLatin1String("-p"); args << fi.completeBaseName(); args << ptoUrl.toLocalFile(); runProcess(args); // HuginExecutor does not return an error code when something went wrong... + QFile panoOutput(panoUrl.toLocalFile()); if (!panoOutput.exists()) { successFlag = false; errString = getProcessError(); } printDebug(QLatin1String("hugin_executor")); } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/panotask.cpp b/core/dplugins/generic/tools/panorama/tasks/panotask.cpp index 3dedebe998..f46da00bef 100644 --- a/core/dplugins/generic/tools/panorama/tasks/panotask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/panotask.cpp @@ -1,54 +1,55 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "panotask.h" // Qt includes #include namespace DigikamGenericPanoramaPlugin { -PanoTask::PanoTask(PanoAction action, const QString& workDirPath) +PanoTask::PanoTask(PanoAction action, + const QString& workDirPath) : action(action), isAbortedFlag(false), successFlag(false), tmpDir(QUrl::fromLocalFile(workDirPath + QLatin1Char('/'))) { } PanoTask::~PanoTask() { } bool PanoTask::success() const { return successFlag; } void PanoTask::requestAbort() { isAbortedFlag = true; } } // namespace DigikamGenericPanoramaPlugin diff --git a/core/dplugins/generic/tools/panorama/tasks/preprocesstask.cpp b/core/dplugins/generic/tools/panorama/tasks/preprocesstask.cpp index ffe127740f..89317c4a87 100644 --- a/core/dplugins/generic/tools/panorama/tasks/preprocesstask.cpp +++ b/core/dplugins/generic/tools/panorama/tasks/preprocesstask.cpp @@ -1,245 +1,254 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2012-03-15 * Description : a tool to create panorama by fusion of several images. * * Copyright (C) 2012-2016 by Benjamin Girault * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "preprocesstask.h" // Qt includes #include // KDE includes #include #include #include // Local includes #include "dbinarysearch.h" #include "digikam_debug.h" #include "drawdecoder.h" #include "dimg.h" #include "dimgloaderobserver.h" #include "drawdecoderwidget.h" #include "drawdecoding.h" namespace DigikamGenericPanoramaPlugin { class PanoObserver; class Q_DECL_HIDDEN PreProcessTask::Private { public: - explicit Private(PanoramaPreprocessedUrls& urls, const QUrl& url) + explicit Private(PanoramaPreprocessedUrls& urls, + const QUrl& url) : fileUrl(url), preProcessedUrl(urls), observer(nullptr) { } const QUrl fileUrl; PanoramaPreprocessedUrls& preProcessedUrl; DMetadata meta; PanoObserver* observer; }; class Q_DECL_HIDDEN PanoObserver : public DImgLoaderObserver { public: explicit PanoObserver(PreProcessTask* const p) : DImgLoaderObserver(), parent(p) { } ~PanoObserver() { } bool continueQuery() override { return (!parent->isAbortedFlag); } private: PreProcessTask* const parent; }; -PreProcessTask::PreProcessTask(const QString& workDirPath, int id, PanoramaPreprocessedUrls& targetUrls, +PreProcessTask::PreProcessTask(const QString& workDirPath, + int id, + PanoramaPreprocessedUrls& targetUrls, const QUrl& sourceUrl) : PanoTask(PANO_PREPROCESS_INPUT, workDirPath), id(id), d(new Private(targetUrls, sourceUrl)) { d->observer = new PanoObserver(this); } PreProcessTask::~PreProcessTask() { } void PreProcessTask::requestAbort() { PanoTask::requestAbort(); } void PreProcessTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*) { // check if its a RAW file. + if (DRawDecoder::isRawFile(d->fileUrl)) { d->preProcessedUrl.preprocessedUrl = tmpDir; if (!convertRaw()) { successFlag = false; + return; } } else { // NOTE: in this case, preprocessed Url is the original file Url. + d->preProcessedUrl.preprocessedUrl = d->fileUrl; } d->preProcessedUrl.previewUrl = tmpDir; if (!computePreview(d->preProcessedUrl.preprocessedUrl)) { successFlag = false; + return; } successFlag = true; - return; } bool PreProcessTask::computePreview(const QUrl& inUrl) { QUrl& outUrl = d->preProcessedUrl.previewUrl; QFileInfo fi(inUrl.toLocalFile()); outUrl.setPath(outUrl.path() + fi.completeBaseName().replace(QLatin1Char('.'), QLatin1String("_")) + QLatin1String("-preview.jpg")); DImg img; if (img.load(inUrl.toLocalFile())) { DImg preview = img.smoothScale(1280, 1024, Qt::KeepAspectRatio); bool saved = preview.save(outUrl.toLocalFile(), DImg::JPEG); // save exif information also to preview image for auto rotation + if (saved) { d->meta.load(inUrl.toLocalFile()); MetaEngine::ImageOrientation orientation = d->meta.getItemOrientation(); d->meta.load(outUrl.toLocalFile()); d->meta.setItemOrientation(orientation); d->meta.setItemDimensions(QSize(preview.width(), preview.height())); d->meta.applyChanges(true); } qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Preview Image url: " << outUrl << ", saved: " << saved; + return saved; } else { qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Error during preview generation of: " << inUrl; errString = i18n("Input image cannot be loaded for preview generation."); } return false; } bool PreProcessTask::convertRaw() { - const QUrl& inUrl = d->fileUrl; - QUrl& outUrl = d->preProcessedUrl.preprocessedUrl; + const QUrl& inUrl = d->fileUrl; + QUrl& outUrl = d->preProcessedUrl.preprocessedUrl; DImg img; DRawDecoding settings; KSharedConfig::Ptr config = KSharedConfig::openConfig(); KConfigGroup group = config->group(QLatin1String("ImageViewer Settings")); DRawDecoderWidget::readSettings(settings.rawPrm, group); if (img.load(inUrl.toLocalFile(), d->observer, settings)) { d->meta.load(inUrl.toLocalFile()); DMetadata::MetaDataMap m = d->meta.getExifTagsDataList(QStringList() << QLatin1String("Photo")); if (!m.isEmpty()) { - for (DMetadata::MetaDataMap::iterator it = m.begin(); it != m.end(); ++it) + for (DMetadata::MetaDataMap::iterator it = m.begin() ; it != m.end() ; ++it) { d->meta.removeExifTag(it.key().toLatin1().constData()); } } QByteArray exif = d->meta.getExifEncoded(); QByteArray iptc = d->meta.getIptc(); QByteArray xmp = d->meta.getXmp(); QString make = d->meta.getExifTagString("Exif.Image.Make"); QString model = d->meta.getExifTagString("Exif.Image.Model"); QFileInfo fi(inUrl.toLocalFile()); QDir outDir(outUrl.toLocalFile()); outDir.cdUp(); - QString path = outDir.path() + QLatin1Char('/'); + QString path = outDir.path() + QLatin1Char('/'); outUrl.setPath(path + fi.completeBaseName().replace(QLatin1Char('.'), QLatin1String("_")) + QLatin1String(".tif")); if (!img.save(outUrl.toLocalFile(), QLatin1String("TIF"))) { errString = i18n("Tiff image creation failed."); + return false; } d->meta.load(outUrl.toLocalFile()); d->meta.setExif(exif); d->meta.setIptc(iptc); d->meta.setXmp(xmp); d->meta.setItemDimensions(QSize(img.width(), img.height())); d->meta.setExifTagString("Exif.Image.DocumentName", inUrl.fileName()); d->meta.setXmpTagString("Xmp.tiff.Make", make); d->meta.setXmpTagString("Xmp.tiff.Model", model); d->meta.setItemOrientation(DMetadata::ORIENTATION_NORMAL); d->meta.applyChanges(true); } else { errString = i18n("Raw file conversion failed."); return false; } qCDebug(DIGIKAM_DPLUGIN_GENERIC_LOG) << "Convert RAW output url: " << outUrl; return true; } } // namespace DigikamGenericPanoramaPlugin