19#include <QDirIterator>
20#include <QElapsedTimer>
22#include <QRegularExpression>
23#include <QApplication>
24#include <QMutexLocker>
28#include <QSharedPointer>
37 "KisToolSelectOutline",
38 "KisToolSelectPolygonal",
39 "KisToolEncloseAndFill",
43 "KisToolSelectMagnetic",
47 "KritaTransform/KisToolMove",
48 "KritaShape/KisToolLine",
49 "KritaShape/KisToolRectangle",
50 "KritaShape/KisToolEllipse",
51 "KisToolSelectRectangular",
52 "KisToolSelectElliptical",
59 threads =
static_cast<unsigned int>(
67 auto oldValue =
get();
120 auto oldValue =
inUse;
121 inUse =
static_cast<unsigned int>(
124 return oldValue !=
inUse;
168 const bool needSrgbConversion = [&]() {
184 if (
targetCs && needSrgbConversion) {
190 const quint32 width = image->
width() & bitmask;
191 const quint32 height = image->
height() & bitmask;
192 const int bufferSize = device->
pixelSize() * width * height;
200 const int outWidth = width / divider;
201 const int outHeight = height / divider;
202 uchar *outData =
reinterpret_cast<uchar *
>(
imageBuffer.data());
204 frame = QImage(outData, outWidth, outHeight, QImage::Format_ARGB32);
215 inline quint32
avg(quint32 c1, quint32 c2)
217 return (((c1 ^ c2) & 0xfefefefeUL) >> 1) + (c1 & c2);
222 quint32 *buffer =
reinterpret_cast<quint32 *
>(
imageBuffer.data());
223 quint32 *out = buffer;
231 avg(in1[x], in1[x + 1]),
232 avg(in2[x], in2[x + 1])
248 const int inverseAlpha = 255 - alpha;
250 (alpha * qRed(
source) + inverseAlpha * qRed(destination)) >> 8,
251 (alpha * qGreen(
source) + inverseAlpha * qGreen(destination)) >> 8,
252 (alpha * qBlue(
source) + inverseAlpha * qBlue(destination)) >> 8
258 const quint32 background = 0xFFFFFFFF;
259 quint32 *buffer =
reinterpret_cast<quint32 *
>(
imageBuffer.data());
261 while (buffer != end) {
262 const int alpha = qAlpha(*buffer);
267 *buffer = background;
282 const QString fileName = QString(
"%1").arg(
partIndex, 7, 10, QLatin1Char(
'0'));
298 QFile(filePath).remove();
320 if (
static_cast<int>(
id) != writerId)
345 QObject* threadParent,
388 QElapsedTimer dbgTimer;
391 QDirIterator dirIterator(directory);
395 int recordIndex = -1;
396 while (dirIterator.hasNext()) {
399 const QString &fileName = dirIterator.fileName();
400 const QRegularExpressionMatch &match = snapshotFilePattern.match(fileName);
401 if (match.hasMatch()) {
402 int index = match.captured(1).toInt();
403 if (recordIndex < index)
407 dbgTools <<
"findLastPartNumber for" << directory <<
": " << dbgTimer.elapsed() <<
"ms";
415 bool alreadyWarn =
false;
416 bool alreadyErr =
false;
421 disconnect(
q, SIGNAL(
startCapturing(
int,
int)), el.writer.get(), SLOT(onCaptureImage(
int,
int)));
422 disconnect(el.writer.get(), SIGNAL(capturingDone(
int,
bool)),
q, SLOT(
onCapturingDone(
int,
bool)));
423 if (el.thread->isRunning())
426 warnResources <<
"One of the Recorder WriterPool threads has been blocked and has to be terminated. "
427 <<
"Thread Name: " << el.thread->objectName();
430 el.thread->terminate();
434 errResources <<
"Something odd has been happen. Krita was unable to stop one of the Recorder WriterPool Threads. "
435 <<
"Thread Name: " << el.thread->objectName();
462 auto writerPtr =
writerPool[newWorkerId].writer;
463 auto threadPtr =
writerPool[newWorkerId].thread;
464 threadPtr->setObjectName(QString(
"Krita-Recorder-WriterPool#%1").arg(newWorkerId));
467 writerPtr->moveToThread(threadPtr.get());
468 threadPtr->start(QThread::IdlePriority);
475 for(
auto i = 0; i <
writerPool.size(); i++, j++)
495 : d(new
Private(this, recorderThreads))
496 , exporterSettings(es)
498 d->
timer.setTimerType(Qt::PreciseTimer);
509 bool restart =
d->
timer.isActive();
518 disconnect(proxy, SIGNAL(toolChanged(QString)),
this, SLOT(
onToolChanged(QString)));
530 Qt::DirectConnection);
532 Qt::DirectConnection);
534 Qt::DirectConnection);
545 bool restart =
d->
timer.isActive();
610 if (qobject_cast<KisMainWindow*>(QApplication::activeWindow()) ==
nullptr)
614 (
d->
canvas->image()->isIsolatingLayer() ||
d->
canvas->image()->isIsolatingGroup())) {
645 d->
writerPool[workerId].thread->setPriority(QThread::IdlePriority);
659 (
d->
canvas->image()->isIsolatingLayer() ||
d->
canvas->image()->isIsolatingGroup()))
float value(const T *src, size_t ch)
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
ColorPrimaries
The colorPrimaries enum Enum of colorants, follows ITU H.273 for values 0 to 255, and has extra known...
@ PRIMARIES_ITU_R_BT_709_5
TransferCharacteristics
The transferCharacteristics enum Enum of transfer characteristics, follows ITU H.273 for values 0 to ...
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
const KoColorSpace * colorSpace() const
KisPaintDeviceSP projection() const
void immediateLockForReadOnly()
QRect bounds() const override
quint32 pixelSize() const
void makeCloneFromRough(KisPaintDeviceSP src, const QRect &minimalRect)
void convertTo(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags(), KUndo2Command *parentCommand=nullptr, KoUpdater *progressUpdater=nullptr)
void readBytes(quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h) const
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
virtual const KoColorProfile * profile() const =0
volatile std::atomic_bool toolActivated
QPointer< KisCanvas2 > canvas
ThreadCounter & recorderThreads
int findLastIndex(const QString &directory)
RecorderWriterManager *const q
volatile std::atomic_bool isActivateBlackTool
volatile std::atomic_bool imageModified
void searchForFreeWriter()
Private(RecorderWriterManager *q_ptr, ThreadCounter &rt)
std::atomic_int freeWriterId
volatile std::atomic_bool isForceBlackTool
RecorderWriterSettings settings
volatile std::atomic_bool enabled
RecorderWriterManager()=delete
void start(bool toggleEnabled=true)
void onCapturingDone(int workerId, bool success)
void startCapturing(int writerId, int index)
void onToolPrimaryActionActivated(bool activated)
void lowPerformanceWarning()
void recorderStopWarning()
void setCanvas(QPointer< KisCanvas2 > canvas)
bool stop(bool toggleEnabled=true)
void setEnabled(bool enabled)
void setup(const RecorderWriterSettings &settings)
ThreadCounter recorderThreads
const RecorderExportSettings & exporterSettings
void onToolChanged(const QString &toolId)
Private(Private &&)=delete
void removeFrameTransparency()
QPointer< KisCanvas2 > canvas
quint32 avg(quint32 c1, quint32 c2)
const KoColorSpace * targetCs
void halfSizeImageBuffer()
Private & operator=(Private &&)=delete
Private & operator=(const Private &)=default
quint32 blendSourceOver(const int alpha, const quint32 source, const quint32 destination)
const RecorderWriterSettings * settings
Private(QPointer< KisCanvas2 > c, const RecorderWriterSettings &s, const QDir &d)
Private(const Private &)=default
void onCaptureImage(int writerId, int index)
void capturingDone(int writerId, bool success)
void setUsedAndNotify(int value)
bool setUsedImpl(int value)
unsigned int getUsed() const
void notifyValueChange(bool valueWasIncreased)
void setAndNotify(int value)
void notifyInUseChange(bool valueWasIncreased)
QRegularExpression snapshotFilePatternFor(const QString &extension)
constexpr int waitThreadTimeoutMs
const unsigned int MaxThreadCount
virtual ColorPrimaries getColorPrimaries() const
getColorPrimaries
virtual bool hasColorants() const =0
virtual TransferCharacteristics getTransferCharacteristics() const
getTransferCharacteristics This function should be subclassed at some point so we can get the value f...
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
const KoColorProfile * p709SRGBProfile() const
bool recordIsolateLayerMode
QSharedPointer< RecorderWriter > writer
QSharedPointer< QThread > thread
WriterPoolEl(QObject *threadParent, unsigned int i, QPointer< KisCanvas2 > c, const RecorderWriterSettings &s, const QDir &d)