ref: d180b70c6c69ffe8168cc8571772ad6e15ac6aba
dir: /chan.myr/
use std
use "types"
pkg draw =
pkglocal const chanparse : (str : byte[:] -> std.option(chan))
pkglocal const chanfmt : (buf : byte[:], chan : chan -> byte[:])
pkglocal const chandepth : (chan : chan -> uint32)
;;
var channames = "rgbkamx"
const chanparse = {str
var c, n, chan, depth
str = std.strstrip(str)
depth = 0
chan = 0
for var i = 0; i < str.len - 1; i += 2
if std.isspace((str[i] : char))
break
;;
match std.strfind(channames, str[i:i+1])
| `std.None: -> `std.None
| `std.Some ty:
c = (str[i + 1] : char)
n = std.charval(c, 10)
if n < 0
-> `std.None
;;
depth += n
chan <<= 8
chan |= dc((ty : uint32), n)
;;
;;
if depth==0 || (depth>8 && depth%8 != 0) || (depth<8 && 8%depth != 0)
-> `std.None
;;
-> `std.Some chan
}
const chanfmt = {buf, chan
var c, name, rc, i
rc = 0
for c = chan; c != 0; c >>= 8
rc <<= 8
rc |= c & 0xff
;;
i = 0
for c = rc; c != 0; c >>= 8
name = std.decode(channames[ctype(c & 0xff):])
std.bfmt(buf[i:i+2], "{}{}", name, cdepth(c & 0xff))
i += 2
;;
-> buf[:i]
}
const chandepth = {chan
var depth
depth = 0
for var c = chan; c != 0; c >>= 8
depth += cdepth(c)
;;
if depth==0 || (depth>8 && depth%8 != 0) || (depth<8 && 8%depth != 0)
-> 0
;;
-> depth
}
const dc = {ty, nbit
-> (((ty & 15) << 4) | (nbit & 15) : chan)
}
const ctype = {c
-> ((c & 0xf0) >> 4 : uint32)
}
const cdepth = {c
-> (c & 0xf : uint32)
}