src/jpeg_enc.bend checks
raw source on the hub · import 0x83c5c81fb41f55ca634bdc7bde39a51b/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.ff source · line 165 · raw
@ff:Bool -> @out:List<&2, U32> -> @+bb:U32 -> Put
def encode.stuff source · line 172 · raw
@out:List<&2, U32> -> @+bb:U32 -> Put
def encode.bit.n source · line 175 · raw
@full:Bool -> @out:List<&2, U32> -> @+nb:U32 -> @+nn:U32 -> Put
def encode.bit source · line 182 · raw
@pp:Put -> @+bit:U32 -> Put
def encode.bits.go source · line 187 · raw
@left:Nat -> @pp:Put -> @+code:U32 -> Put
def encode.bits source · line 195 · raw
@pp:Put -> @+len:U32 -> @+code:U32 -> Put
def encode.pad.byte source · line 198 · raw
@ff:Bool -> @out:List<&2, U32> -> @+byte:U32 -> List<&2, U32>
def encode.pad.n source · line 205 · raw
@zz:Bool -> @out:List<&2, U32> -> @+buf:U32 -> @+nn:U32 -> List<&2, U32>
def encode.pad source · line 215 · raw
@pp:Put -> List<&2, U32>
def encode.drop source · line 220 · raw
@xs:List<&2, U32> -> U32
def encode.fill source · line 224 · 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 247 · raw
@hh:0x83c5c81fb41f55ca634bdc7bde39a51b/src/jpeg.Huff -> Array<U32>
def encode.huff source · line 252 · raw
@+counts:List<&2, U32> -> @+syms:List<&2, U32> -> Array<U32>
def encode.book source · line 255 · raw
@+dcc:List<&2, U32> -> @+dcs:List<&2, U32> -> @+acc:List<&2, U32> -> @+acs:List<&2, U32> -> Book
def encode.cat.fr source · line 258 · raw
@done:Bool -> @+lt:Bool -> Bool
def encode.cat.on source · line 265 · raw
@fr:Bool -> U32
def encode.cat.c source · line 272 · raw
@fr:Bool -> @+cc:U32 -> U32
def encode.cat.lim source · line 279 · raw
@fr:Bool -> @+lim:U32 -> U32
def encode.cat.go source · line 286 · raw
@left:Nat -> @+done:U32 -> @+aa:U32 -> @+cc:U32 -> @+lim:U32 -> U32
def encode.cat source · line 294 · raw
@+vv:U32 -> U32
def encode.mag.s source · line 297 · raw
@+ss:U32 -> @+cat:U32 -> @+vv:U32 -> U32
def encode.mag source · line 304 · raw
@+cat:U32 -> @+vv:U32 -> U32
def encode.magp.z source · line 307 · raw
@zz:Bool -> @pp:Put -> @+cat:U32 -> @+vv:U32 -> Put
def encode.coded source · line 315 · raw
@got:Pair(Array<U32>, U32) -> Pair(Array<U32>, Code)
the indexed word is the length and the code
def encode.sym source · line 319 · raw
@aa:Array<U32> -> @+sym:U32 -> Pair(Array<U32>, Code)
def encode.dc.use source · line 322 · raw
@got:Pair(Array<U32>, Code) -> @pp:Put -> @+cat:U32 -> @+diff:U32 -> Pair(Array<U32>, Put)
def encode.dc source · line 327 · raw
@aa:Array<U32> -> @+pp:Put -> @+diff:U32 -> Pair(Array<U32>, Put)
def encode.clip.hi source · line 331 · raw
@hi:Bool -> @+vv:U32 -> @+lim:U32 -> U32
def encode.clip.lo source · line 338 · raw
@lo:Bool -> @+vv:U32 -> @+lim:U32 -> U32
def encode.clip.s source · line 345 · raw
@+ss:U32 -> @+vv:U32 -> @+lim:U32 -> U32
def encode.clip source · line 352 · raw
@+vv:U32 -> @+lim:U32 -> U32
def encode.emit source · line 355 · raw
@got:Pair(Array<U32>, Code) -> @pp:Put -> Pair(Array<U32>, Put)
def encode.eob source · line 360 · raw
@need:Bool -> @aa:Array<U32> -> @pp:Put -> Pair(Array<U32>, Put)
def encode.eob.on source · line 367 · raw
@need:Bool -> @st:Pair(Array<U32>, Put) -> Pair(Array<U32>, Put)
def encode.zrls.one source · line 372 · raw
@st:Pair(Array<U32>, Put) -> Pair(Array<U32>, Put)
def encode.zrls source · line 377 · raw
@left:Nat -> @st:Pair(Array<U32>, Put) -> Pair(Array<U32>, Put)
def encode.ac.mag source · line 384 · raw
@got:Pair(Array<U32>, Put) -> @+cat:U32 -> @+clip:U32 -> Pair(Array<U32>, Put)
def encode.ac.hit source · line 389 · raw
@got:Pair(Array<U32>, Put) -> @+sym:U32 -> @+cat:U32 -> @+clip:U32 -> Pair(Array<U32>, Put)
def encode.ac.step source · line 394 · raw
@+cc:U32 -> @+run:U32 -> @st:Pair(Array<U32>, Put) -> Pair(Array<U32>, Put)
def encode.ac source · line 402 · raw
@zz:List<&2, U32> -> @+run:U32 -> @st:Pair(Array<U32>, Put) -> Pair(Array<U32>, Put)
def encode.qnz source · line 411 · raw
@+qq:U32 -> U32
def encode.qdiv.s source · line 418 · raw
@+ss:U32 -> @+vv:U32 -> @+qq:U32 -> U32
def encode.qdiv source · line 425 · raw
@+vv:U32 -> @+qq:U32 -> U32
def encode.block.join source · line 428 · raw
@got:Pair(Array<U32>, Put) -> @dc2:Array<U32> -> @+dd:U32 -> Pair(Book, Pair(U32, Put))
def encode.block.dc source · line 432 · 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 437 · raw
@book:Book -> @pp:Put -> @+pred:U32 -> @+dc0:U32 -> @rest:List<&2, U32> -> Pair(Book, Pair(U32, Put))
the clipped DC is written and kept, so the next block can predict from it
def encode.block.go source · line 443 · raw
@book:Book -> @pp:Put -> @+pred:U32 -> @zz:List<&2, U32> -> Pair(Book, Pair(U32, Put))
def encode.add64.acc source · line 450 · raw
@+ph:U32 -> @+pl:U32 -> @acc:Pair(U32, U32) -> Pair(U32, U32)
def encode.add64 source · line 457 · 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 463 · raw
@+coef:U32 -> @+samp:U32 -> @acc:Pair(U32, U32) -> Pair(U32, U32)
one more product on the accumulator
def encode.q17 source · line 467 · raw
@acc:Pair(U32, U32) -> U32
the same rounding the matrix product applies to a finished sum
def encode.scale source · line 472 · raw
@+coef:U32 -> @+samp:U32 -> U32
def encode.two source · line 475 · raw
@+c0:U32 -> @+x0:U32 -> @+c1:U32 -> @+x1:U32 -> U32
def encode.two.n source · line 478 · raw
@+c0:U32 -> @+x0:U32 -> @+c1:U32 -> @+x1:U32 -> U32
def encode.four source · line 481 · raw
@+c0:U32 -> @+s0:U32 -> @+c1:U32 -> @+s1:U32 -> @+c2:U32 -> @+s2:U32 -> @+c3:U32 -> @+s3:U32 -> U32
def encode.even source · line 485 · 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 508 · 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 515 · raw
@+f0:U32 -> @+f2:U32 -> @+f4:U32 -> @+f6:U32 -> @od:Oct -> Oct
def encode.dct8.at source · line 521 · raw
@ev:Oct -> @od:Oct -> Oct
def encode.dct8.k source · line 527 · 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 544 · 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 549 · raw
@row:List<&2, U32> -> Oct
def encode.put8 source · line 557 · 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 580 · raw
@oo:Oct -> @aa:Array<U32> -> @+at:U32 -> Array<U32>
def encode.scatter source · line 585 · raw
@oo:Oct -> @aa:Array<U32> -> @+at:U32 -> Array<U32>
def encode.oct.pack source · line 590 · 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 603 · 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 616 · 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 629 · 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 642 · 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 655 · 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 668 · 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 681 · 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 694 · 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 708 · 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 718 · raw
@got:Pair(Array<U32>, Oct) -> @kern:Kern -> Pair(Array<U32>, Oct)
def encode.col source · line 724 · 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 727 · raw
@rows:List<&2, List<&2, U32>> -> @+kern:Kern -> @arr:Array<U32> -> @+at:U32 -> Array<U32>
def encode.pix.sink source · line 735 · raw
@aa:Array<U32> -> U32
def encode.book.sink source · line 742 · raw
@book:Book -> U32
def encode.pass2.done source · line 747 · raw
@st:Planes -> @kern:Kern -> Array<U32>
def encode.pass2.put source · line 755 · raw
@got:Pair(Array<U32>, Oct) -> @dst:Array<U32> -> @+at:U32 -> Planes
def encode.pass2.step source · line 760 · raw
@st:Planes -> @kern:Kern -> Planes
def encode.pass2 source · line 765 · raw
@left:Nat -> @st:Planes -> @+kern:Kern -> Array<U32>
def encode.pass.rows.done source · line 772 · raw
@st:Planes -> @kern:Kern -> Array<U32>
def encode.pass.rows.lay source · line 780 · raw
@got:Pair(Array<U32>, Oct) -> @+kern:Kern -> @dst:Array<U32> -> @+at:U32 -> Planes
def encode.pass.rows.next source · line 785 · raw
@st:Planes -> @+kern:Kern -> Planes
def encode.pass.rows source · line 791 · raw
@left:Nat -> @st:Planes -> @+kern:Kern -> Array<U32>
eight row transforms. left rows are still unread.
def encode.pass.mid source · line 798 · raw
@src:Array<U32> -> @+kern:Kern -> Array<U32>
def encode.freq source · line 802 · raw
@src:Array<U32> -> @+kern:Kern -> Array<U32>
level plane in, natural-order frequencies out
def encode.drain.pack source · line 805 · raw
@got:Pair(Array<U32>, U32) -> @acc:List<&2, U32> -> Pair(Array<U32>, Pair(U32, List<&2, U32>))
def encode.drain.step source · line 810 · 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 814 · raw
@st:Pair(Array<U32>, Pair(U32, List<&2, U32>)) -> List<&2, U32>
def encode.drain source · line 820 · 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 827 · raw
@got:Pair(Array<U32>, U32) -> Pair(Array<U32>, Pair(U32, List<&2, U32>))
def encode.fdct.go source · line 832 · raw
@src:Array<U32> -> @kern:Kern -> List<&2, U32>
def encode.fdct source · line 835 · raw
@rows:List<&2, List<&2, U32>> -> @+cs:List<&2, U32> -> List<&2, U32>
def encode.level source · line 839 · raw
@xs:List<&2, U32> -> List<&2, U32>
def encode.levels source · line 846 · raw
@rows:List<&2, List<&2, U32>> -> List<&2, List<&2, U32>>
def encode.sat source · line 853 · raw
@over:Bool -> @+xx:U32 -> @+lim:U32 -> U32
def encode.sat8 source · line 860 · raw
@over:Bool -> @+vv:U32 -> U32
def encode.y source · line 867 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.cb source · line 870 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.cr source · line 873 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.ych source · line 876 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.cbch source · line 880 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.crch source · line 884 · raw
@+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.chan.w source · line 888 · raw
@+ch:U32 -> @+rr:U32 -> @+gg:U32 -> @+bb:U32 -> U32
def encode.chan source · line 897 · raw
@+pix:U32 -> @+ch:U32 -> U32
def encode.pix.load source · line 901 · 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 911 · raw
@got:Pair(Array<U32>, U32) -> @+ch:U32 -> Pair(Array<U32>, U32)
def encode.sample source · line 916 · 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 921 · raw
@aa:Bool -> @bb:Bool -> Bool
both samples are the neutral level
def encode.rowpix.step source · line 930 · 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 934 · raw
@+ss:U32 -> @aa:Array<U32> -> Pair(Array<U32>, Pair(List<&2, U32>, Bool))
def encode.rowpix source · line 938 · 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 959 · 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 967 · 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 971 · 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 992 · raw
@rows:List<&2, List<&2, U32>> -> U32
def encode.zzq.take source · line 1001 · 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 1009 · 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 1031 · 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 1040 · raw
@nat:List<&2, U32> -> @arr:Array<U32> -> @+at:U32 -> Array<U32>
def encode.zzq source · line 1048 · 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 1052 · 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 1069 · raw
@got:Pair(Book, Pair(U32, Put)) -> @aa:Array<U32> -> Pair(Array<U32>, Pair(Book, Pair(U32, Put)))
def encode.block.use source · line 1074 · 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 1086 · 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 1105 · raw
@more:Bool -> @+mx:U32 -> U32
def encode.ny source · line 1112 · raw
@more:Bool -> @+my:U32 -> U32
def encode.step.end source · line 1119 · 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 1127 · raw
@got:Pair(Array<U32>, Put) -> @arr:Array<U32> -> Scan
def encode.scan.skip source · line 1131 · raw
@sc:Scan -> @+cc:U32 -> Scan
def encode.scan.keep source · line 1137 · raw
@sc:Scan -> @+cc:U32 -> Scan
def encode.scan.bump source · line 1142 · raw
@zz:Bool -> @sc:Scan -> @+cc:U32 -> Scan
def encode.scan.val source · line 1150 · 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 1155 · raw
@sc:Scan -> @+gg:U32 -> Scan
def encode.scan.end source · line 1160 · raw
@sc:Scan -> Pair(Array<U32>, Put)
def encode.scan.ac source · line 1167 · 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 1174 · raw
@got:Pair(Array<U32>, Put) -> @dc:Array<U32> -> @+dd:U32 -> Pair(Book, Pair(U32, Put))
def encode.scan.join source · line 1178 · 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 1188 · 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 1201 · 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 1211 · raw
@book:Book -> @pp:Put -> @arr:Array<U32> -> @+pred:U32 -> Pair(Book, Pair(U32, Put))
def encode.scan source · line 1217 · 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 1224 · 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 1239 · 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 1251 · 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 1267 · raw
@aa:Array<U32> -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> Pair(Array<U32>, U32)
def encode.tile.store source · line 1270 · 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 1291 · raw
@tt:Tile -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> @+ii:U32 -> Tile
def encode.tile.row source · line 1296 · raw
@left:Nat -> @tt:Tile -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> @+ii:U32 -> Tile
def encode.tile.rows source · line 1304 · raw
@left:Nat -> @tt:Tile -> @+ww:U32 -> @+hh:U32 -> @+xx:U32 -> @+yy:U32 -> @+ii:U32 -> Tile
def encode.tile source · line 1313 · 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 1317 · raw
@got:Pair(Book, Pair(U32, Put)) -> @aa:Array<U32> -> Pair(Array<U32>, Pair(Book, Pair(U32, Put)))
def encode.step.cr source · line 1322 · 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 1336 · 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 1352 · 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 1368 · 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 1385 · raw
@got:Pair(Array<U32>, Pair(Book, Pair(U32, Pair(U32, Pair(U32, Put))))) -> Put
def encode.mcus source · line 1392 · 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 1413 · 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 1425 · 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 1428 · raw
@+seen:U32 -> @+hh:U32 -> @tt:List<&2, U32> -> Pair(Bool, List<&2, U32>)
def encode.hunt.rest source · line 1431 · raw
@xs:List<&2, U32> -> Pair(Bool, List<&2, U32>)
def encode.hunt.done source · line 1436 · 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 1444 · 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 1452 · 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 1468 · 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 1471 · raw
@xs:List<&2, U32> -> @+cc:U32 -> @+hh:U32 -> @+seen:U32 -> Pair(Bool, List<&2, U32>)
def encode.hold.done source · line 1476 · raw
@eq:Bool -> @+hh:U32 -> @xs:List<&2, U32> -> @+cc:U32 -> @+seen:U32 -> Pair(Bool, List<&2, U32>)
def encode.hold.empty source · line 1483 · raw
@eq:Bool -> @+hh:U32 -> @+cc:U32 -> @+seen:U32 -> Pair(Bool, List<&2, U32>)
def encode.hold.go source · line 1492 · 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 1508 · 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 1517 · raw
@got:Pair(Bool, List<&2, U32>) -> @+hh:U32 -> Pair(U32, Pair(U32, List<&2, U32>))
def encode.watch.pick source · line 1527 · raw
@neu:Bool -> @kk:Nat -> @tt:List<&2, U32> -> @+hh:U32 -> Pair(U32, Pair(U32, List<&2, U32>))
def encode.watch source · line 1534 · raw
@left:Nat -> @xs:List<&2, U32> -> Pair(U32, Pair(U32, List<&2, U32>))
def encode.pack.byte source · line 1547 · 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 1550 · raw
@full:Bool -> @out:List<&2, U32> -> @+buf:U32 -> @+nn:U32 -> @+len:U32 -> @+code:U32 -> Put
def encode.pack.keep source · line 1557 · raw
@pp:Put -> @+lo:U32 -> @+rest:U32 -> Put
def encode.pack.span source · line 1562 · raw
@out:List<&2, U32> -> @+buf:U32 -> @+nn:U32 -> @+len:U32 -> @+code:U32 -> Put
def encode.pack.fit source · line 1568 · raw
@fit:Bool -> @out:List<&2, U32> -> @+buf:U32 -> @+nn:U32 -> @+len:U32 -> @+code:U32 -> Put
def encode.pack source · line 1575 · raw
@pp:Put -> @+len:U32 -> @+code:U32 -> Put
def encode.zput source · line 1581 · raw
@pp:Put -> Put
Annex K luminance: a zero block is DC 00 then EOB 1010
def encode.ztri source · line 1584 · raw
@pp:Put -> Put
def encode.neutral.mcus source · line 1587 · raw
@left:Nat -> @pp:Put -> Put
def encode.neutral source · line 1595 · 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 1601 · 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 1608 · raw
@got:Pair(Array<U32>, Pair(Book, Pair(U32, Put))) -> @+ctx:Ctx -> Put
def encode.solid.cb source · line 1613 · raw
@got:Pair(Array<U32>, Pair(Book, Pair(U32, Put))) -> @+ctx:Ctx -> Put
def encode.solid.y source · line 1618 · raw
@aa:Array<U32> -> @book:Book -> @bit:Put -> @+ctx:Ctx -> Put
def encode.solid source · line 1623 · 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 1633 · 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 source · line 1643 · raw
@+tag:U32 -> @+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.arm.use source · line 1657 · 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 1663 · 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 1666 · raw
@bad:Bool -> @+ww:U32 -> @+hh:U32 -> @px:List<&2, U32> -> List<&2, U32>
def encode source · line 1676 · 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