This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Setting channel visibility in python

Tags: None
(comma "," separated)
gobber
Registered Member
Posts
8
Karma
0
Hi all,

I am having trouble setting individual channel visibility on a layer, using python in Krita.
I am not sure whether this is a bug, or whether I am just not following the correct procedure.

To reproduce what I am trying to do, you can a load photo or image into Krita, then open the Scripter, and run this code:

Code: Select all
from krita import *

activeView = Krita.instance().activeWindow().activeView()
activeDocument = activeView.document()
# grab the active layer
activeNode = activeDocument.activeNode()

# try to set both blue and green channels to invisible
activeNode.channels()[0].setVisible(False)
activeNode.channels()[1].setVisible(False)

activeDocument.waitForDone()
activeDocument.refreshProjection()


The expected outcome is that the visibility of channels 0 and 1 should be set to False (ie. Blue and Green), leaving only channels 2 (Red) and 3 (Alpha) visible - at least for an RGBA U8 image.

After running this code however, only channel 1 (Green) is set to invisible. Channel 0 (Blue) is visible. Upon playing with the test code, it seems only the last setVisible() "sticks"; all other channels are (silently) reset to setVisible(True). So if I for example reversed the order of the two setVisible() operations in this code, only Blue would remain invisible, and Green would be reset to visible.

I've checked out the code in https://invent.kde.org/graphics/krita/- ... /Channel.h, as has been suggested to me before, but that looks like it should work (ie. every call to a channel's setVisible() should only affect that channel, and leave the others alone), and I'm wondering if there is maybe something going on in the python interface layer... I'd be willing to take a look at it if someone could point me to the python interface code (generated, I believe?)

Any help would be greatly appreciated!
Thanks,
Chris

PS this question is a follow-up to my previous question viewtopic.php?f=156&t=169799
in which I was told that this forum is not the ideal place for asking these sorts of questions.
However, I posted my question to https://krita-artists.org last night and as of this morning have not had any replies.
If there is a better place to post these kinds of questions please let me know!
gobber
Registered Member
Posts
8
Karma
0
I've now rebuilt Krita from scratch, using the 4.4.2 branch (commit #16abcfe40464fe5a5a38ad1a9600fb6d77d52f71).

Having had a good look and play around with the code in the setVisibility() method in "libs/libKis/Channel.cpp",
Code: Select all
void Channel::setVisible(bool value)
{
    if (!d->node || !d->channel) return;
    if (!d->node->inherits("KisLayer")) return;

    for (uint i = 0; i < d->node->colorSpace()->channelCount(); ++i) {
        if (d->node->colorSpace()->channels()[i] == d->channel) {
            QBitArray flags = d->node->colorSpace()->channelFlags(true, true);
            flags.setBit(i, value);
            KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data());
            layer->setChannelFlags(flags);
            break;
        }
    }

}

it looks like the attempt to grab the per-channel visibility by calling "QBitArray flags = d->node->colorSpace()->channelFlags(true, true);" is incorrect.
What this does is return the *kinds* of the channels (ie. whether they are colors, or alpha channels), instead of their visibility.

The hint is down where the code sets the visibility by using "layer->setChannelFlags(flags);".
What I think the code should do is to initially grab the channel visibility by calling "layer->channelFlags()" instead.

When I modify the code like this:
Code: Select all
 void Channel::setVisible(bool value)
 {
     if (!d->node || !d->channel) return;
     if (!d->node->inherits("KisLayer")) return;
 
+    KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data());
+    QBitArray flags = layer->channelFlags();
+    if (flags.isEmpty()) {
+        flags.fill(1, d->node->colorSpace()->channelCount());
+    }
+
     for (uint i = 0; i < d->node->colorSpace()->channelCount(); ++i) {
         if (d->node->colorSpace()->channels()[i] == d->channel) {
-            QBitArray flags = d->node->colorSpace()->channelFlags(true, true);
             flags.setBit(i, value);
-            KisLayerSP layer = qobject_cast<KisLayer*>(d->node.data());
             layer->setChannelFlags(flags);
             break;
         }
     }
 
 }

it correctly reads the current state of the channel visibilities, modifies the specified one, and writes them back.
The original python code now works as I believe it should.

I will submit a bug report on kde.org.
User avatar
tymond
KDE Developer
Posts
240
Karma
5
Hi, it means that you basically came up with a patch. Instead of making a bug report, you can submit a patch directly to https://invent.kde.org/graphics/krita :) From the first glance it looks like it *is* the correct behaviour/code (the one after your changes), and the previous one was just a simple mistake.

There is manual for submitting patches here: https://docs.krita.org/en/untranslatabl ... ng-patches (you won't need any more accounts since it uses the same KDE Identity that you need to log into this forum).
gobber
Registered Member
Posts
8
Karma
0
@tymond I've already submitted the bug report, but I will go ahead and see if I can create the fork and submit a pull request as described in the manual. Thanks for your help, I appreciate it!


Bookmarks



Who is online

Registered users: bartoloni, Bing [Bot], Google [Bot], Sogou [Bot], Yahoo [Bot]