implement Images;
include "draw.m";
draw : Draw;
include "sys.m";
sys: Sys;
include "bufio.m";
bufio: Bufio;
Iobuf : import bufio;
include "ppm.m";
ppm_header(width, height, format, maxval : int) : array of byte
{
return array of byte sys->sprint("P%d\n%d %d\n%d\n", format, width, height, maxval);
}
init(nil: ref Draw->Context, nil: list of string)
{
draw = load Draw Draw->PATH;
sys = load Sys Sys->PATH;
bufio = load Bufio Bufio->PATH;
}
new_rgba8(width, height : int) : ref Image
{
return ref Image(width, height, 6, 255, 3, ref Bitmap.rgba8(width, height, array [width * height * 4] of byte), big 0, nil);
}
create_ppm(i : ref Image, filename : string)
{
fd := sys->create(filename, sys->OWRITE, 0666);
if(fd == nil) raise "create file failed";
pick bm := i.bitmap {
rgba8 =>
hdr := ppm_header(i.width, i.height, 6, 255);
sys->write(fd, hdr, len hdr);
rowbytes := i.width * 3;
rgb := array[rowbytes] of byte;
j, k : int;
j = 0;
for(y := 0; y < i.height; y++) {
k = 0;
for(x := 0; x < i.width; x++) {
rgb[k++] = bm.pixels[j+2];
rgb[k++] = bm.pixels[j+1];
rgb[k++] = bm.pixels[j];
j+=4;
}
sys->write(fd, rgb, rowbytes);
}
* =>
raise "only 8bpp P6 ppm supported";
}
}
Image.open_ppm(f : self ref Image, filename : string) : ref sys->FD
{
hdr := ppm_header(f.width, f.height, f.format, f.maxval);
f.dataoffset = big len hdr;
f.fd = sys->open(filename, sys->ORDWR);
return f.fd;
}
Image.write_to_ppm_pixel(f : self ref Image, x, y, v, channel : int) : int
{
bytespp := 0;
mv := f.maxval;
while(mv > 0) {
bytespp++;
mv >>= 8;
}
numchannels := 3;
pixel := y * numchannels * f.width + x * numchannels;
pixel += channel;
pos := f.dataoffset + big bytespp * big pixel;
sys->seek(f.fd, pos, sys->SEEKSTART);
vb := array[bytespp] of byte;
if(bytespp > 1) {
for(i := 0; i < bytespp; i++) {
vb[i] = (byte v) & byte 16rFF;
v >>= 1;
}
} else {
vb[0] = byte v;
}
return sys->write(f.fd, vb, len vb);
}
|