implement PPM_dv;
include "ppm_dv.m";
include "draw.m";
draw : Draw;
include "sys.m";
sys: Sys;
include "bufio.m";
bufio: Bufio;
Iobuf : import bufio;
include "readdir.m";
readdir : Readdir;
include "ppm.m";
imgs : Images;
init(nil: ref Draw->Context, nil: list of string)
{
draw = load Draw Draw->PATH;
sys = load Sys Sys->PATH;
bufio = load Bufio Bufio->PATH;
readdir = load Readdir Readdir->PATH;
imgs = load Images Images->PATH;
imgs->init(nil, nil);
}
new_sequence(d : string) : ref Sequence
{
r := ref Sequence(0, d, big 0, 0, 0, 0, 1);
r.scan();
return r;
}
get_number(b : ref Iobuf) : int
{
n := b.gett("\n ");
if(n[0] == '#' && n[len n - 1] != '\n') {
b.gets('\n');
return get_number(b);
} else {
return int n;
}
}
Sequence.scan(s : self ref Sequence)
{
(files, filecount) := readdir->init(s.directory, readdir->NAME | readdir->COMPACT);
s.framecount = big filecount;
fname := sys->sprint("%s/%s", s.directory, files[0].name);
b := bufio->open(fname, sys->OREAD);
if(b == nil){
sys->print("Opening %s failed\n", fname);
return;
}
b.getc();
if(get_number(b) != 6) {
sys->print("WRONG PPM\n");
return;
}
s.width = get_number(b);
s.height = get_number(b);
s.maxvalue = get_number(b);
s.bpp = 1; # for now
# mx := s.maxvalue;
# while(mx > 0) {
# s.bpp++;
# mx >>= 8;
# }
s.headersize = int b.offset();
}
Sequence.sample(s : self ref Sequence, frame:big, offset : big) : int
{
fname := sys->sprint("%s/w%04bd.ppm", s.directory, frame);
sample := array[s.bpp] of byte;
fd := sys->open(fname, sys->OREAD);
if(fd == nil)
return -255;
sys->pread(fd, sample, len sample, offset);
# assumes 1 byte values
if(s.bpp != 1)
raise "ONLY 8bpp supported atm.";
return int sample[0];
}
Sequence.offset(s : self ref Sequence, x, y, channel : int) : big
{
offset := big x + big y * big s.width;
offset *= big 3 * big s.bpp;
offset += big s.headersize + big (channel * s.bpp);
return offset;
}
Sequence.frame_pixel(s : self ref Sequence, startframe : big, samplesize, x, y, channel : int) : array of int
{
samples := array[samplesize] of int;
offset := s.offset(x, y, channel);
frame := startframe - big (samplesize >> 1);
for(i := 0; i < samplesize; i++) {
samples[i] = s.sample(frame, offset);
frame += big 1;
}
return samples;
}
Sequence.info(s : self ref Sequence) : string
{
return sys->sprint("Directory: %s\nHeadersize %d\nframecount %bd\nwidth x height x maxvalue %d x %d x %d\n", s.directory, s.headersize, s.framecount, s.width, s.height, s.maxvalue);
}
Sequence.sample_set(s : self ref Sequence, startframe, endframe : big, x, y, channel : int) : ref Samples
{
samplesize := int (endframe - startframe);
if(samplesize < 0) return nil;
offset := s.offset(x, y, channel);
samples := ref Samples(big startframe, 0, array[samplesize] of real, offset);
frame := startframe;
for(i := 0; i < samplesize; i++) {
samples.r[i] = real s.sample(frame, offset) / real s.maxvalue;
frame += big 1;
}
return samples;
}
Samples.readnext(s : self ref Samples, seq : ref Sequence) : int
{
s.r[s.firstr++] = real seq.sample(s.frame, s.offset) / real seq.maxvalue;
s.firstr %= len s.r;
return s.firstr;
}
Samples.print(s : self ref Samples)
{
sys->print("frame %bd\n", s.frame);
sys->print("firstr %d\n", s.firstr);
for(i :=0; i < len s.r; i++) {
sys->print("i %d r %g\n", i, s.r[i]);
}
}
Samples.advance_to(s : self ref Samples, seq : ref Sequence, frame : big) : int
{
while(s.frame < frame && s.readnext(seq) > 0);
if(s.frame == frame) return 1;
return 0;
}
Samples.in_sequence(s: self ref Samples) : array of real
{
reals := array[len s.r] of real;
ri : int;
ri = s.firstr + 1;
ri %= len s.r;
for(k := len s.r - 1; k >= 0; k--) {
reals[k] = s.r[ri++];
ri %= len s.r;
}
return s.r;
}
write_to_pixel(s : ref Sequence, c : chan of ref Pixel)
{
raise "needs fixing,stupid and slow anyway!";
# p : ref Pixel;
# p = <-c;
# while(p != nil) {
# i := ppm->new_rgba8(s.width, s.height);
# ppm := create_ppm(
# fname := sys->sprint("%s/%06bd.ppm", s.directory, p.frame);
# if(f.open(fname) == nil) {
# sys->print("OPEN FAILED\n");
# if(f.create(fname) == nil)
# raise sys->sprint("I/O FAIL %s\n", fname);
# }
# if(f.write_to_pixel(p.x, p.y, p.v, p.channel) < 1)
# raise sys->sprint("I/O WRITE FAIL %s\n", fname);
#sys->print("write_to_pixel(p.x %d, p.y %d, p.v %d, p.channel %d)\n", p.x, p.y, p.v, p.channel);
# p = <-c;
# }
}
|