Krita Source Code Documentation
Loading...
Searching...
No Matches
KisAsyncAnimationFramesSavingRenderer.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2017 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include "kis_image.h"
10#include "kis_paint_device.h"
12#include "KisPart.h"
13#include "KisDocument.h"
14#include "kis_time_span.h"
15#include "kis_paint_layer.h"
16
17#include <kis_debug.h>
18
19#ifdef Q_OS_ANDROID
20#include <KisAndroidUtils.h>
21#endif
22
23
25{
26 Private(KisImageSP image, const KisTimeSpan &_range, int _sequenceNumberingOffset, bool _onlyNeedsUniqueFrames, KisPropertiesConfigurationSP _exportConfiguration)
28 range(_range),
29 sequenceNumberingOffset(_sequenceNumberingOffset),
30 onlyNeedsUniqueFrames(_onlyNeedsUniqueFrames),
31 exportConfiguration(_exportConfiguration)
32 {
33
34 savingDoc->setInfiniteAutoSaveInterval();
35 savingDoc->setFileBatchMode(true);
36
37 KisImageSP savingImage = new KisImage(savingDoc->createUndoStore(),
38 image->bounds().width(),
39 image->bounds().height(),
40 image->colorSpace(),
41 QString());
42
43 savingImage->setResolution(image->xRes(), image->yRes());
44 savingDoc->setCurrentImage(savingImage);
45
46 KisPaintLayer* paintLayer = new KisPaintLayer(savingImage, "paint device", 255);
47 savingImage->addNode(paintLayer, savingImage->root(), KisLayerSP(0));
48
49 savingDevice = paintLayer->paintDevice();
50 }
51
52 QScopedPointer<KisDocument> savingDoc;
54
57
59
62
63 QByteArray outputMimeType;
65};
66
68 const QString &fileNamePrefix,
69 const QString &fileNameSuffix,
70 const QByteArray &outputMimeType,
71 const KisTimeSpan &range,
72 const int sequenceNumberingOffset,
73 const bool onlyNeedsUniqueFrames,
74 KisPropertiesConfigurationSP exportConfiguration)
75 : m_d(new Private(image, range, sequenceNumberingOffset, onlyNeedsUniqueFrames, exportConfiguration))
76{
77 m_d->filenamePrefix = fileNamePrefix;
78 m_d->filenameSuffix = fileNameSuffix;
79 m_d->outputMimeType = outputMimeType;
80
81 connect(this, SIGNAL(sigCompleteRegenerationInternal(int)), SLOT(notifyFrameCompleted(int)));
83}
84
85
86
87
91
93{
94 KisImageSP image = requestedImage();
95 if (!image) return;
96
99 return;
100 }
101
102 m_d->savingDevice->makeCloneFromRough(image->projection(), image->bounds());
103
105
106 QString frameNumber = QString("%1").arg(frame + m_d->sequenceNumberingOffset, 4, 10, QChar('0'));
107 QString filename = m_d->filenamePrefix + frameNumber + m_d->filenameSuffix;
108
109 if (!m_d->savingDoc->exportDocumentSync(filename, m_d->outputMimeType, m_d->exportConfiguration)) {
111 }
112
113 //Get all identical frames to this one and either copy or symlink based on settings.
114 if (status.isOk()) {
116 identicals &= m_d->range;
117 if( !m_d->onlyNeedsUniqueFrames && identicals.start() < identicals.end() ) {
118 for (int identicalFrame = (identicals.start() + 1); identicalFrame <= identicals.end(); identicalFrame++) {
119 QString identicalFrameNumber = QString("%1").arg(identicalFrame + m_d->sequenceNumberingOffset, 4, 10, QChar('0'));
120 QString identicalFrameName = m_d->filenamePrefix + identicalFrameNumber + m_d->filenameSuffix;
121
122 bool copyOk;
123 QString copyErrorMessage;
124#ifdef Q_OS_ANDROID
125 copyOk = KisAndroidUtils::copyFile(filename, identicalFrameName, &copyErrorMessage);
126#else
127 QFile sourceFile(filename);
128 if (sourceFile.copy(identicalFrameName)) {
129 copyOk = true;
130 } else {
131 copyOk = false;
132 copyErrorMessage = sourceFile.errorString();
133 }
134#endif
135 if (!copyOk) {
136 warnFile.nospace() << "Failed to copy frame '" << filename << "' to '" << identicalFrameName
137 << "': " << copyErrorMessage;
139 break;
140 }
141
142 /* This would be nice to do but sym-linking on windows isn't possible without
143 * way more other work to be done. This works on linux though!
144 *
145 * if (m_d->linkRedundantFrames) {
146 * QFile::link(filename, identicalFrameName);
147 * } else {
148 * QFile::copy(filename, identicalFrameName);
149 * }
150 */
151 }
152 }
153 }
154
155 if (status.isOk()) {
157 } else {
159 }
160}
161
163{
164 notifyFrameCancelled(frame, cancelReason);
165}
166
PythonPluginManager * instance
void frameCancelledCallback(int frame, CancelReason cancelReason) override
frameCancelledCallback is called when the rendering of the frame was cancelled.
void sigCancelRegenerationInternal(int frame, KisAsyncAnimationRendererBase::CancelReason cancelReason)
void frameCompletedCallback(int frame, const KisRegion &requestedRegion) override
frameCompletedCallback is called by the renderer when a new frame becomes ready
KisAsyncAnimationFramesSavingRenderer(KisImageSP image, const QString &fileNamePrefix, const QString &fileNameSuffix, const QByteArray &outputMimeType, const KisTimeSpan &range, const int sequenceNumberingOffset, const bool onlyNeedsUniqueFrames, KisPropertiesConfigurationSP exportConfiguration)
void sigCompleteRegenerationInternal(int frame)
const KoColorSpace * colorSpace() const
KisPaintDeviceSP projection() const
double xRes() const
double yRes() const
QRect bounds() const override
void setResolution(double xres, double yres)
int start() const
static KisTimeSpan calculateIdenticalFramesRecursive(const KisNode *node, int time)
int end() const
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
#define warnFile
Definition kis_debug.h:99
KisDocument * createDocument(QList< KisNodeSP > nodes, KisImageSP srcImage, const QRect &copiedBounds)
bool copyFile(const QString &inputPath, const QString &outputPath, QString *outErrorMessage)
Private(KisImageSP image, const KisTimeSpan &_range, int _sequenceNumberingOffset, bool _onlyNeedsUniqueFrames, KisPropertiesConfigurationSP _exportConfiguration)
void notifyFrameCancelled(int frame, KisAsyncAnimationRendererBase::CancelReason cancelReason)
bool addNode(KisNodeSP node, KisNodeSP parent=KisNodeSP(), KisNodeAdditionFlags flags=KisNodeAdditionFlag::None)
KisPaintDeviceSP paintDevice