nx_intra.nx source
↩ module page · 43 lines · 2566 B
1// nx_intra.nx -- sovereign INTRA PREDICTION (V-R7, the q/bit gap-closer). Instead of coding raw pixels-128, an
2// intra block is predicted from its already-reconstructed neighbours (the row above, the column to the left) and
3// only the small RESIDUAL is transform-coded -> far fewer bits at the same quality. This is the H.264/VP9 intra
4// technique; we ship the 3 highest-value modes and pick the cheapest per block. 4x4 blocks, 8bpp. license_tier: ORIGINAL
5
6const IN_DC: i64 = 0
7const IN_VERT: i64 = 1 // copy the top row down (good for vertical structure)
8const IN_HORIZ: i64 = 2 // copy the left column across (good for horizontal structure)
9
10// fill a 4x4 predictor for `mode`. top[4] = reconstructed pixels above; left[4] = to the left.
11func in_predict(mode: i64, top: *i64, left: *i64, has_top: i64, has_left: i64, pred: *i64) -> i64 {
12 if mode == IN_VERT { var y: i64=0; while y<4 { var x: i64=0; while x<4 { pred[y*4+x] = top[x]; x=x+1 } y=y+1 } return 0 }
13 if mode == IN_HORIZ { var y: i64=0; while y<4 { var x: i64=0; while x<4 { pred[y*4+x] = left[y]; x=x+1 } y=y+1 } return 0 }
14 var sum: i64 = 0; var cnt: i64 = 0
15 if has_top == 1 { var x: i64=0; while x<4 { sum = sum + top[x]; cnt = cnt + 1; x=x+1 } }
16 if has_left == 1 { var y: i64=0; while y<4 { sum = sum + left[y]; cnt = cnt + 1; y=y+1 } }
17 var dc: i64 = 128
18 if cnt > 0 { dc = sum / cnt }
19 var i: i64 = 0; while i < 16 { pred[i] = dc; i = i + 1 }
20 return 0
21}
22// SAD of a 4x4 block vs a predictor (the residual energy = a bits proxy)
23func in_sad(block: *i64, pred: *i64) -> i64 {
24 var s: i64 = 0; var i: i64 = 0
25 while i < 16 { let d: i64 = block[i] - pred[i]; if d < 0 { s = s - d } else { s = s + d } i = i + 1 }
26 return s
27}
28// pick the cheapest mode (min residual SAD); leaves the chosen predictor in `pred`; returns the mode.
29func in_best(block: *i64, top: *i64, left: *i64, has_top: i64, has_left: i64, pred: *i64) -> i64 {
30 var best_mode: i64 = IN_DC
31 in_predict(IN_DC, top, left, has_top, has_left, pred)
32 var best: i64 = in_sad(block, pred)
33 if has_top == 1 {
34 in_predict(IN_VERT, top, left, has_top, has_left, pred)
35 let s: i64 = in_sad(block, pred); if s < best { best = s; best_mode = IN_VERT }
36 }
37 if has_left == 1 {
38 in_predict(IN_HORIZ, top, left, has_top, has_left, pred)
39 let s: i64 = in_sad(block, pred); if s < best { best = s; best_mode = IN_HORIZ }
40 }
41 in_predict(best_mode, top, left, has_top, has_left, pred) // leave the winning predictor in pred
42 return best_mode
43}