RosettaCodeData/Task/Bitmap-Bresenhams-line-algo.../Zkl/bitmap-bresenhams-line-algo...

91 lines
2.9 KiB
Plaintext

class PPM{ // (0,0) is logically bottom left
fcn init(width,height,rgb=0){
sz:=width*height;
var [const]
data=Data(sz*3).fill(rgb.toBigEndian(3).toData()), // initialize to 24bit Black (RGB=000)
w=width, h=height;
}
fcn fill(rgb){ data.fill(rgb.toBigEndian(3).toData()) }
fcn __sGet(x,y) { data.toBigEndian(3*y*w + 3*x,3); } //ppm[x,y]
fcn __sSet(rgb,x,y){ data[3*y*w + x*3,3]=rgb.toBigEndian(3); rgb } //ppm[x,y]=rgb
fcn write(out,raw=False){ // write bottom to top to move (0,0) from top left to bottom left
out.write("P6\n#rosettacode PPM\n%d %d\n255\n".fmt(w,h));
if(raw) out.write(data);
else [h-1..0, -1].pump(out,'wrap(h){ data.seek(3*h*w); data.read(3*w) });
}
fcn writeJPGFile(fname){ // Linux, using imagemagick
System.popen(0'|convert ppm:- jpg:"%s"|.fmt(fname),"w") :
write(_,vm.pasteArgs(1));
}
fcn readJPGFile(fileName){ // Linux, using imagemagick
p:=System.popen("convert \"%s\" ppm:-".fmt(fileName),"r");
img:=PPM.readPPM(p);
p.close();
img
}
fcn readPPMFile(fileName){
f:=File(fileName,"rb"); ppm:=readPPM(f); f.close();
ppm
}
fcn readPPM(image){ // image is a PPM byte stream
// header is "P6\n[#comment\n]<w> <h>\nmaxPixelValue\n
image.readln(); // "P6"
while("#"==(text:=image.readln().strip())[0]){}
w,h:=text.split().apply("toInt");
image.readln(); // max pixel value
ppm,sz,buffer:=PPM(w,h), 3*w, Data(sz);
ppm.data.clear(); // gonna write file image data
// image is stored upside down in my data structure
do(h){ ppm.data.insert(0, image.read(sz,buffer)) }
ppm
}
fcn circle(x0,y0,r,rgb){
x:=r; y:=0; radiusError:=1-x;
while(x >= y){
__sSet(rgb, x + x0, y + y0);
__sSet(rgb, y + x0, x + y0);
__sSet(rgb,-x + x0, y + y0);
__sSet(rgb,-y + x0, x + y0);
self[-x + x0, -y + y0]=rgb; // or do it this way, __sSet gets called as above
self[-y + x0, -x + y0]=rgb;
self[ x + x0, -y + y0]=rgb;
self[ y + x0, -x + y0]=rgb;
y+=1;
if (radiusError<0) radiusError+=2*y + 1;
else{ x-=1; radiusError+=2*(y - x + 1); }
}
}
fcn cross(x,y,rgb=0xff|00,len=10){
a:=len/2; b:=len-a;
line(x-a,y, x+b,y,rgb); line(x,y-a, x,y+b,rgb);
}
fcn line(x0,y0, x1,y1, rgb){
dx:=(x1-x0).abs();
dy:=(y1-y0).abs();
if(x0 < x1) sx:=1 else sx:=-1;
if(y0 < y1) sy:=1 else sy:=-1;
err:=dx - dy;
while(1){
__sSet(rgb,x0,y0);
if(x0==x1 and y0==y1) break;
e2:=2*err;
if(e2 > -dy){ err=err - dy; x0=x0 + sx; }
if(e2 < dx) { err=err + dx; y0=y0 + sy; }
}
}
fcn flood(x,y, repl){ // slow!
targ:=self[x,y];
(stack:=List.createLong(10000)).append(T(x,y));
while(stack){
x,y:=stack.pop();
if((0<=y<h) and (0<=x<w)){
p:=self[x,y];
if(p==targ){
self[x,y]=repl;
stack.append( T(x-1,y), T(x+1,y), T(x, y-1), T(x, y+1) );
}
}
}
}
}