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; # } }