Theory and Practice of Sprixels: Difference between revisions

Line 84: Line 84:


==The T-A Matrix==
==The T-A Matrix==
Associated with a sprixel (technically with the plane on which the sixel is blitted, so it can be reused across frames) is a "transparency-annihilation matrix" having dimensions equivalent to the sprixel's area in cells. These matrix entries are loaded when the sprixel is first encoded, as either 0 (a wholly <b>opaque</b> cell) or 1 (a cell region with at least one <b>transparent</b> pixel). These values are used to determine whether or not a cell <i>underneath</i> the sprixel needs be updated to reflect a change in the render; if the cell is entirely obscured by the sprixel, there's no need to change the text in the cell (and this saves us an expensive redraw when using Sixel). When we cut out a cell, the T-A matrix takes the value 2 (<b>annihilation</b>). Only with Kitty do we actually cut the cell out of the encoded glyph (which we then delete and replay), but we always want to track this, because we often reuse the T-A matrix across frames. When we encode an image with a preseeded T-A matrix in hand, we implicitly drop the annihilated pixels. Using this method, we never obscure text atop a series of frames, eliminating flicker we would otherwise suffer.
Associated with a sprixel (technically with the plane on which the sixel is blitted, so it can be reused across frames) is a "transparency-annihilation matrix" having dimensions equivalent to the sprixel's area in cells. These matrix entries are loaded when the sprixel is first encoded, as one of:
 
* 0 (a wholly <b>opaque</b> cell)
* 1 (a cell region with both <b>transparent and opaque</b> pixels)
* 2 (a wholly <b>transparent</b> cell, <b>in Kitty</b>)
 
Each has different properties. The wholly opaque cell obstructs text underneath it entirely, so we can elide updates to such text. We can update the text underneath a wholly transparent cell in Kitty without an expensive repaint of the bitmap. A mixed cell's most interesting property is that it has no interesting properties.
 
When we cut out a cell (to print text above the bitmap), the T-A matrix takes the value 3 (<b>annihilation</b>). Only with Kitty do we actually cut the cell out of the encoded glyph (which we then delete and replay), but we always want to track this, because we often reuse the T-A matrix across frames. When we encode an image with a preseeded T-A matrix in hand, we implicitly drop the annihilated pixels. Using this method, we never obscure text atop a series of frames, eliminating flicker we would otherwise suffer.


As you might have already guessed, the cut vector mentioned above is hung off the T-A matrix (though it must be refreshed on each frame change). When an annihilated cell is uncovered, it must be reconstructed; the T-A matrix value is changed to 4 (<b>anastasis</b>). At render time, the resurrected cell can either be rebuilt using the cut vector directly into the image (Kitty), or the Sixel-based sprixel can be reconstructed <i>in toto</i>. It might be desirable to revive into cell-sized sprixels, but see below. Either way, following reconstruction, the TAM entry returns to 0 or 1.
As you might have already guessed, the cut vector mentioned above is hung off the T-A matrix (though it must be refreshed on each frame change). When an annihilated cell is uncovered, it must be reconstructed; the T-A matrix value is changed to 4 (<b>anastasis</b>). At render time, the resurrected cell can either be rebuilt using the cut vector directly into the image (Kitty), or the Sixel-based sprixel can be reconstructed <i>in toto</i>. It might be desirable to revive into cell-sized sprixels, but see below. Either way, following reconstruction, the TAM entry returns to 0 or 1.