File indexing completed on 2025-03-09 03:56:14
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2017-05-25 0007 * Description : a tool to generate video slideshow frames from images. 0008 * 0009 * SPDX-FileCopyrightText: 2017-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 "vidslidetask.h" 0016 0017 // C++ includes 0018 0019 #include <cmath> 0020 0021 // Qt includes 0022 0023 #include <QDir> 0024 #include <QString> 0025 #include <QStringList> 0026 #include <QImage> 0027 #include <QSize> 0028 #include <QPainter> 0029 #include <QFileInfo> 0030 #include <QFile> 0031 #include <QIODevice> 0032 #include <QDateTime> 0033 #include <QTextStream> 0034 0035 // KDE includes 0036 0037 #include <klocalizedstring.h> 0038 0039 // Local includes 0040 0041 #include "digikam_config.h" 0042 #include "digikam_debug.h" 0043 #include "digikam_globals.h" 0044 #include "frameutils.h" 0045 #include "frameosd.h" 0046 #include "dfileoperations.h" 0047 #include "transitionmngr.h" 0048 #include "effectmngr.h" 0049 0050 namespace Digikam 0051 { 0052 0053 VidSlideTask::VidSlideTask(VidSlideSettings* const settings) 0054 : ActionJob() 0055 { 0056 m_settings = settings; 0057 } 0058 0059 VidSlideTask::~VidSlideTask() 0060 { 0061 cancel(); 0062 } 0063 0064 void VidSlideTask::run() 0065 { 0066 FrameOsd osd; 0067 0068 int frameId = 1; 0069 m_settings->filesList = m_settings->tempDir + QLatin1String("fileslist.txt"); 0070 QFile fList(m_settings->filesList); 0071 0072 if (!fList.open(QIODevice::WriteOnly | QIODevice::Text)) 0073 { 0074 qCWarning(DIGIKAM_GENERAL_LOG) << "Cannot create files list:" << m_settings->filesList; 0075 } 0076 0077 QTextStream out(&fList); 0078 0079 // --------------------------------------------- 0080 // Setup output video file 0081 0082 QUrl dest = QUrl::fromLocalFile(m_settings->outputDir); 0083 dest = dest.adjusted(QUrl::StripTrailingSlash); 0084 dest.setPath(dest.path() + QDir::separator() + QLatin1String("videoslideshow.") + m_settings->videoFormat()); 0085 QString outFile = dest.toLocalFile(); 0086 QFileInfo fi(outFile); 0087 0088 if (fi.exists() && (m_settings->conflictRule != FileSaveConflictBox::OVERWRITE)) 0089 { 0090 outFile = DFileOperations::getUniqueFileUrl(dest).toLocalFile(); 0091 } 0092 0093 QImage qiimg; 0094 QSize osize = m_settings->videoSize(); 0095 0096 // -------------------------------------------------------------- 0097 // Loop to encode frames with images list as temporary JPEG files 0098 0099 TransitionMngr transmngr; 0100 transmngr.setOutputSize(osize); 0101 0102 EffectMngr effmngr; 0103 effmngr.setOutputSize(osize); 0104 effmngr.setFrames(m_settings->imgFrames); 0105 0106 for (int i = 0 ; ((i < m_settings->inputImages.count() + 1) && !m_cancel) ; ++i) 0107 { 0108 if (i == 0) 0109 { 0110 qiimg = FrameUtils::makeFramedImage(QString(), osize); 0111 } 0112 0113 QString ofile; 0114 0115 if (i < m_settings->inputImages.count()) 0116 { 0117 ofile = m_settings->inputImages[i].toLocalFile(); 0118 } 0119 0120 QImage qoimg = FrameUtils::makeFramedImage(ofile, osize); 0121 0122 // -- Transition encoding ---------- 0123 0124 transmngr.setInImage(qiimg); 0125 transmngr.setOutImage(qoimg); 0126 transmngr.setTransition(m_settings->transition); 0127 0128 int ttmout = 0; 0129 QImage frame; 0130 QString framePath; 0131 0132 do 0133 { 0134 frame = QImage(transmngr.currentFrame(ttmout)); 0135 framePath = m_settings->tempDir + QString::fromLatin1("frame_%1").arg(frameId, 9, 10, QLatin1Char('0')) + QLatin1String(".jpg"); 0136 0137 if (!frame.save(framePath, "JPEG")) 0138 { 0139 qCWarning(DIGIKAM_GENERAL_LOG) << "Cannot generate frame:" << framePath; 0140 } 0141 else 0142 { 0143 qCDebug(DIGIKAM_GENERAL_LOG) << "Frame generated:" << framePath; 0144 } 0145 0146 out << QString::fromUtf8("file '%1'").arg(QFileInfo(framePath).fileName()) << QT_ENDL; 0147 ++frameId; 0148 } 0149 while ((ttmout != -1) && !m_cancel); 0150 0151 // -- Images encoding ---------- 0152 0153 if (i < m_settings->inputImages.count()) 0154 { 0155 int count = 0; 0156 int itmout = 0; 0157 effmngr.setImage(qoimg); 0158 effmngr.setEffect(m_settings->vEffect); 0159 0160 do 0161 { 0162 qiimg = effmngr.currentFrame(itmout); 0163 0164 if ((osize.width() >= 1024) && (osize.height() >= 576)) 0165 { 0166 osd.insertOsdToFrame(qiimg, 0167 QUrl::fromLocalFile(ofile), 0168 m_settings->osdSettings, 0169 m_settings->iface); 0170 } 0171 0172 frame = qiimg; 0173 framePath = m_settings->tempDir + QString::fromLatin1("frame_%1").arg(frameId, 9, 10, QLatin1Char('0')) + QLatin1String(".jpg"); 0174 0175 if (!frame.save(framePath, "JPEG")) 0176 { 0177 qCWarning(DIGIKAM_GENERAL_LOG) << "Cannot generate frame:" << framePath; 0178 } 0179 else 0180 { 0181 qCDebug(DIGIKAM_GENERAL_LOG) << "Frame generated:" << ":" << framePath; 0182 } 0183 0184 out << QString::fromUtf8("file '%1'").arg(QFileInfo(framePath).fileName()) << QT_ENDL; 0185 ++frameId; 0186 ++count; 0187 } 0188 while ((count < m_settings->imgFrames) && !m_cancel); 0189 } 0190 0191 qCDebug(DIGIKAM_GENERAL_LOG) << "Generating frames from image" << i << "done"; 0192 0193 if (!ofile.isEmpty()) 0194 { 0195 Q_EMIT signalMessage(i18n("Generating frames from %1 Done", ofile), false); 0196 } 0197 0198 Q_EMIT signalProgress(i); 0199 } 0200 0201 fList.close(); 0202 0203 m_settings->outputFile = outFile; 0204 0205 Q_EMIT signalDone(!m_cancel); 0206 } 0207 0208 } // namespace Digikam