Draft: the layers, the flat colours, each layer’s lines
✅ verified (the flat colours and the tree) · 🧪 in progress (each layer’s lines, ch. 4) · step 5 of the layered route, and the gate · code: appendix B · the probes behind it: appendix C
What this step does
Stack what the first four steps produced into a layer tree a person can use and paint one version for them to look at: every layer named, a whole object (ch. 3), and able to be hidden or edited on its own; each layer’s shape a vector with a flat fill of its local colour inside it – every pixel of that flat colour used to be a stroke too, not a fill; and each layer’s own lines drawn inside its group. Hide the dress and you see a whole leg and the lines on it; hide the body and you see the whole of the back hair. That is the draft: lines plus flat colour. A person looks at it and decides whether to go on to painting (ch. 6), which paints into each of its layers.
Inputs and outputs
| input | from |
|---|---|
| the sub-parts and the silhouette, plus one mask per word | segment |
| each group’s completed layer, and the account of what was invented | complete |
| each layer’s lines | lines |
| which sub-parts make up each group, which groups share a flat colour, which group is cut out of a mask, the occlusion order, and where the close-ups are centred | the parts table |
| output | contents |
|---|---|
| the draft’s plan | one entry per group – its name, its local colour, its outlines and what it fills – plus the names of the line layers, the silhouette, and the close-up boxes |
| the flat strokes | the long strokes that lay each local colour |
| the lines | each layer’s lines, copied over from the lines step unchanged |
| the 1x simulation | what the plan looks like before Krita ever opens |
| what Krita produced | the .kra, the composite, the painting journal, the manifest, one image per stage, and the review images |
The file names are fixed and are all in appendix F; the parts-table fields are in appendix G.
The tree
09_Post/
06_Line/ (left empty; the lines are drawn inside each group)
04_Color/
<group>/ … in GROUPS order, bottom to top; each group inheritAlpha -> silhouette
Shape vector: this layer's whole shape (amodal), fitted cubic beziers,
filled with the flat colour -- this is what owns the edge
<G>_Flat the flat colour: long flat strokes covering it, clip -> Shape
<G>_Line this layer's own lines, not clipped (the outer half of a line has to
show), covered by the groups above it
Subject_Silhouette the vector silhouette, at the bottom of the group
01_BG/
BG_Base the draft's pale grey ground, the one place it writes pixels
Painting (ch. 6) adds _Shade, the named bands, _Blend and _Strand inside each group, and the shape of the tree does not change. The one-shot route’s tree is a different thing (ch. 8).
Four rules. Vectors own the edges and strokes own the interiors (an edge is an analytic curve and resolution-independent; inside it, every pixel is a stroke). Layers may overlap (each group’s Shape is its whole shape, and its lines are drawn inside the group rather than on a top layer). One local colour per group (the value structure comes from the weight of the strokes and from named bands, not from cutting a pile of bands). And an upper Shape may not cover a lower layer’s visible pixels – Shapes are expanded so that neighbouring parts overlap and no ground shows through, but however smooth the expansion, an upper shape then extends a ring beyond the lower one, and covering a lower layer’s visible pixels is painting it out of existence. So the outline is pulled back to the zero isoline wherever it would trespass – the forbidden area being the union of the visible masks of every group below it – and expands as usual everywhere else, so the transition is continuous with no steps. That forbidden area accumulates bottom-up in the groups’ own order, and a completed group traces its outline from its whole shape rather than from what is visible of it.
Clipping is the pivot. Each group is setInheritAlpha(True)-ed to the silhouette, and the flat layer is clipped to the Shape: a vector layer can serve as the base and passes its fractional alpha through to the paint layers above it, so the edge stays analytic. A group must not be passthrough, and the flat layer has to be at the bottom of its group. The three measured rules and their readings are in ch. 13.
Seams. Parts are vectorized separately, so their boundary curves never meet exactly and the black ground shows through at the seam. Splitting alpha between neighbours by coverage (0.5 each) is the wrong road: Krita composites alpha-over rather than as a weighted sum, so two layers at 0.5 leave 25% of the background, which on a pure black ground is a string of black dots. The right way is the artist’s: every part is opaque in itself, its Shape is expanded by shape_expand (1.2 px; too small and a sliver of black ground shows between the outline and the fill), and the occlusion order lets the upper one cover the lower. The bulge that creates is cut off by clipping the parts group to the silhouette, and the background fills the whole canvas on the bottom layer (ch. 6).
Fitted rings. A Shape’s rings and its lines use the same fit (ch. 2): a fitted line sits at most 3 px@1x from the mask’s edge, and a Shape fitted any other way leaves the line and the fill’s edge out of register. Alpha is solved on “the source, with the completed image substituted only in the invented region”; solving it on the completed image throughout shifts the visible part’s edge by 1 px.
Flat colour
The local colour is the modal cell of the 16-cubed RGB histogram of the brighter half of that area’s pixels, taking the mean of the pixels in that cell. Two more intuitive rules both get it wrong:
| rule | what it gets wrong |
|---|---|
| the median colour of the brightest 40% | a saturated red comes out as the pink of its highlight |
| the largest band by area from k-means | in a part with a gradient, one end of the gradient has the largest area and the whole part takes that colour |
The modal cell gets both right. “Only the brighter half” is because the local colour is the colour of the lit side, and shadows and the dark end of a gradient do not count.
Clustering. Members of a group whose colours are far apart each get their own path: a chroma difference above 30 splits them (several ribbons of different colours in one group each get their own colour), while a member that is merely darker because it is in shadow does not split. Groups a person marked as sharing a colour take one between them (front and back hair are the same hair, and an artist picks one colour for both).
The flat colour is that vector shape, with no strokes at all. There used to be a filling pass here: scanning the mask along its principal axis at a fixed spacing and then patching the holes with a small brush, more than thirteen hundred strokes a picture. Those strokes drew nothing new – the Shape vector layer had already filled the same area with analytic bezier rings, whose boundary deviation of 0.0828 is the best edge in the library and independent of resolution. What forced it to be covered was the old criterion “strokes cover at least 95% of the Shape”, a ruler that measures whether it was filled rather than whether it was right; both were deleted together (ch. 7).
So <G>_Flat is now empty and therefore does not enter the layer tree (stages/tree.prune). The draft’s tree fell from four nodes per group to three.
Each layer’s lines
Ch. 4’s lines were arbitrated per layer and each carries a group, so this step only checks the group names (a mismatch is an error outright: lines and draft read different segment or complete steps). The lines are drawn into <G>_Line, not clipped to the Shape (the outer half of a line has to show), and covered by the groups above – a line on a leg under the skirt is invisible until the dress is hidden. Lines in the invented region (made_up >= 0.5) are counted separately in the README.
Knobs
| what it controls | default | meaning |
|---|---|---|
| the Shape’s outward expansion | 1.2 | how far outside the tidied region the vector outline may sit (px@1x) |
| fitting the outlines | 2.0 / 1.5 | the tolerance the arcs are fitted to, and the blur before fitting |
| the isoline | 0.8 / 0.30 / 1.0 | the blur before the isoline is taken, the simplification tolerance, and how far the silhouette is pushed out |
| the ground | 220,220,220 / same as the ground / one paintPath per arc | the draft’s background colour, what colour the silhouette is filled with, and how lines are drawn (the alternative tapers both ends) |
| the multiplier, and whether Krita runs | the project’s multiplier / on | turn the job off and the step produces only the plan and the 1x simulation |
The constant names are at the top of this stage’s main.py and are listed in appendix A.
What a person decides here
| the decision | how to make it |
|---|---|
| which sub-parts make up each group | a group is the union of some sub-parts; the order is bottom to top, which is the occlusion order, the order of the groups in the .kra, and who occludes whom during completion. Anything you want filled as its own colour has to be a separate sub-part, since the clustering works on members |
| which groups share one local colour | front hair and back hair are one colour, not two |
| which group is cut out of another with a mask | its name, which mask, the group it goes after, and the sub-part the mask is intersected with |
| the sub-parts’ occlusion order | the same order ch. 1 established; the one-shot route’s tree follows it too |
The field names, their formats and the step to rerun after each change are in appendix G.
Reviewing and overruling
This is the gate, and everything to look at is in the review images the painting wrote (appendix F): each layer’s flat colour on grey, to see the coverage and where the holes are; each group rendered alone with nothing over it – “is the kettle whole”, and where the hidden lines can be seen; the 1x composite, to check the local colours (a saturated thing must not come out as its highlight, and a gradient thing has to take its dominant colour); the 1:1 close-ups, centred where the parts table says, at least the face, the neck, a hand and a foot; and the manifest, for the whole tree at a glance. Look for: whether the group order is right (the upper covering the lower), whether each group is a whole object, whether each line is on the layer it belongs to, and whether there is any layer you cannot name.
What to change: the order, and which sub-parts make up a group, or which group is cut out of a mask (appendix G); a wrong colour -> whether that area should be two sub-parts; insufficient coverage -> usually fine structure, so check whether the second pass filled it; a wrong line -> ch. 4’s overrides.json; a wrong invented shape -> ch. 3. The verdict goes at the end of the step’s README.
Where it breaks
- An upper Shape covering a ring of the lower one: the expansion had no
forbid. - Judging clipping by RGB alone: it concludes “not clipped” (ch. 13).
- A passthrough group: clipping stops working, and a multiply inside the group no longer multiplies what is under the group either.
- Splitting alpha at a seam: a string of black dots.
- The median colour coming out as the highlight and k-means’ largest band pulling it off (the table above); and the brightest band is not necessarily Light (on a white part).
- Fine things not getting filled: the big scanning strokes skip them, and the perpendicular second pass catches them.
- Local colours disagreeing across groups: front and back hair sampled separately differ slightly, which is what the shared-colour decision is for.
- Node explosion: one node per part per k-means band, with meaningless names – such a tree is “a great many layers no human ever wanted” (which is by design what ch. 8’s tree is).
On origin
The number of groups, each group’s local colour and clustering, the number of flat strokes, the coverage, the node count, the .kra’s size, and the images of each group rendered alone: ch. 19, “The layered route”.