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 "createptotask.h"
0016 #include "ptotype.h"
0017 
0018 // Qt includes
0019 
0020 #include <QFile>
0021 
0022 // KDE includes
0023 
0024 #include <klocalizedstring.h>
0025 
0026 namespace DigikamGenericPanoramaPlugin
0027 {
0028 
0029 CreatePtoTask::CreatePtoTask(const QString& workDirPath,
0030                              PanoramaFileType fileType,
0031                              QUrl& ptoUrl,
0032                              const QList<QUrl>& inputFiles,
0033                              const PanoramaItemUrlsMap& preProcessedMap,
0034                              bool addGPlusMetadata,
0035                              const QString& huginVersion)
0036     : PanoTask(PANO_CREATEPTO,
0037       workDirPath),
0038       ptoUrl(ptoUrl),
0039       preProcessedMap(&preProcessedMap),
0040       fileType(addGPlusMetadata ? JPEG : fileType),
0041       inputFiles(inputFiles),
0042       addGPlusMetadata(addGPlusMetadata),
0043       huginVersion(huginVersion)
0044 {
0045 }
0046 
0047 CreatePtoTask::~CreatePtoTask()
0048 {
0049 }
0050 
0051 void CreatePtoTask::run(ThreadWeaver::JobPointer, ThreadWeaver::Thread*)
0052 {
0053     ptoUrl = tmpDir;
0054     ptoUrl.setPath(ptoUrl.path() + QLatin1String("pano_base.pto"));
0055 
0056     QFile pto(ptoUrl.toLocalFile());
0057 
0058     if (pto.exists())
0059     {
0060         errString   = i18n("PTO file already created in the temporary directory.");
0061         successFlag = false;
0062 
0063         return;
0064     }
0065 
0066     if (!pto.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
0067     {
0068         errString   = i18n("PTO file cannot be created in the temporary directory.");
0069         successFlag = false;
0070 
0071         return;
0072     }
0073 
0074     pto.close();
0075 
0076     // 1. Project parameters
0077 
0078     PTOType panoBase(huginVersion);
0079 
0080     if (addGPlusMetadata)
0081     {
0082         panoBase.project.projection = PTOType::Project::EQUIRECTANGULAR;
0083     }
0084     else
0085     {
0086         panoBase.project.projection = PTOType::Project::CYLINDRICAL;
0087     }
0088 
0089     panoBase.project.fieldOfView = 0;
0090     panoBase.project.hdr         = false;
0091 
0092     switch (fileType)
0093     {
0094         case JPEG:
0095             panoBase.project.fileFormat.fileType = PTOType::Project::FileFormat::JPEG;
0096             panoBase.project.fileFormat.quality = 90;
0097             break;
0098 
0099         case TIFF:
0100             panoBase.project.fileFormat.fileType = PTOType::Project::FileFormat::TIFF_m;
0101             panoBase.project.fileFormat.compressionMethod = PTOType::Project::FileFormat::LZW;
0102             panoBase.project.fileFormat.savePositions = false;
0103             panoBase.project.fileFormat.cropped = false;
0104             break;
0105 
0106         case HDR:
0107             panoBase.project.hdr = true;
0108             // TODO HDR
0109             break;
0110     }
0111 /*
0112     panoBase.project.bitDepth = PTOType::Project::FLOAT;
0113     panoBase.project.crop.setLeft(X_left);
0114     panoBase.project.crop.setRight(X_right);
0115     panoBase.project.crop.setTop(X_top);
0116     panoBase.project.crop.setBottom(X_bottom);
0117 */
0118     panoBase.project.photometricReferenceId = 0;
0119 
0120     // 2. Images
0121 
0122     panoBase.images.reserve(inputFiles.size());
0123     panoBase.images.resize(inputFiles.size());
0124     int i = 0;
0125 
0126     for (i = 0 ; i < inputFiles.size() ; ++i)
0127     {
0128         QUrl inputFile(inputFiles.at(i));
0129         QUrl preprocessedUrl(preProcessedMap->value(inputFile).preprocessedUrl);
0130         m_meta.load(preprocessedUrl.toLocalFile());
0131         QSize size                        = m_meta.getPixelSize();
0132 
0133         panoBase.images[i]                = PTOType::Image();
0134         panoBase.images[i].lensProjection = PTOType::Image::RECTILINEAR;
0135         panoBase.images[i].size           = size;
0136 
0137         if (i > 0)
0138         {
0139             // We suppose that the pictures are all taken with the same camera and lens
0140 
0141             panoBase.images[i].lensBarrelCoefficientA.referenceId = 0;
0142             panoBase.images[i].lensBarrelCoefficientB.referenceId = 0;
0143             panoBase.images[i].lensBarrelCoefficientC.referenceId = 0;
0144             panoBase.images[i].lensCenterOffsetX.referenceId      = 0;
0145             panoBase.images[i].lensCenterOffsetY.referenceId      = 0;
0146             panoBase.images[i].lensShearX.referenceId             = 0;
0147             panoBase.images[i].lensShearY.referenceId             = 0;
0148             panoBase.images[i].vignettingCorrectionI.referenceId  = 0;
0149             panoBase.images[i].vignettingCorrectionJ.referenceId  = 0;
0150             panoBase.images[i].vignettingCorrectionK.referenceId  = 0;
0151             panoBase.images[i].vignettingCorrectionL.referenceId  = 0;
0152             panoBase.images[i].vignettingOffsetX.referenceId      = 0;
0153             panoBase.images[i].vignettingOffsetY.referenceId      = 0;
0154         }
0155         else
0156         {
0157             panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0158             panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSA;
0159             panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0160             panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSB;
0161             panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0162             panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSC;
0163             panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0164             panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSD;
0165             panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0166             panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::LENSE;
0167             panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0168             panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VA;
0169             panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0170             panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VB;
0171             panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0172             panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VC;
0173             panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0174             panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VD;
0175             panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0176             panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VX;
0177             panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0178             panoBase.images[i].optimizationParameters.last().parameter = PTOType::Optimization::VY;
0179         }
0180 
0181         panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0182         panoBase.images[i].optimizationParameters.last().parameter =  PTOType::Optimization::RA;
0183         panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0184         panoBase.images[i].optimizationParameters.last().parameter =  PTOType::Optimization::RB;
0185         panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0186         panoBase.images[i].optimizationParameters.last().parameter =  PTOType::Optimization::RC;
0187         panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0188         panoBase.images[i].optimizationParameters.last().parameter =  PTOType::Optimization::RD;
0189         panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0190         panoBase.images[i].optimizationParameters.last().parameter =  PTOType::Optimization::RE;
0191         panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0192         panoBase.images[i].optimizationParameters.last().parameter =  PTOType::Optimization::EXPOSURE;
0193         panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0194         panoBase.images[i].optimizationParameters.last().parameter =  PTOType::Optimization::WBR;
0195         panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0196         panoBase.images[i].optimizationParameters.last().parameter =  PTOType::Optimization::WBB;
0197         panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0198         panoBase.images[i].optimizationParameters.last().parameter =  PTOType::Optimization::LENSYAW;
0199         panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0200         panoBase.images[i].optimizationParameters.last().parameter =  PTOType::Optimization::LENSPITCH;
0201         panoBase.images[i].optimizationParameters.append(PTOType::Optimization());
0202         panoBase.images[i].optimizationParameters.last().parameter =  PTOType::Optimization::LENSROLL;
0203         panoBase.images[i].fileName = preprocessedUrl.toLocalFile();
0204     }
0205 
0206     switch (fileType)
0207     {
0208         case TIFF:
0209             panoBase.lastComments << QLatin1String("#hugin_outputImageType tif");
0210             panoBase.lastComments << QLatin1String("#hugin_outputImageTypeCompression LZW");
0211             break;
0212 
0213         case JPEG:
0214             panoBase.lastComments << QLatin1String("#hugin_outputImageType jpg");
0215             panoBase.lastComments << QLatin1String("#hugin_outputJPEGQuality 90");
0216             break;
0217 
0218         case HDR:
0219             // TODO: HDR
0220             break;
0221     }
0222 
0223     panoBase.createFile(ptoUrl.toLocalFile());
0224 
0225     successFlag = true;
0226 }
0227 
0228 } // namespace DigikamGenericPanoramaPlugin