code wiki / (root) / nx_colordesc.nx

nx_colordesc.nx source

↩ module page · 77 lines · 3082 B

1// nx_colordesc.nx -- CHROMA color-layout descriptor (brightness-invariant), the color complement to 2// nx_visdesc. dHash and the edge/tone descriptor both run on GRAYSCALE -- so two fields of equal luma 3// but different hue (a red field vs a green field) collapse to the SAME representation and are 4// indistinguishable. This descriptor carries the color axis grayscale throws away: a 4x4 spatial grid 5// of average chroma (Cb,Cr) -> a 32-dim integer vector ranked by L1. Chroma is computed as (channel - 6// luma), so a uniform additive brightness/exposure shift cancels EXACTLY -> brightness-invariant by 7// construction. Integer + deterministic + zero-dep. Pairs with nx_visdesc (structure/tone) for a full 8// visual signature; "Google-lite" color-layout, the MPEG-7 CLD lineage done sovereignly. 9// 10// genealogy_id: kasson_1992_ycc + manjunath_2001_mpeg7_cld (color-layout descriptor) 11// license_tier: ORIGINAL 12import "syscalls.nx" 13 14const CD_GRID: i64 = 4 15const CD_DIM: i64 = 32 // CD_GRID*CD_GRID*2 (Cb,Cr per cell) 16 17func nx_colordesc_dim() -> i64 { return CD_DIM } 18 19func cd_clamp255(v: i64) -> i64 { if v < 0 { return 0 } if v > 255 { return 255 } return v } 20 21// extract the 32-dim chroma-layout descriptor of a w*h interleaved RGB (3 bytes/pixel) buffer into 22// out[0..32); returns CD_DIM. Cb=(B-Y)*0.564, Cr=(R-Y)*0.713 (integer, *256), centered at 128. 23func nx_colordesc_extract(rgb: *u8, w: i64, h: i64, out: *i64) -> i64 { 24 var cy: i64 = 0 25 while cy < CD_GRID { 26 let y0: i64 = cy*h/CD_GRID 27 let y1: i64 = (cy+1)*h/CD_GRID 28 var cx: i64 = 0 29 while cx < CD_GRID { 30 let x0: i64 = cx*w/CD_GRID 31 let x1: i64 = (cx+1)*w/CD_GRID 32 var sr: i64 = 0 33 var sg: i64 = 0 34 var sb: i64 = 0 35 var cnt: i64 = 0 36 var y: i64 = y0 37 while y < y1 { 38 var x: i64 = x0 39 while x < x1 { 40 let idx: i64 = (y*w+x)*3 41 sr = sr + (rgb[idx] as i64) 42 sg = sg + (rgb[idx+1] as i64) 43 sb = sb + (rgb[idx+2] as i64) 44 cnt = cnt + 1 45 x = x + 1 46 } 47 y = y + 1 48 } 49 var ar: i64 = 0 50 var ag: i64 = 0 51 var ab: i64 = 0 52 if cnt > 0 { ar = sr/cnt; ag = sg/cnt; ab = sb/cnt } 53 let yv: i64 = (77*ar + 150*ag + 29*ab) / 256 54 let cb: i64 = (ab - yv)*144/256 + 128 55 let cr: i64 = (ar - yv)*183/256 + 128 56 let base: i64 = (cy*CD_GRID + cx)*2 57 out[base] = cd_clamp255(cb) 58 out[base+1] = cd_clamp255(cr) 59 cx = cx + 1 60 } 61 cy = cy + 1 62 } 63 return CD_DIM 64} 65 66// L1 (Manhattan) distance between two chroma descriptors; smaller = more similar in color. 67func nx_colordesc_l1(a: *i64, b: *i64) -> i64 { 68 var d: i64 = 0 69 var i: i64 = 0 70 while i < CD_DIM { 71 var t: i64 = a[i] - b[i] 72 if t < 0 { t = 0 - t } 73 d = d + t 74 i = i + 1 75 } 76 return d 77}