File indexing completed on 2024-05-12 16:01:45
0001 /* 0002 * SPDX-FileCopyrightText: 2017 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "KisAsyncAnimationFramesSavingRenderer.h" 0008 0009 #include "kis_image.h" 0010 #include "kis_paint_device.h" 0011 #include "KisImportExportFilter.h" 0012 #include "KisPart.h" 0013 #include "KisDocument.h" 0014 #include "kis_time_span.h" 0015 #include "kis_paint_layer.h" 0016 0017 0018 struct KisAsyncAnimationFramesSavingRenderer::Private 0019 { 0020 Private(KisImageSP image, const KisTimeSpan &_range, int _sequenceNumberingOffset, bool _onlyNeedsUniqueFrames, KisPropertiesConfigurationSP _exportConfiguration) 0021 : savingDoc(KisPart::instance()->createDocument()), 0022 range(_range), 0023 sequenceNumberingOffset(_sequenceNumberingOffset), 0024 onlyNeedsUniqueFrames(_onlyNeedsUniqueFrames), 0025 exportConfiguration(_exportConfiguration) 0026 { 0027 0028 savingDoc->setInfiniteAutoSaveInterval(); 0029 savingDoc->setFileBatchMode(true); 0030 0031 KisImageSP savingImage = new KisImage(savingDoc->createUndoStore(), 0032 image->bounds().width(), 0033 image->bounds().height(), 0034 image->colorSpace(), 0035 QString()); 0036 0037 savingImage->setResolution(image->xRes(), image->yRes()); 0038 savingDoc->setCurrentImage(savingImage); 0039 0040 KisPaintLayer* paintLayer = new KisPaintLayer(savingImage, "paint device", 255); 0041 savingImage->addNode(paintLayer, savingImage->root(), KisLayerSP(0)); 0042 0043 savingDevice = paintLayer->paintDevice(); 0044 } 0045 0046 QScopedPointer<KisDocument> savingDoc; 0047 KisPaintDeviceSP savingDevice; 0048 0049 KisTimeSpan range; 0050 int sequenceNumberingOffset = 0; 0051 0052 bool onlyNeedsUniqueFrames; 0053 0054 QString filenamePrefix; 0055 QString filenameSuffix; 0056 0057 QByteArray outputMimeType; 0058 KisPropertiesConfigurationSP exportConfiguration; 0059 }; 0060 0061 KisAsyncAnimationFramesSavingRenderer::KisAsyncAnimationFramesSavingRenderer(KisImageSP image, 0062 const QString &fileNamePrefix, 0063 const QString &fileNameSuffix, 0064 const QByteArray &outputMimeType, 0065 const KisTimeSpan &range, 0066 const int startNumberingAt, 0067 const bool onlyNeedsUniqueFrames, 0068 KisPropertiesConfigurationSP exportConfiguration) 0069 : m_d(new Private(image, range, qMax(startNumberingAt - range.start(), range.start() * -1), onlyNeedsUniqueFrames, exportConfiguration)) 0070 { 0071 m_d->filenamePrefix = fileNamePrefix; 0072 m_d->filenameSuffix = fileNameSuffix; 0073 m_d->outputMimeType = outputMimeType; 0074 0075 connect(this, SIGNAL(sigCompleteRegenerationInternal(int)), SLOT(notifyFrameCompleted(int))); 0076 connect(this, SIGNAL(sigCancelRegenerationInternal(int, KisAsyncAnimationRendererBase::CancelReason)), SLOT(notifyFrameCancelled(int, KisAsyncAnimationRendererBase::CancelReason))); 0077 } 0078 0079 0080 0081 0082 KisAsyncAnimationFramesSavingRenderer::~KisAsyncAnimationFramesSavingRenderer() 0083 { 0084 } 0085 0086 void KisAsyncAnimationFramesSavingRenderer::frameCompletedCallback(int frame, const KisRegion &requestedRegion) 0087 { 0088 KisImageSP image = requestedImage(); 0089 if (!image) return; 0090 0091 KIS_SAFE_ASSERT_RECOVER (requestedRegion == image->bounds()) { 0092 emit sigCancelRegenerationInternal(frame, KisAsyncAnimationRendererBase::RenderingFailed); 0093 return; 0094 } 0095 0096 m_d->savingDevice->makeCloneFromRough(image->projection(), image->bounds()); 0097 0098 KisImportExportErrorCode status = ImportExportCodes::OK; 0099 0100 QString frameNumber = QString("%1").arg(frame + m_d->sequenceNumberingOffset, 4, 10, QChar('0')); 0101 QString filename = m_d->filenamePrefix + frameNumber + m_d->filenameSuffix; 0102 0103 if (!m_d->savingDoc->exportDocumentSync(filename, m_d->outputMimeType, m_d->exportConfiguration)) { 0104 status = ImportExportCodes::InternalError; 0105 } 0106 0107 //Get all identical frames to this one and either copy or symlink based on settings. 0108 KisTimeSpan identicals = KisTimeSpan::calculateIdenticalFramesRecursive(image->root(), frame); 0109 identicals &= m_d->range; 0110 if( !m_d->onlyNeedsUniqueFrames && identicals.start() < identicals.end() ) { 0111 for (int identicalFrame = (identicals.start() + 1); identicalFrame <= identicals.end(); identicalFrame++) { 0112 QString identicalFrameNumber = QString("%1").arg(identicalFrame + m_d->sequenceNumberingOffset, 4, 10, QChar('0')); 0113 QString identicalFrameName = m_d->filenamePrefix + identicalFrameNumber + m_d->filenameSuffix; 0114 0115 QFile::copy(filename, identicalFrameName); 0116 0117 /* This would be nice to do but sym-linking on windows isn't possible without 0118 * way more other work to be done. This works on linux though! 0119 * 0120 * if (m_d->linkRedundantFrames) { 0121 * QFile::link(filename, identicalFrameName); 0122 * } else { 0123 * QFile::copy(filename, identicalFrameName); 0124 * } 0125 */ 0126 } 0127 } 0128 0129 if (status.isOk()) { 0130 emit sigCompleteRegenerationInternal(frame); 0131 } else { 0132 emit sigCancelRegenerationInternal(frame, KisAsyncAnimationRendererBase::RenderingFailed); 0133 } 0134 } 0135 0136 void KisAsyncAnimationFramesSavingRenderer::frameCancelledCallback(int frame, CancelReason cancelReason) 0137 { 0138 notifyFrameCancelled(frame, cancelReason); 0139 } 0140