Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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

inputfrom
the sub-parts and the silhouette, plus one mask per wordsegment
each group’s completed layer, and the account of what was inventedcomplete
each layer’s lineslines
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 centredthe parts table
outputcontents
the draft’s planone 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 strokesthe long strokes that lay each local colour
the lineseach layer’s lines, copied over from the lines step unchanged
the 1x simulationwhat the plan looks like before Krita ever opens
what Krita producedthe .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:

rulewhat 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-meansin 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 controlsdefaultmeaning
the Shape’s outward expansion1.2how far outside the tidied region the vector outline may sit (px@1x)
fitting the outlines2.0 / 1.5the tolerance the arcs are fitted to, and the blur before fitting
the isoline0.8 / 0.30 / 1.0the blur before the isoline is taken, the simplification tolerance, and how far the silhouette is pushed out
the ground220,220,220 / same as the ground / one paintPath per arcthe 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 runsthe project’s multiplier / onturn 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 decisionhow to make it
which sub-parts make up each groupa 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 colourfront hair and back hair are one colour, not two
which group is cut out of another with a maskits name, which mask, the group it goes after, and the sub-part the mask is intersected with
the sub-parts’ occlusion orderthe 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”.