src/jpeg_enc.bend checks
raw source on the hub · import 0x57618559b9b26dd8415f821176a3e692/src/jpeg_enc.bend as Jpeg_enc
src/jpeg_enc: baseline JPEG encode. Sequential 8-bit Huffman (SOF0) and JFIF APP0. Colour is 4:4:4 YCbCr, no subsampling: one 8 by 8 block per component per MCU. Samples are packed 0xAARRGGBB, the layout decode returns; the alpha byte is ignored. Quantisation steps are all 1, so an integer coefficient is kept whole. The forward DCT (T.81 A.3.3) pairs samples that share a cosine weight, then rounds once with the same fixed-point product as a matrix column. Both components share the Annex K luminance Huffman tables. A coefficient indexes its symbol. The scan does not walk the table. A mixed MCU reads each pixel once and keeps the three level planes in arrays. Quant steps are 1, so the mixed scan emits coefficients without dividing. A neutral solid (R = G = B = 128) is an all-zero block and round-trips exactly. Other colours are lossy. Progressive and arithmetic frames are not written. Width and height must sit in 1..65535; anything else is SOI then EOI.
2 imports
import Base import ./jpeg.bend as Jpeg
Types
type Put source · line 19 · raw
Data
bytes emitted so far (newest first), the open byte, and how many bits it holds
Put@out:List<&2, U32> -> @buf:U32 -> @n:U32 -> Put
type Kern source · line 23 · raw
Data
cosine weights shared by symmetric samples: DC, two even weights, four odd weights
Kern@k0:U32 -> @k2:U32 -> @k6:U32 -> @o0:U32 -> @o1:U32 -> @o2:U32 -> @o3:U32 -> Kern
type Ctx source · line 27 · raw
Data
the cosine kernel, zigzag, and the all-ones quant table
Ctx@kern:Kern -> @zig:List<&2, U32> -> @quant:List<&2, U32> -> Ctx
type Book source · line 31 · raw
Type
DC and AC symbols indexed to a packed code: length in the high half, code in the low half
Book@dc:Array<U32> -> @ac:Array<U32> -> Book
type Code source · line 35 · raw
Data
one looked-up Huffman code
Code@len:U32 -> @bits:U32 -> Code
type Oct source · line 39 · raw
Data
eight values, the first at frequency 0
Oct@f0:U32 -> @f1:U32 -> @f2:U32 -> @f3:U32 -> @f4:U32 -> @f5:U32 -> @f6:U32 -> @f7:U32 -> Oct
type Planes source · line 43 · raw
Type
the sample plane, the frequency plane, and the next column of one forward DCT
Planes@src:Array<U32> -> @dst:Array<U32> -> @at:U32 -> Planes
type Tile source · line 47 · raw
Type
one MCU: packed pixels, three level planes, and whether each plane is the neutral level
Tile@pix:Array<U32> -> @ys:Array<U32> -> @bs:Array<U32> -> @rs:Array<U32> -> @fy:Bool -> @fb:Bool -> @fr:Bool -> Tile
type Scan source · line 51 · raw
Type
frequency plane, the open zero run, and the AC coder. Steps are 1, so no quant list.
Scan@arr:Array<U32> -> @run:U32 -> @ac:Array<U32> -> @bit:Put -> Scan
Definitions
def encode.join source · line 54 · raw
@aa:List<&2, U32> -> @bb:List<&2, U32> -> List<&2, U32>
def encode.len source · line 57 · raw
@xs:List<&2, U32> -> U32
def encode.seg source · line 60 · raw
@+mark:U32 -> @+body:List<&2, U32> -> List<&2, U32>
def encode.app0 source · line 64 · raw
List<&2, U32>
def encode.quant source · line 67 · raw
List<&2, U32>
def encode.dqt source · line 70 · raw
List<&2, U32>
def encode.sofbody source · line 73 · raw
@+ww:U32 -> @+hh:U32 -> List<&2, U32>
def encode.sof source · line 76 · raw
@+ww:U32 -> @+hh:U32 -> List<&2, U32>
def encode.dccounts source · line 79 · raw
List<&2, U32>
def encode.dcsyms source · line 82 · raw
List<&2, U32>
def encode.accounts source · line 85 · raw
List<&2, U32>
def encode.acsyms source · line 88 · raw
List<&2, U32>
def encode.dht source · line 97 · raw
@+cls:U32 -> @+counts:List<&2, U32> -> @+syms:List<&2, U32> -> List<&2, U32>
def encode.sos source · line 100 · raw
List<&2, U32>
def encode.header source · line 103 · raw
@+ww:U32 -> @+hh:U32 -> @+dcc:List<&2, U32> -> @+dcs:List<&2, U32> -> @+acc:List<&2, U32> -> @+acs:List<&2, U32> -> List<&2, U32>
def encode.kern source · line 115 · raw
@+cs:List<&2, U32> -> Kern
C[0][0], C[0][2], C[0][6], and the first four weights of frequency 1
def encode.kern.drop source · line 119 · raw
@kern:Kern -> U32
def encode.ctx source · line 131 · raw
Ctx
def encode.word source · line 135 · raw
@+len:U32 -> @+code:U32 -> U32
length sits above the 16-bit code
def encode.bad.b source · line 138 · raw
@bw:Bool -> @bh:Bool -> Bool
def encode.bad.h source · line 145 · raw
@zz:Bool -> @bw:Bool -> @bh:Bool -> Bool
def encode.bad.w source · line 152 · raw
@zz:Bool -> @zh:Bool -> @bw:Bool -> @bh:Bool -> Bool
def encode.bad source · line 159 · raw
@+ww:U32 -> @+hh:U32 -> Bool
def encode.put0 source · line 162 · raw
Put
def encode.stuff source · line 166 · raw
@out:List<&2, U32> -> @+bb:U32 -> Put
a finished byte. Bytes are kept as written; encode.pad stuffs them once, at the end.
def encode.bit.n source · line 169 · raw
@full:Bool -> @out:List<&2, U32> -> @+nb:U32 -> @+nn:U32 -> Put
def encode.bit source · line 176 · raw
@pp:Put -> @+bit:U32 -> Put
def encode.bits.go source · line 181 · raw
@left:Nat -> @pp:Put -> @+code:U32 -> Put
def encode.bits source · line 189 · raw
@pp:Put -> @+len:U32 -> @+code:U32 -> Put
def encode.stuff.put source · line 193 · raw
@ff:Bool -> @+bb:U32 -> @acc:List<&2, U32> -> List<&2, U32>
one byte put in front of the stuffed bytes after it: 255 is followed by a 0
def encode.stuff.all source · line 202 · raw
@out:List<&2, U32> -> @acc:List<&2, U32> -> List<&2, U32>
the written bytes, newest first, stuffed and put in order onto acc: every 255 is followed by a 0 (T.81 F.1.2.3). U32.is_eq, not a literal pattern, so a law reaches a symbolic byte.
def encode.pad.n source · line 209 · raw
@zz:Bool -> @out:List<&2, U32> -> @+buf:U32 -> @+nn:U32 -> List<&2, U32>
def encode.pad source · line 218 · raw
@pp:Put -> List<&2, U32>
the entropy-coded bytes: the open byte padded with 1 bits, then every byte stuffed, in order
def encode.drop source · line 223 · raw
@xs:List<&2, U32> -> U32
def encode.fill source · line 227 · raw
@syms:List<&2, U32> -> @codes:List<&2, U32> -> @lens:List<&2, U32> -> @aa:Array<U32> -> Array<U32>
one canonical table, stored so the symbol is the index
def encode.huff.of source · line 250 · raw
@hh:0x57618559b9b26dd8415f821176a3e692/src/jpeg.Huff -> Array<U32>
def encode.huff source · line 255 · raw
@+counts:List<&2, U32> -> @+syms:List<&2, U32> -> Array<U32>
def encode.book source · line 258 · raw
@+dcc:List<&2, U32> -> @+dcs:List<&2, U32> -> @+acc:List<&2, U32> -> @+acs:List<&2, U32> -> Book
def encode.cat.pick source · line 262 · raw
@lt:Bool -> @+cc:U32 -> @+rest:U32 -> U32
the first of two sizes when the value is below the limit, else the second
def encode.cat.go source · line 273 · raw
@left:Nat -> @+aa:U32 -> @+cc:U32 -> @+lim:U32 -> U32
the size of a magnitude: the first cc with aa below lim = 2^cc, left sizes tried, else cc. Each comparison is made with a constant limit, so a law over a symbolic value keeps one comparison per size.
def encode.cat source · line 282 · raw
@+vv:U32 -> U32
def encode.mag.s source · line 285 · raw
@+ss:U32 -> @+cat:U32 -> @+vv:U32 -> U32
def encode.mag source · line 292 · raw
@+cat:U32 -> @+vv:U32 -> U32
def encode.magp.z source · line 295 · raw
@zz:Bool -> @pp:Put -> @+cat:U32 -> @+vv:U32 -> Put
def encode.coded source · line 303 · raw
@got:Pair(Array<U32>, U32) -> Pair(Array<U32>, Code)
the indexed word is the length and the code
def encode.sym source · line 307 · raw
@aa:Array<U32> -> @+sym:U32 -> Pair(Array<U32>, Code)
def encode.dc.use source · line 310 · raw
@got:Pair(Array<U32>, Code) -> @pp:Put -> @+cat:U32 -> @+diff:U32 -> Pair(Array<U32>, Put)
def encode.dc source · line 315 · raw
@aa:Array<U32> -> @+pp:Put -> @+diff:U32 -> Pair(Array<U32>, Put)
def encode.clip.hi source · line 319 · raw
@hi:Bool -> @+vv:U32 -> @+lim:U32 -> U32
def encode.clip.lo source · line 326 · raw
@lo:Bool -> @+vv:U32 -> @+lim:U32 -> U32
def encode.clip.b source · line 334 · raw
@pos:Bool -> @+vv:U32 -> @+lim:U32 -> U32
by the sign, asked with U32.is_eq so a law reaches a symbolic value
def encode.clip source · line 341 · raw
@+vv:U32 -> @+lim:U32 -> U32
def encode.dcbias.b source · line 347 · raw
@pos:Bool -> @+vv:U32 -> U32
a DC clipped to T.81's range for 8-bit samples, -1024 to 1023, kept as that plus 1024 (0 to 2047), so the difference of two DCs has at most 11 bits (F.1.2.1) and is found without wrapping. The level shift keeps the forward DCT's DC in -1024..1015, so the clip never changes it.
def encode.dcbias source · line 355 · raw
@+vv:U32 -> U32
a DC clipped to -1024 to 1023, plus 1024
def encode.magp.n source · line 359 · raw
@zz:Bool -> @pp:Put -> @+cat:U32 -> @+mm:U32 -> Put
a negative DC difference -mm: its size's code, then its magnitude bits, 2^size - 1 - mm (F.1.2.1)
def encode.dc.use.neg source · line 368 · raw
@got:Pair(Array<U32>, Code) -> @pp:Put -> @+cat:U32 -> @+mm:U32 -> Pair(Array<U32>, Put)
the size's code of a negative DC difference, then its magnitude
def encode.dc.neg source · line 374 · raw
@aa:Array<U32> -> @+pp:Put -> @+mm:U32 -> Pair(Array<U32>, Put)
a negative DC difference, -mm
def encode.dcdiff.b source · line 379 · raw
@up:Bool -> @aa:Array<U32> -> @pp:Put -> @+bb:U32 -> @+pb:U32 -> Pair(Array<U32>, Put)
the DC difference of two biased DCs, by its sign
def encode.dcdiff source · line 387 · raw
@aa:Array<U32> -> @pp:Put -> @+bb:U32 -> @+pb:U32 -> Pair(Array<U32>, Put)
the DC difference of biased DC bb from biased predictor pb
def encode.emit source · line 390 · raw
@got:Pair(Array<U32>, Code) -> @pp:Put -> Pair(Array<U32>, Put)
def encode.eob source · line 395 · raw
@need:Bool -> @aa:Array<U32> -> @pp:Put -> Pair(Array<U32>, Put)
def encode.eob.on source · line 402 · raw
@need:Bool -> @st:Pair(Array<U32>, Put) -> Pair(Array<U32>, Put)
def encode.zrls.one source · line 407 · raw
@st:Pair(Array<U32>, Put) -> Pair(Array<U32>, Put)
def encode.zrls source · line 412 · raw
@left:Nat -> @st:Pair(Array<U32>, Put) -> Pair(Array<U32>, Put)
def encode.ac.mag source · line 419 · raw
@got:Pair(Array<U32>, Put) -> @+cat:U32 -> @+clip:U32 -> Pair(Array<U32>, Put)
def encode.ac.hit source · line 424 · raw
@got:Pair(Array<U32>, Put) -> @+sym:U32 -> @+cat:U32 -> @+clip:U32 -> Pair(Array<U32>, Put)
def encode.ac.step source · line 429 · raw
@+cc:U32 -> @+run:U32 -> @st:Pair(Array<U32>, Put) -> Pair(Array<U32>, Put)
def encode.ac.run source · line 438 · raw
@zero:Bool -> @+run:U32 -> U32
the zero run after one more coefficient
def encode.ac.at source · line 447 · raw
@zero:Bool -> @+cc:U32 -> @+run:U32 -> @st:Pair(Array<U32>, Put) -> Pair(Array<U32>, Put)
one more coefficient: a zero only lengthens the run
def encode.ac source · line 456 · raw
@zz:List<&2, U32> -> @+run:U32 -> @st:Pair(Array<U32>, Put) -> Pair(Array<U32>, Put)
the AC coefficients in zigzag order. U32.is_eq, not a literal pattern, so a law reaches a symbolic coefficient.
def encode.qnz source · line 463 · raw
@+qq:U32 -> U32
def encode.qdiv.s source · line 470 · raw
@+ss:U32 -> @+vv:U32 -> @+qq:U32 -> U32
def encode.qdiv source · line 477 · raw
@+vv:U32 -> @+qq:U32 -> U32
def encode.block.join source · line 480 · raw
@got:Pair(Array<U32>, Put) -> @dc2:Array<U32> -> @+dd:U32 -> Pair(Book, Pair(U32, Put))
def encode.block.dc source · line 484 · raw
@got:Pair(Array<U32>, Put) -> @ac:Array<U32> -> @+dd:U32 -> @rest:List<&2, U32> -> Pair(Book, Pair(U32, Put))
def encode.block.ac source · line 490 · raw
@book:Book -> @pp:Put -> @+pred:U32 -> @+dc0:U32 -> @rest:List<&2, U32> -> Pair(Book, Pair(U32, Put))
the DC, clipped to T.81's 8-bit range and biased by 1024, is written as its difference from the last and kept, so the next block can predict from it
def encode.block.go source · line 496 · raw
@book:Book -> @pp:Put -> @+pred:U32 -> @zz:List<&2, U32> -> Pair(Book, Pair(U32, Put))
def encode.add64.acc source · line 503 · raw
@+ph:U32 -> @+pl:U32 -> @acc:Pair(U32, U32) -> Pair(U32, U32)
def encode.add64 source · line 510 · raw
@prod:Pair(U32, U32) -> @acc:Pair(U32, U32) -> Pair(U32, U32)
add a signed product onto a 64-bit accumulator
def encode.mac source · line 516 · raw
@+coef:U32 -> @+samp:U32 -> @acc:Pair(U32, U32) -> Pair(U32, U32)
one more product on the accumulator
def encode.q17 source · line 520 · raw
@acc:Pair(U32, U32) -> U32
the same rounding the matrix product applies to a finished sum
def encode.scale source · line 525 · raw
@+coef:U32 -> @+samp:U32 -> U32
def encode.two source · line 528 · raw
@+c0:U32 -> @+x0:U32 -> @+c1:U32 -> @+x1:U32 -> U32
def encode.two.n source · line 531 · raw
@+c0:U32 -> @+x0:U32 -> @+c1:U32 -> @+x1:U32 -> U32
def encode.four source · line 534 · raw
@+c0:U32 -> @+s0:U32 -> @+c1:U32 -> @+s1:U32 -> @+c2:U32 -> @+s2:U32 -> @+c3:U32 -> @+s3:U32 -> U32
def encode.even source · line 538 · raw
@+s0:U32 -> @+s1:U32 -> @+s2:U32 -> @+s3:U32 -> @+s4:U32 -> @+s5:U32 -> @+s6:U32 -> @+s7:U32 -> @+k0:U32 -> @+k2:U32 -> @+k6:U32 -> Oct
even frequencies: symmetric samples share one weight
def encode.odd source · line 561 · raw
@+d0:U32 -> @+d1:U32 -> @+d2:U32 -> @+d3:U32 -> @+o0:U32 -> @+o1:U32 -> @+o2:U32 -> @+o3:U32 -> Oct
odd frequencies: antisymmetric samples share one weight
def encode.dct8.od source · line 568 · raw
@+f0:U32 -> @+f2:U32 -> @+f4:U32 -> @+f6:U32 -> @od:Oct -> Oct
def encode.dct8.at source · line 574 · raw
@ev:Oct -> @od:Oct -> Oct
def encode.dct8.k source · line 580 · raw
@+s0:U32 -> @+s1:U32 -> @+s2:U32 -> @+s3:U32 -> @+s4:U32 -> @+s5:U32 -> @+s6:U32 -> @+s7:U32 -> @kern:Kern -> Oct
def encode.dct8 source · line 597 · raw
@samp:Oct -> @kern:Kern -> Oct
one 8-point transform. Pairing is the matrix product, so the rounded value matches.
def encode.take source · line 602 · raw
@row:List<&2, U32> -> Oct
def encode.put8 source · line 610 · raw
@+f0:U32 -> @+f1:U32 -> @+f2:U32 -> @+f3:U32 -> @+f4:U32 -> @+f5:U32 -> @+f6:U32 -> @+f7:U32 -> @aa:Array<U32> -> @+at:U32 -> @+step:U32 -> Array<U32>
def encode.lay source · line 633 · raw
@oo:Oct -> @aa:Array<U32> -> @+at:U32 -> Array<U32>
def encode.scatter source · line 638 · raw
@oo:Oct -> @aa:Array<U32> -> @+at:U32 -> Array<U32>
def encode.oct.pack source · line 643 · raw
@+s0:U32 -> @+s1:U32 -> @+s2:U32 -> @+s3:U32 -> @+s4:U32 -> @+s5:U32 -> @+s6:U32 -> @+s7:U32 -> @aa:Array<U32> -> Pair(Array<U32>, Oct)
def encode.oct.g7 source · line 656 · raw
@got:Pair(Array<U32>, U32) -> @+s0:U32 -> @+s1:U32 -> @+s2:U32 -> @+s3:U32 -> @+s4:U32 -> @+s5:U32 -> @+s6:U32 -> Pair(Array<U32>, Oct)
def encode.oct.g6 source · line 669 · raw
@got:Pair(Array<U32>, U32) -> @+s0:U32 -> @+s1:U32 -> @+s2:U32 -> @+s3:U32 -> @+s4:U32 -> @+s5:U32 -> @+i7:U32 -> Pair(Array<U32>, Oct)
def encode.oct.g5 source · line 682 · raw
@got:Pair(Array<U32>, U32) -> @+s0:U32 -> @+s1:U32 -> @+s2:U32 -> @+s3:U32 -> @+s4:U32 -> @+i6:U32 -> @+i7:U32 -> Pair(Array<U32>, Oct)
def encode.oct.g4 source · line 695 · raw
@got:Pair(Array<U32>, U32) -> @+s0:U32 -> @+s1:U32 -> @+s2:U32 -> @+s3:U32 -> @+i5:U32 -> @+i6:U32 -> @+i7:U32 -> Pair(Array<U32>, Oct)
def encode.oct.g3 source · line 708 · raw
@got:Pair(Array<U32>, U32) -> @+s0:U32 -> @+s1:U32 -> @+s2:U32 -> @+i4:U32 -> @+i5:U32 -> @+i6:U32 -> @+i7:U32 -> Pair(Array<U32>, Oct)
def encode.oct.g2 source · line 721 · raw
@got:Pair(Array<U32>, U32) -> @+s0:U32 -> @+s1:U32 -> @+i3:U32 -> @+i4:U32 -> @+i5:U32 -> @+i6:U32 -> @+i7:U32 -> Pair(Array<U32>, Oct)
def encode.oct.g1 source · line 734 · raw
@got:Pair(Array<U32>, U32) -> @+s0:U32 -> @+i2:U32 -> @+i3:U32 -> @+i4:U32 -> @+i5:U32 -> @+i6:U32 -> @+i7:U32 -> Pair(Array<U32>, Oct)
def encode.oct.g0 source · line 747 · raw
@got:Pair(Array<U32>, U32) -> @+i1:U32 -> @+i2:U32 -> @+i3:U32 -> @+i4:U32 -> @+i5:U32 -> @+i6:U32 -> @+i7:U32 -> Pair(Array<U32>, Oct)
def encode.oct.stride source · line 761 · raw
@aa:Array<U32> -> @+at:U32 -> @+step:U32 -> Pair(Array<U32>, Oct)
eight samples starting at at, every step slots
def encode.col.use source · line 771 · raw
@got:Pair(Array<U32>, Oct) -> @kern:Kern -> Pair(Array<U32>, Oct)
def encode.col source · line 777 · raw
@arr:Array<U32> -> @+at:U32 -> @kern:Kern -> Pair(Array<U32>, Oct)
one frequency column, read straight from the plane
def encode.pass1 source · line 780 · raw
@rows:List<&2, List<&2, U32>> -> @+kern:Kern -> @arr:Array<U32> -> @+at:U32 -> Array<U32>
def encode.pix.sink source · line 788 · raw
@aa:Array<U32> -> U32
def encode.book.sink source · line 795 · raw
@book:Book -> U32
def encode.pass2.done source · line 800 · raw
@st:Planes -> @kern:Kern -> Array<U32>
def encode.pass2.put source · line 808 · raw
@got:Pair(Array<U32>, Oct) -> @dst:Array<U32> -> @+at:U32 -> Planes
def encode.pass2.step source · line 813 · raw
@st:Planes -> @kern:Kern -> Planes
def encode.pass2 source · line 818 · raw
@left:Nat -> @st:Planes -> @+kern:Kern -> Array<U32>
def encode.pass.rows.done source · line 825 · raw
@st:Planes -> @kern:Kern -> Array<U32>
def encode.pass.rows.lay source · line 833 · raw
@got:Pair(Array<U32>, Oct) -> @+kern:Kern -> @dst:Array<U32> -> @+at:U32 -> Planes
def encode.pass.rows.next source · line 838 · raw
@st:Planes -> @+kern:Kern -> Planes
def encode.pass.rows source · line 844 · raw
@left:Nat -> @st:Planes -> @+kern:Kern -> Array<U32>
eight row transforms. left rows are still unread.
def encode.pass.mid source · line 851 · raw
@src:Array<U32> -> @+kern:Kern -> Array<U32>
def encode.freq source · line 855 · raw
@src:Array<U32> -> @+kern:Kern -> Array<U32>
level plane in, natural-order frequencies out
def encode.drain.pack source · line 858 · raw
@got:Pair(Array<U32>, U32) -> @acc:List<&2, U32> -> Pair(Array<U32>, Pair(U32, List<&2, U32>))
def encode.drain.step source · line 863 · raw
@st:Pair(Array<U32>, Pair(U32, List<&2, U32>)) -> @+idx:Nat -> Pair(Array<U32>, Pair(U32, List<&2, U32>))
def encode.drain.done source · line 867 · raw
@st:Pair(Array<U32>, Pair(U32, List<&2, U32>)) -> List<&2, U32>
def encode.drain source · line 873 · raw
@left:Nat -> @st:Pair(Array<U32>, Pair(U32, List<&2, U32>)) -> List<&2, U32>
read index 63 first, so the cons list comes out in order
def encode.drain.st source · line 880 · raw
@got:Pair(Array<U32>, U32) -> Pair(Array<U32>, Pair(U32, List<&2, U32>))
def encode.fdct.go source · line 885 · raw
@src:Array<U32> -> @kern:Kern -> List<&2, U32>
def encode.fdct source · line 888 · raw
@rows:List<&2, List<&2, U32>> -> @+cs:List<&2, U32> -> List<&2, U32>
def encode.level source · line 892 · raw
@xs:List<&2, U32> -> List<&2, U32>
def encode.levels source · line 899 · raw
@rows:List<&2, List<&2, U32>> -> List<&2, List<&2, U32>>
def encode.sat source · line 906 · raw
@over:Bool -> @+xx:U32 -> @+lim:U32 -> U32
def encode.sat8 source · line 913 · raw
@over:Bool -> @+vv:U32 -> U32
def encode.y source · line 920 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.cb source · line 923 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.cr source · line 926 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.ych source · line 929 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.cbch source · line 933 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.crch source · line 937 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.chan.w source · line 941 · raw
@+ch:U32 -> @+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.chan source · line 950 · raw
@+pix:U32 -> @+ch:U32 -> U32
def encode.pix.load source · line 954 · raw
@left:Nat -> @px:List<&2, U32> -> @aa:Array<U32> -> @+ii:U32 -> Array<U32>
the first left samples, then the rest of the list is unused
def encode.sample.use source · line 964 · raw
@got:Pair(Array<U32>, U32) -> @+ch:U32 -> Pair(Array<U32>, U32)
def encode.sample source · line 969 · raw
@aa:Array<U32> -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> @+ch:U32 -> Pair(Array<U32>, U32)
one index into the sample array, instead of a walk from the head of the list
def encode.flat.both source · line 974 · raw
@aa:Bool -> @bb:Bool -> Bool
both samples are the neutral level
def encode.rowpix.step source · line 983 · raw
@+ss:U32 -> @got:Pair(Array<U32>, Pair(List<&2, U32>, Bool)) -> Pair(Array<U32>, Pair(List<&2, U32>, Bool))
def encode.rowpix.one source · line 987 · raw
@+ss:U32 -> @aa:Array<U32> -> Pair(Array<U32>, Pair(List<&2, U32>, Bool))
def encode.rowpix source · line 991 · raw
@left:Nat -> @got:Pair(Array<U32>, U32) -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> @+ch:U32 -> Pair(Array<U32>, Pair(List<&2, U32>, Bool))
got is the sample at x. left counts it and the samples after it.
def encode.rows.join source · line 1012 · raw
@+row:List<&2, U32> -> @rf:Bool -> @rest:Pair(Array<U32>, Pair(List<&2, List<&2, U32>>, Bool)) -> Pair(Array<U32>, Pair(List<&2, List<&2, U32>>, Bool))
def encode.rows.one source · line 1020 · raw
@+row:List<&2, U32> -> @rf:Bool -> @aa:Array<U32> -> Pair(Array<U32>, Pair(List<&2, List<&2, U32>>, Bool))
def encode.rows source · line 1024 · raw
@left:Nat -> @got:Pair(Array<U32>, Pair(List<&2, U32>, Bool)) -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> @+ch:U32 -> Pair(Array<U32>, Pair(List<&2, List<&2, U32>>, Bool))
got is the row at y. left counts it and the rows after it.
def encode.droprows source · line 1045 · raw
@rows:List<&2, List<&2, U32>> -> U32
def encode.zzq.take source · line 1054 · raw
@qs:List<&2, U32> -> Pair(U32, List<&2, U32>)
the next quant step, or 0 when the table has run out (qdiv turns 0 into 1)
def encode.zzq.go source · line 1062 · raw
@rest:List<&2, U32> -> @got:Pair(Array<U32>, U32) -> @qv:Pair(U32, List<&2, U32>) -> @acc:List<&2, U32> -> List<&2, U32>
got is the coefficient at the zigzag index just read. rest is the indexes after it.
def encode.zzq.enter source · line 1084 · raw
@zig:List<&2, U32> -> @arr:Array<U32> -> @qs:List<&2, U32> -> @acc:List<&2, U32> -> List<&2, U32>
def encode.zzq.load source · line 1093 · raw
@nat:List<&2, U32> -> @arr:Array<U32> -> @+at:U32 -> Array<U32>
def encode.zzq source · line 1101 · raw
@zig:List<&2, U32> -> @+nat:List<&2, U32> -> @+qs:List<&2, U32> -> @acc:List<&2, U32> -> List<&2, U32>
the coefficient block is an array, so each zigzag step is an index
def encode.zz source · line 1105 · raw
@flat:Bool -> @rows:List<&2, List<&2, U32>> -> @+kern:Kern -> @+zig:List<&2, U32> -> @+qs:List<&2, U32> -> List<&2, U32>
128 level-shifts to 0, and the integer DCT of that block is 0, so quant by 1 stays 0
def encode.block.pair source · line 1122 · raw
@got:Pair(Book, Pair(U32, Put)) -> @aa:Array<U32> -> Pair(Array<U32>, Pair(Book, Pair(U32, Put)))
def encode.block.use source · line 1127 · raw
@book:Book -> @pp:Put -> @+pred:U32 -> @got:Pair(Array<U32>, Pair(List<&2, List<&2, U32>>, Bool)) -> @+kern:Kern -> @+zig:List<&2, U32> -> @+qs:List<&2, U32> -> Pair(Array<U32>, Pair(Book, Pair(U32, Put)))
def encode.block source · line 1139 · raw
@book:Book -> @pp:Put -> @+pred:U32 -> @aa:Array<U32> -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> @+ch:U32 -> @ctx:Ctx -> Pair(Array<U32>, Pair(Book, Pair(U32, Put)))
def encode.nx source · line 1158 · raw
@more:Bool -> @+mx:U32 -> U32
def encode.ny source · line 1165 · raw
@more:Bool -> @+my:U32 -> U32
def encode.step.end source · line 1172 · raw
@got:Pair(Array<U32>, Pair(Book, Pair(U32, Put))) -> @+ydc:U32 -> @+bdc:U32 -> Pair(Array<U32>, Pair(Book, Pair(U32, Pair(U32, Pair(U32, Put)))))
def encode.scan.hit source · line 1180 · raw
@got:Pair(Array<U32>, Put) -> @arr:Array<U32> -> Scan
def encode.scan.skip source · line 1184 · raw
@sc:Scan -> @+cc:U32 -> Scan
def encode.scan.keep source · line 1190 · raw
@sc:Scan -> @+cc:U32 -> Scan
def encode.scan.bump source · line 1195 · raw
@zz:Bool -> @sc:Scan -> @+cc:U32 -> Scan
def encode.scan.val source · line 1203 · raw
@got:Pair(Array<U32>, U32) -> @+run:U32 -> @st:Pair(Array<U32>, Put) -> Scan
step is 1, so the frequency is the coefficient
def encode.scan.step source · line 1208 · raw
@sc:Scan -> @+gg:U32 -> Scan
def encode.scan.end source · line 1213 · raw
@sc:Scan -> Pair(Array<U32>, Put)
def encode.scan.ac source · line 1220 · raw
@rest:List<&2, U32> -> @sc:Scan -> Pair(Array<U32>, Put)
the rest of the zigzag, indexed in the frequency plane
def encode.scan.book source · line 1227 · raw
@got:Pair(Array<U32>, Put) -> @dc:Array<U32> -> @+dd:U32 -> Pair(Book, Pair(U32, Put))
def encode.scan.join source · line 1231 · raw
@got:Pair(Array<U32>, Put) -> @ac:Array<U32> -> @+dd:U32 -> @rest:List<&2, U32> -> @arr:Array<U32> -> Pair(Book, Pair(U32, Put))
def encode.scan.dc source · line 1241 · raw
@book:Book -> @pp:Put -> @+pred:U32 -> @+d0:U32 -> @rest:List<&2, U32> -> @arr:Array<U32> -> Pair(Book, Pair(U32, Put))
def encode.scan.open source · line 1254 · raw
@rest:List<&2, U32> -> @got:Pair(Array<U32>, U32) -> @book:Book -> @pp:Put -> @+pred:U32 -> Pair(Book, Pair(U32, Put))
def encode.scan.none source · line 1264 · raw
@book:Book -> @pp:Put -> @arr:Array<U32> -> @+pred:U32 -> Pair(Book, Pair(U32, Put))
def encode.scan source · line 1270 · raw
@book:Book -> @pp:Put -> @+pred:U32 -> @arr:Array<U32> -> @zig:List<&2, U32> -> Pair(Book, Pair(U32, Put))
DC at the first zigzag index, then the AC run, both read from the frequency plane
def encode.chan.flat source · line 1277 · raw
@plane:Array<U32> -> @book:Book -> @pp:Put -> @+pred:U32 -> @+kern:Kern -> @+zig:List<&2, U32> -> @+qs:List<&2, U32> -> Pair(Book, Pair(U32, Put))
def encode.chan.mix source · line 1292 · raw
@plane:Array<U32> -> @book:Book -> @pp:Put -> @+pred:U32 -> @+kern:Kern -> @zig:List<&2, U32> -> @qs:List<&2, U32> -> Pair(Book, Pair(U32, Put))
def encode.chan.go source · line 1304 · raw
@flat:Bool -> @plane:Array<U32> -> @book:Book -> @pp:Put -> @+pred:U32 -> @+kern:Kern -> @+zig:List<&2, U32> -> @+qs:List<&2, U32> -> Pair(Book, Pair(U32, Put))
def encode.pix.at source · line 1320 · raw
@aa:Array<U32> -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> Pair(Array<U32>, U32)
def encode.tile.store source · line 1323 · raw
@got:Pair(Array<U32>, U32) -> @ys:Array<U32> -> @bs:Array<U32> -> @rs:Array<U32> -> @fy:Bool -> @fb:Bool -> @fr:Bool -> @+ii:U32 -> Tile
def encode.tile.pix source · line 1344 · raw
@tt:Tile -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> @+ii:U32 -> Tile
def encode.tile.row source · line 1349 · raw
@left:Nat -> @tt:Tile -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> @+ii:U32 -> Tile
def encode.tile.rows source · line 1357 · raw
@left:Nat -> @tt:Tile -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> @+ii:U32 -> Tile
def encode.tile source · line 1366 · raw
@aa:Array<U32> -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> Tile
three level planes from one walk of this MCU
def encode.chan.pair source · line 1370 · raw
@got:Pair(Book, Pair(U32, Put)) -> @aa:Array<U32> -> Pair(Array<U32>, Pair(Book, Pair(U32, Put)))
def encode.step.cr source · line 1375 · raw
@got:Pair(Book, Pair(U32, Put)) -> @aa:Array<U32> -> @rs:Array<U32> -> @fr:Bool -> @+ydc:U32 -> @+pr:U32 -> @+kern:Kern -> @+zig:List<&2, U32> -> @+qs:List<&2, U32> -> Pair(Array<U32>, Pair(Book, Pair(U32, Pair(U32, Pair(U32, Put)))))
def encode.step.cb source · line 1389 · raw
@got:Pair(Book, Pair(U32, Put)) -> @aa:Array<U32> -> @bs:Array<U32> -> @rs:Array<U32> -> @fb:Bool -> @fr:Bool -> @+pb:U32 -> @+pr:U32 -> @+kern:Kern -> @+zig:List<&2, U32> -> @+qs:List<&2, U32> -> Pair(Array<U32>, Pair(Book, Pair(U32, Pair(U32, Pair(U32, Put)))))
def encode.step.tile source · line 1405 · raw
@tt:Tile -> @book:Book -> @bit:Put -> @+py:U32 -> @+pb:U32 -> @+pr:U32 -> @+kern:Kern -> @+zig:List<&2, U32> -> @+qs:List<&2, U32> -> Pair(Array<U32>, Pair(Book, Pair(U32, Pair(U32, Pair(U32, Put)))))
def encode.step.y source · line 1421 · raw
@aa:Array<U32> -> @book:Book -> @bit:Put -> @+py:U32 -> @+pb:U32 -> @+pr:U32 -> @+xx:U32 -> @+yy:U32 -> @+ww:U32 -> @+hh:U32 -> @+ctx:Ctx -> Pair(Array<U32>, Pair(Book, Pair(U32, Pair(U32, Pair(U32, Put)))))
one walk of the MCU, then Y, Cb, and Cr. Each clipped DC is the next predictor.
def encode.mcus.done source · line 1438 · raw
@got:Pair(Array<U32>, Pair(Book, Pair(U32, Pair(U32, Pair(U32, Put))))) -> Put
def encode.mcus source · line 1445 · raw
@left:Nat -> @got:Pair(Array<U32>, Pair(Book, Pair(U32, Pair(U32, Pair(U32, Put))))) -> @+mx:U32 -> @+my:U32 -> @+mw:U32 -> @+ww:U32 -> @+hh:U32 -> @+ctx:Ctx -> Put
def encode.finish source · line 1466 · raw
@+ww:U32 -> @+hh:U32 -> @ent:List<&2, U32> -> @+dcc:List<&2, U32> -> @+dcs:List<&2, U32> -> @+acc:List<&2, U32> -> @+acs:List<&2, U32> -> List<&2, U32>
def encode.hunt.nil source · line 1478 · raw
@+seen:U32 -> Pair(Bool, List<&2, U32>)
samples before a mismatch were packed 8421504, so that prefix can be replayed
def encode.hunt.mix source · line 1481 · raw
@+seen:U32 -> @+hh:U32 -> @tt:List<&2, U32> -> Pair(Bool, List<&2, U32>)
def encode.hunt.rest source · line 1484 · raw
@xs:List<&2, U32> -> Pair(Bool, List<&2, U32>)
def encode.hunt.done source · line 1489 · raw
@eq:Bool -> @+hh:U32 -> @xs:List<&2, U32> -> @+seen:U32 -> Pair(Bool, List<&2, U32>)
no samples remain after h
def encode.hunt.empty source · line 1497 · raw
@eq:Bool -> @+hh:U32 -> @+seen:U32 -> Pair(Bool, List<&2, U32>)
the list ended before the area did
def encode.hunt.go source · line 1505 · raw
@left:Nat -> @xs:List<&2, U32> -> @eq:Bool -> @+hh:U32 -> @+seen:U32 -> Pair(Bool, List<&2, U32>)
h was just read. left samples remain after it. seen neutral samples precede it.
def encode.hold.no source · line 1521 · raw
@+seen:U32 -> @+cc:U32 -> @tail:List<&2, U32> -> Pair(Bool, List<&2, U32>)
the area was one colour. seen of those samples are replayed only on a miss.
def encode.hold.yes source · line 1524 · raw
@xs:List<&2, U32> -> @+cc:U32 -> @+hh:U32 -> @+seen:U32 -> Pair(Bool, List<&2, U32>)
def encode.hold.done source · line 1529 · raw
@eq:Bool -> @+hh:U32 -> @xs:List<&2, U32> -> @+cc:U32 -> @+seen:U32 -> Pair(Bool, List<&2, U32>)
def encode.hold.empty source · line 1536 · raw
@eq:Bool -> @+hh:U32 -> @+cc:U32 -> @+seen:U32 -> Pair(Bool, List<&2, U32>)
def encode.hold.go source · line 1545 · raw
@left:Nat -> @xs:List<&2, U32> -> @eq:Bool -> @+hh:U32 -> @+cc:U32 -> @+seen:U32 -> Pair(Bool, List<&2, U32>)
h was just read. left samples remain after it. seen copies of c precede it.
def encode.watch.neu source · line 1561 · raw
@got:Pair(Bool, List<&2, U32>) -> Pair(U32, Pair(U32, List<&2, U32>))
0 neutral, 1 one other colour, 2 mixed. A short list stays mixed: the plane's gaps are 0.
def encode.watch.sol source · line 1570 · raw
@got:Pair(Bool, List<&2, U32>) -> @+hh:U32 -> Pair(U32, Pair(U32, List<&2, U32>))
def encode.watch.pick source · line 1580 · raw
@neu:Bool -> @kk:Nat -> @tt:List<&2, U32> -> @+hh:U32 -> Pair(U32, Pair(U32, List<&2, U32>))
def encode.watch source · line 1587 · raw
@left:Nat -> @xs:List<&2, U32> -> Pair(U32, Pair(U32, List<&2, U32>))
def encode.pack.byte source · line 1600 · raw
@+buf:U32 -> @+len:U32 -> @+code:U32 -> U32
low len bits of code join the open byte; a finished byte is stuffed
def encode.pack.full source · line 1603 · raw
@full:Bool -> @out:List<&2, U32> -> @+buf:U32 -> @+nn:U32 -> @+len:U32 -> @+code:U32 -> Put
def encode.pack.keep source · line 1610 · raw
@pp:Put -> @+lo:U32 -> @+rest:U32 -> Put
def encode.pack.span source · line 1615 · raw
@out:List<&2, U32> -> @+buf:U32 -> @+nn:U32 -> @+len:U32 -> @+code:U32 -> Put
def encode.pack.fit source · line 1621 · raw
@fit:Bool -> @out:List<&2, U32> -> @+buf:U32 -> @+nn:U32 -> @+len:U32 -> @+code:U32 -> Put
def encode.pack source · line 1628 · raw
@pp:Put -> @+len:U32 -> @+code:U32 -> Put
def encode.zput source · line 1634 · raw
@pp:Put -> Put
Annex K luminance: a zero block is DC 00 then EOB 1010
def encode.ztri source · line 1637 · raw
@pp:Put -> Put
def encode.neutral.mcus source · line 1640 · raw
@left:Nat -> @pp:Put -> Put
def encode.neutral source · line 1648 · raw
@+ww:U32 -> @+hh:U32 -> List<&2, U32>
the entropy-coded bytes of a neutral picture: every MCU is three zero blocks
def encode.solid.end source · line 1654 · raw
@got:Pair(Array<U32>, Pair(Book, Pair(U32, Put))) -> Put
the rest of a solid picture is the same DC, so each later block is a zero difference
def encode.solid.cr source · line 1661 · raw
@got:Pair(Array<U32>, Pair(Book, Pair(U32, Put))) -> @+ctx:Ctx -> Put
def encode.solid.cb source · line 1666 · raw
@got:Pair(Array<U32>, Pair(Book, Pair(U32, Put))) -> @+ctx:Ctx -> Put
def encode.solid.y source · line 1671 · raw
@aa:Array<U32> -> @book:Book -> @bit:Put -> @+ctx:Ctx -> Put
def encode.solid source · line 1676 · raw
@+ww:U32 -> @+hh:U32 -> @+color:U32 -> List<&2, U32>
one colour repeated. The first MCU is that block; every later MCU is three zero differences. The result is the entropy-coded bytes.
def encode.go source · line 1686 · raw
@+ww:U32 -> @+hh:U32 -> @px:List<&2, U32> -> List<&2, U32>
the entropy-coded bytes of any other picture, MCU by MCU
def encode.dispatch.b source · line 1696 · raw
@neu:Bool -> @sol:Bool -> @+color:U32 -> @px:List<&2, U32> -> @+ww:U32 -> @+hh:U32 -> List<&2, U32>
the entropy-coded bytes, by what the watch found: neutral, one solid colour, or anything else
def encode.dispatch source · line 1713 · raw
@+tag:U32 -> @+color:U32 -> @px:List<&2, U32> -> @+ww:U32 -> @+hh:U32 -> List<&2, U32>
the watch's tag, 0 neutral, 1 solid, 2 mixed, asked with U32.is_eq so a law reaches every tag
def encode.arm.use source · line 1717 · raw
@got:Pair(U32, Pair(U32, List<&2, U32>)) -> @+ww:U32 -> @+hh:U32 -> List<&2, U32>
the watch's answer, dispatched
def encode.arm source · line 1723 · raw
@+ww:U32 -> @+hh:U32 -> @px:List<&2, U32> -> List<&2, U32>
the entropy-coded bytes of an accepted size
def encode.pick source · line 1726 · raw
@bad:Bool -> @+ww:U32 -> @+hh:U32 -> @px:List<&2, U32> -> List<&2, U32>
def encode source · line 1736 · raw
@+ww:U32 -> @+hh:U32 -> @px:List<&2, U32> -> List<&2, U32>
baseline sequential 4:4:4 JPEG bytes for packed RGB samples, or SOI EOI when the size is rejected