| Summary: | Layers manipulation is buggy | ||
|---|---|---|---|
| Product: | [Applications] krita | Reporter: | grum999 |
| Component: | Scripting | Assignee: | Krita Bugs <krita-bugs-null> |
| Status: | CONFIRMED --- | ||
| Severity: | normal | CC: | tamtamy.tymona |
| Priority: | NOR | ||
| Version First Reported In: | nightly build (please specify the git hash!) | ||
| Target Milestone: | --- | ||
| Platform: | Other | ||
| OS: | Linux | ||
| Latest Commit: | Version Fixed/Implemented In: | ||
| Sentry Crash Report: | |||
| Attachments: | Improved Python script showing all three cases | ||
|
Description
grum999
2020-09-09 19:51:08 UTC
I'm not sure about Component / Version to set (4.4.0 and 5.0.0 are not in version list) Grum999 It's technically a regression caused by making the Fill Layer multi-threaded, but I think just adding waitForDone() in the FillLayer.cpp should solve this. I haven't checked it yet though. (If you want @Grum check it, please see if adding waitForDone() instead of sleep() would make it work). d52e55f6cc0567ac75c8 In script example, I've replaced > sleep(sv) by > newDocument.waitForDone() There's no change in results, it's still incorrect Grum999 Created attachment 131537 [details]
Improved Python script showing all three cases
I attached an improved script that shows all three cases:
- using doc.waitForDone()
- using 1 ms sleep (not enough for Krita to finish generating)
- using 125 ms sleep (enough)
First two cases give bad results.
Steps to reproduce:
1. Open Krita.
2. Go to Tools -> Scripts -> Scripter.
3. Paste the script and execute.
I've made some other tests. On my side it seems that to get expected results, call to sleepOrWait() is needed only after: - a call to layer.setGenerator() - a call to layer.setBlendingMode() When other call to sleepOrWait() function are in comment, expected result is still OK. With this I can't affirm that problem doesn't occurs for mergeDown(), addChildNode() or other layer/document manipulation, but this tends to confirm that problem, as suspected bu @Tiar, is relative to fill layer. Grum999 Git commit 74dbabc3636fd5a1c18967d9fed105fb2ddaf7b2 by Dmitry Kazakov. Committed on 16/09/2020 at 11:37. Pushed by dkazakov into branch 'master'. Fix Python API for Node::addChildNode() The function should use the command, run it in a stroke and wait for it to finish. That ensures that 1) updates are issued; 2) undo item is created; 3) no threading issues arise. M +12 -4 libs/libkis/Node.cpp https://invent.kde.org/graphics/krita/commit/74dbabc3636fd5a1c18967d9fed105fb2ddaf7b2 Git commit 57dbf8a946d022a86855b95f278f1013f29d3148 by Dmitry Kazakov. Committed on 16/09/2020 at 11:37. Pushed by dkazakov into branch 'master'. Fix Python API for Node::setBlendingMode() The function should use the command, run it in a stroke and wait for it to finish. That ensures that 1) updates are issued; 2) undo item is created; 3) no threading issues arise. M +9 -1 libs/libkis/Node.cpp https://invent.kde.org/graphics/krita/commit/57dbf8a946d022a86855b95f278f1013f29d3148 Git commit 623c5114e009485391be9fbe943a1d9cd4da6bd3 by Dmitry Kazakov. Committed on 16/09/2020 at 11:37. Pushed by dkazakov into branch 'master'. Fix KisGeneratorLayer support KisDelayedUpdateNodeInterface It is needed to make sure the layer is updated when some synchronous non-gui provoked actions are requested. E.g. saving or changing via python API. The path also fixes FillLayer's Pythong API to be synchronous using this fix. M +15 -0 libs/image/generator/kis_generator_layer.cpp M +7 -1 libs/image/generator/kis_generator_layer.h M +6 -0 libs/libkis/FillLayer.cpp https://invent.kde.org/graphics/krita/commit/623c5114e009485391be9fbe943a1d9cd4da6bd3 After my patches the following script works fine:
===========================================================
from krita import *
from PyQt5.Qt import *
from PyQt5 import QtCore
from PyQt5.QtCore import (
QByteArray,
QPoint
)
from PyQt5.QtGui import (
QColor,
QImage,
QPixmap
)
def buildQImage(color, w, h):
"""Generate a QImage to use for example"""
img=QImage(w, h, QImage.Format_ARGB32_Premultiplied)
img.fill(Qt.transparent)
pxmTgt = QPixmap.fromImage(img)
gradientb = QRadialGradient(QPointF(w/3, h/4), 2*w/3)
gradientb.setColorAt(0, color)
gradientb.setColorAt(1, Qt.black)
gradientf = QRadialGradient(QPointF(w/3, h/4), 2*w/3)
gradientf.setColorAt(0, Qt.white)
gradientf.setColorAt(0.15, Qt.transparent)
gradientf.setColorAt(1, Qt.transparent)
canvas = QPainter()
canvas.begin(pxmTgt)
canvas.setRenderHint(QPainter.Antialiasing)
canvas.setPen(Qt.NoPen)
canvas.setBrush(gradientb)
canvas.drawEllipse(QRect(20,20,w-40, h-40));
canvas.setBrush(gradientf)
canvas.drawEllipse(QRect(20,20,w-40, h-40));
canvas.end()
return pxmTgt.toImage()
def setLayerFromQImage(layerNode, image):
"""Set QImage as layer content"""
position = QPoint(0, 0)
ptr = image.bits()
ptr.setsize(image.byteCount())
layerNode.setPixelData(QByteArray(ptr.asstring()), position.x(), position.y(), image.width(), image.height())
def sleep(value):
"""Do a sleep of `value` milliseconds"""
loop = QEventLoop()
QTimer.singleShot(value, loop.quit)
loop.exec()
dWidth=500
dHeight=500
# Cyan, Magenta, Yellow: colors used to generate layers
colors=[QColor(0,255,255), QColor(255,0,255), QColor(255,255,0)]
sleepValues=[0, 125]
image=buildQImage(QColor(255,0,0), dWidth, dHeight)
newDocument = Krita.instance().createDocument(dWidth, dHeight, "Test", "RGBA", "U8", "", 300.0)
Krita.instance().activeWindow().addView(newDocument)
parentGroupLayer = newDocument.createGroupLayer('Group layer')
newDocument.rootNode().addChildNode(parentGroupLayer, None)
for i in range(len(colors)):
# loop over colors and apply basics actions like plugin Newspaper (and Channel2Layers) does
newPLayer = newDocument.createNode(f"PaintLayer{i}", 'paintlayer')
setLayerFromQImage(newPLayer, image)
parentGroupLayer.addChildNode(newPLayer, None)
infoObject = InfoObject();
infoObject.setProperty("color", colors[i])
selection = Selection();
selection.select(0, 0, dWidth, dHeight, 255)
newFLayer = newDocument.createFillLayer(f"Color{i}", "color", infoObject, selection)
parentGroupLayer.addChildNode(newFLayer, newPLayer)
# mandatory as when provided to createFillLayer(), infoObject is not applied
# must also be applied after node has been added to parent...
newFLayer.setGenerator("color", infoObject)
newFLayer.setBlendingMode('add')
newLayer = newFLayer.mergeDown()
# returned layer from merge can't be used, so get the last one
currentProcessedLayer = parentGroupLayer.childNodes()[-1]
currentProcessedLayer.setBlendingMode('multiply')
===========================================================
Though other methods of Python API still have the same problems
Git commit 39bf729d88e70168e1e9ce58cac08fcb5f11f6f3 by Dmitry Kazakov. Committed on 16/09/2020 at 12:19. Pushed by dkazakov into branch 'krita/4.3'. Fix KisGeneratorLayer support KisDelayedUpdateNodeInterface It is needed to make sure the layer is updated when some synchronous non-gui provoked actions are requested. E.g. saving or changing via python API. The path also fixes FillLayer's Pythong API to be synchronous using this fix. # Conflicts: # libs/libkis/FillLayer.cpp M +15 -0 libs/image/generator/kis_generator_layer.cpp M +7 -1 libs/image/generator/kis_generator_layer.h M +7 -0 libs/libkis/FillLayer.cpp https://invent.kde.org/graphics/krita/commit/39bf729d88e70168e1e9ce58cac08fcb5f11f6f3 Git commit 7be91fc9922182bf02a3fc95feb9462ae8948f72 by Dmitry Kazakov. Committed on 16/09/2020 at 12:20. Pushed by dkazakov into branch 'krita/4.3'. Fix Python API for Node::setBlendingMode() The function should use the command, run it in a stroke and wait for it to finish. That ensures that 1) updates are issued; 2) undo item is created; 3) no threading issues arise. M +9 -1 libs/libkis/Node.cpp https://invent.kde.org/graphics/krita/commit/7be91fc9922182bf02a3fc95feb9462ae8948f72 Git commit 7013fef0227028316c8788e828e28a66f026c08d by Dmitry Kazakov. Committed on 16/09/2020 at 12:20. Pushed by dkazakov into branch 'krita/4.3'. Fix Python API for Node::addChildNode() The function should use the command, run it in a stroke and wait for it to finish. That ensures that 1) updates are issued; 2) undo item is created; 3) no threading issues arise. M +12 -4 libs/libkis/Node.cpp https://invent.kde.org/graphics/krita/commit/7013fef0227028316c8788e828e28a66f026c08d Now it is just a bug, not a regression Reassigning back to Amyspark :) |