Selections, filters, erasing, transforms
✅ verified
Selections
from krita import Selection
sel = Selection()
sel.select(x, y, w, h, 255) # a rectangle
sel.setPixelData(mask.tobytes(), 0, 0, w, h) # an arbitrary shape, built with numpy
sel.feather(15); sel.grow(20, 20); sel.shrink(...); sel.border(5, 5)
sel.invert(); sel.smooth(); sel.dilate(); sel.erode()
sel.add(o); sel.subtract(o); sel.intersect(o); sel.symmetricdifference(o)
doc.setSelection(sel)
- A selection confines
paintLine: a rectangle at x in [50,200) lands the stroke in [50,199]; a circle plusfeather(15)feathers 15 outward. All of it exact. - It does not confine
filter.apply(): run a gaussian blur with half the canvas selected and the whole canvas is processed. But the Selection overloads ofcreateFilterMaskandcreateFilterLayerare confined by the selection, feather with it, and are non-destructive (ch. 15). - It cannot keep fractional coverage: feed it a 0-to-255 antialiased mask and what is painted improves only from aliased 100% to 25.5% (boundary-band deviation 0.367 to 0.331, against a vector layer’s 0.083). Do not look to selections for a smooth edge.
- Building one on 8192x12288 takes about 1.1 s, which is the cost of a full-canvas
setPixelData. - There is exactly one way to clear a selection:
doc.setSelection(None).setSelection(Selection())andsel.clear()mean “select nothing”, after which every stroke silently paints 0 px and nothing raises. The symptom is “suddenly no brush works at all”. sel.selectAll()takes two arguments,(node, value).
filter
f = Krita.instance().filter("gaussian blur")
c = f.configuration(); c.setProperty("horizRadius", 25.0); c.setProperty("vertRadius", 25.0)
f.setConfiguration(c)
f.apply(node, x, y, w, h) # it returns None on success too, so check the pixels yourself
52 of them: asc-cdl, autocontrast, blur, burn, colorbalance, colortoalpha, colortransfer, crosschannel, desaturate, dodge, edge detection, emboss (and five more), fastcoloroverlay, gaussian blur, gaussianhighpass, gaussiannoisereducer, gradientmap, halftone, height to normal, hsvadjustment, indexcolors, invert, lens blur, levels, maximize, mean removal, minimize, motion blur, noise, normalize, oilpaint, palettize, perchannel, phongbumpmap, pixelize, posterize, propagatecolors, raindrops, randompick, resettransparent, roundcorners, sharpen, smalltiles, threshold, unsharp, wave, waveletnoisereducer.
Its extent is governed by the box alone, with a knife-cut edge – measuring the blur-strength profile’s 0.9-to-0.1 transition band gives 7.2 px, exactly the criterion’s own floor (what an ideal step reads after the same 9-wide smoothing).
Correction: this used to say that a local filter needing feathering could only be run over the whole canvas and blended back by mask with numpy. That was a conclusion about
apply().doc.createFilterMask(name, f, sel)takes aSelection, wheresel.feather(40)gives a 59.9 px transition band andfeather(120)a 177.7 px one, and it is non-destructive. See ch. 15.
Erasing
The only thing that works is clearing alpha, s.erase(box=, mask=). All three ways of “erasing with a brush” do nothing (ch. 12).
Transforms
Node level, all of which change the bounds: scaleNode(QPointF(cx,cy), w, h, "Bicubic") (QPointF; a QPoint is a TypeError), rotateNode(rad), shearNode, cropNode and move.
Document level: scaleImage(w,h,xres,yres,strategy), rotateImage, shearImage, crop, resizeImage and flatten. The strategies from filterStrategies() are Bell, Bicubic, BSpline, Hermite, Mitchell, Bilinear, Lanczos3 and NearestNeighbor.
scaleImage’s strategy is not validated: pass "xyzzy" and the size changes anyway, by an unknown interpolation. Session.w and h do not follow automatically afterwards; read doc.width() back.
What node-level transforms measure against clipping inside a group, and their non-destructive counterpart the TransformMask, are in ch. 15.
Resources
Krita.instance().resources(type): preset 144, brush 84, gradient 19, pattern 112, palette 13, workspace 9. Any other string returns nothing. createFillLayer(name, "gradient"|"pattern", InfoObject(), sel) lays one as a layer; "simplenoise" segfaults.
Krita.instance().actions() has 688 entries, and any GUI menu item can be .trigger()-ed – the back door to anything the API does not cover, with no return value.
There is no “lay one” API for a gradient or a pattern on a Node; the only way to their rasterized result is Scratchpad.fillGradient and fillPattern (ch. 15).
Other things
- Wrap around:
view.canvas().setWrapAroundMode(True)measurably affects painting, with a stroke past the edge wrapping to the other side. - Animation: it can read and set timeline parameters and import a sequence of frames, but there is no API for creating a keyframe.
- Channel order:
ManagedColor.setComponents,Node.setPixelDataandpixelDataare all BGRA, the first in 0-to-1 floats. Anything the canvas exposes is RGB.