implement Mkimage;
include "sys.m";
sys: Sys;
include "draw.m";
draw: Draw;
Display, Image, Rect, Point, Chans: import draw;
include "string.m";
str: String;
include "arg.m";
arg: Arg;
stderr: ref Sys->FD;
# usage: mkimage colour xmin ymin xmax ymax
Mkimage: module {
init: fn(ctxt: ref Draw->Context, argv: list of string);
};
usage()
{
sys->fprint(stderr, "usage: mkimage [-c chan] colour [xmin ymin] xmax ymax\n");
raise "fail:usage";
}
init(ctxt: ref Draw->Context, argv: list of string)
{
sys = load Sys Sys->PATH;
stderr = sys->fildes(2);
draw = load Draw Draw->PATH;
str = load String String->PATH;
arg = load Arg Arg->PATH;
arg->init(argv);
cstr := "";
while ((opt := arg->opt()) != 0) {
case opt {
'c' =>
cstr = arg->arg();
* =>
usage();
}
}
argv = arg->argv();
displ := ctxt.display;
n := len argv;
if (n != 5 && n != 3)
usage();
col := tkcolour(hd argv);
chans: Chans;
if (cstr != nil)
chans = Chans.mk(cstr);
else if ((col & 16rff) == 16rff)
chans = Draw->RGB24;
else
chans = Draw->RGBA32;
if (chans.desc == 0) {
sys->fprint(stderr, "mkimage: invalid channel description %s\n", cstr);
raise "fail:error";
}
argv = tl argv;
ir := Rect((0, 0), (0, 0));
if (n == 5) {
(ir.min.x, argv) = (int hd argv, tl argv);
(ir.min.y, argv) = (int hd argv, tl argv);
}
(ir.max.x, argv) = (int hd argv, tl argv);
(ir.max.y, argv) = (int hd argv, tl argv);
img := displ.newimage(ir, chans, 0, col);
if (img == nil) {
sys->fprint(stderr, "mkimage: cannot make new image: %r\n");
raise "fail:error";
}
displ.writeimage(sys->fildes(1), img);
}
colours := array[] of {
("black", int 16r0000000ff),
("blue", int 16r00000ccff),
("darkblue", int 16r05d00bbff),
("red", int 16r0ff0000ff),
("yellow", int 16r0ffff00ff),
("green", int 16r0008000ff),
("white", int 16r0ffffffff),
("orange", int 16r0ffaa00ff),
("aqua", int 16r000ffffff),
("fuchsia", int 16r0ff00ffff),
("gray", int 16r0808080ff),
("lime", int 16r000ff00ff),
("maroon", int 16r0800000ff),
("navy", int 16r0000080ff),
("olive", int 16r0808000ff),
("purple", int 16r0800080ff),
("silver", int 16r0c0c0c0ff),
("teal", int 16r0008080ff),
("transparent", int 16r000000000),
};
tkcolour(col: string): int
{
mod := "";
for (i := 0; i < len col; i++)
if (col[i] == '*') {
(col, mod) = (col[0:i], col[i+1:]);
break;
}
rgba := 0;
if ((len col != 7 && len col != 9) || col[0] != '#') {
for (i := 0; i < len colours; i++) {
(ccol, rgb) := colours[i];
if (col == ccol) {
rgba = rgb;
break;
}
}
if (i == len colours) {
sys->fprint(stderr, "mkimage: unknown colour %s\n", col);
raise "fail:bad colour";
}
} else {
(val, rest) := str->toint(col[1:], 16);
if (rest != nil) {
sys->fprint(stderr, "mkimage: unknown colour %s\n", col);
raise "fail:bad colour";
}
if (len col == 7)
rgba = (val << 8) | 16rff;
}
if (mod != nil) {
a: int;
if (mod[0] == '#')
(a, nil) = str->toint(mod[1:], 16);
else
a = int (real mod[1:] * 255.0);
rgba = applyalpha(rgba, a);
}
return rgba;
}
applyalpha(rgba, a: int): int
{
for (i := 0; i < 32; i+=8) {
v := (rgba >> i) & 16rff;
v = (v * a) / 255;
mask := 16rff << i;
rgba = (rgba & ~mask) | (v << i);
}
return rgba;
}
|