Unfill Shape proof of concept ( for working with onion skins )

Hi there,
I’m very new to scripting with Krita so this could probably use some TLC!
Here’s a work around for this feature request:
onion skinning for solid shapes

I cobbled together a script that takes a node and cuts out the pixels offset from the border so you can see the “line work” in the onion skins. This is really nice for adjusting spacing and can be filled back up no problem.

Questions / Quirks:

  • Onion skin has to be less than 250 opacity <— wondering if there is a way to exclude onion skins from a selction instead of filtering out by opacity?
  • Could just turn onion skin off before running the function but I couldn’t find a way to query if it’s enabled. I was hoping to find something like this but couldn’t figure it out.
Krita.instance().activeDocument().activeNode.isOnionSkinned()
  • Currently only works on filled shapes with 100% opacity pixels because of the aforementioned opacity comparison.

PeteNichols_Unfill

from krita import *
#A script to cut out the center of a filled shape so that you can see spacing better with the onion skin docker.
#Go to the frame and layer you want run the script and your left with an outline that you can see properly in the onion skin
#Just fill it back up when your done with the bucket tool

##------IMPORTANT!!!!!--------## Make sure onion skin opacity is less than 95% ish

#TIP: when refilling set your bucket tool to grow by 1px ish to get rid of any artifacts
#To add it to your project just go to tools -> scripts -> ten scripts-> click the elipse next to the hot key you want
#-> navigate to the script and your done!
def unfill_layer( stroke_weight = 5 ):
    doc=Krita.instance().activeDocument()
    if doc: 
    	node=doc.activeNode()
    else:
    	return
    
    x,y,w,h = node.bounds().left(), node.bounds().top(), node.bounds().width(), node.bounds().height()
    pixels=node.projectionPixelData(x,y,w,h)
    
    rgba = 0
    pixelBytes=[]
    for i in range(w*h):
        if pixels[rgba + 3] > int(250).to_bytes(1,'big'):
            pixelBytes.append(255)
        else:
            pixelBytes.append(0)   
        rgba+=4 
    selection = Selection()
    selection.setPixelData(QByteArray(bytes(pixelBytes)),x,y,w,h)
    
    for i in range(stroke_weight):
        selection.erode()
        
    doc.setSelection(selection)
    selection.cut(node) 
    doc.setSelection(Selection().clear())
    doc.refreshProjection()


stroke = 5  #<----------Changes width of left over outline    
unfill_layer(stroke_weight = stroke)

Anyways I’m developing a plug-in for animation clean up and planning to add this but I wanted to get it out there in it’s current format since I know other animators might find it useful.
Thanks!

10 Likes