PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/appl/grid/demo/blur.b

https://bitbucket.org/floren/inferno/
Brainfuck | 654 lines | 605 code | 49 blank | 0 comment | 178 complexity | 49dbc75072d640f2c12a032a281ba952 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception
  1. implement Blur;
  2. include "tk.m";
  3. tk: Tk;
  4. include "tkclient.m";
  5. tkclient: Tkclient;
  6. include "sys.m";
  7. sys : Sys;
  8. include "daytime.m";
  9. daytime: Daytime;
  10. include "draw.m";
  11. draw: Draw;
  12. Display, Chans, Point, Rect, Image: import draw;
  13. include "readdir.m";
  14. readdir: Readdir;
  15. include "grid/demo/exproc.m";
  16. exproc: Exproc;
  17. include "grid/demo/block.m";
  18. block: Block;
  19. display : ref draw->Display;
  20. context : ref draw->Context;
  21. path := "/tmp/blur/";
  22. Blur : module {
  23. init : fn (ctxt : ref Draw->Context, nil : list of string);
  24. getslavedata : fn (lst: list of string);
  25. doblock : fn (block: int, bpath: string);
  26. readblock : fn (block: int, dir: string, chanout: chan of string): int;
  27. finish : fn (waittime: int, tkchan: chan of string);
  28. };
  29. init(ctxt : ref Draw->Context, argv : list of string)
  30. {
  31. sys = load Sys Sys->PATH;
  32. if (sys == nil)
  33. badmod(Sys->PATH);
  34. draw = load Draw Draw->PATH;
  35. if (draw == nil)
  36. badmod(Draw->PATH);
  37. daytime = load Daytime Daytime->PATH;
  38. if (daytime == nil)
  39. badmod(Daytime->PATH);
  40. tk = load Tk Tk->PATH;
  41. if (tk == nil)
  42. badmod(Tk->PATH);
  43. tkclient = load Tkclient Tkclient->PATH;
  44. if (tkclient == nil)
  45. badmod(Tkclient->PATH);
  46. tkclient->init();
  47. readdir = load Readdir Readdir->PATH;
  48. if (readdir == nil)
  49. badmod(Readdir->PATH);
  50. exproc = load Exproc "$self";
  51. if (exproc == nil)
  52. badmod(sys->sprint("Exproc: %r"));
  53. block = load Block Block->PATH;
  54. if (block == nil)
  55. badmod(Block->PATH);
  56. if (ctxt == nil) {
  57. display = Display.allocate(nil);
  58. if (display == nil)
  59. usage(sys->sprint("failed to get a display: %r"));
  60. context = nil;
  61. }
  62. else {
  63. display = ctxt.display;
  64. context = ctxt;
  65. }
  66. spawn blurit(argv);
  67. }
  68. blurit(argv: list of string)
  69. {
  70. mast := 0;
  71. size = 12;
  72. blocks = Point (10,6);
  73. filename := "";
  74. argv = tl argv;
  75. if (len argv > 2)
  76. usage("too many arguments");
  77. for (; argv != nil; argv = tl argv) {
  78. (n,dir) := sys->stat(hd argv);
  79. if (n == -1)
  80. usage("file/directory '"+hd argv+"' does not exist");
  81. if (dir.mode & sys->DMDIR)
  82. path = hd argv;
  83. else {
  84. filename = hd argv;
  85. mast = 1;
  86. }
  87. }
  88. if (mast && context == nil)
  89. usage("nil context - cannot be used as master");
  90. if (path[len path - 1] != '/')
  91. path[len path] = '/';
  92. if (len path < 5 || path[len path - 5:] != "blur/")
  93. path += "blur/";
  94. block->init(path, exproc);
  95. if (mast)
  96. spawn master(filename);
  97. else {
  98. sys->print("starting slave\n");
  99. spawn block->slave();
  100. }
  101. }
  102. usage(err: string)
  103. {
  104. sys->print("usage: blur [dir] [image]\n");
  105. if (err != nil) {
  106. sys->print("Error: %s\n",err);
  107. raise "fail:error";
  108. }
  109. else
  110. exit;
  111. }
  112. getslavedata(lst: list of string)
  113. {
  114. if (lst == nil || len lst < 5)
  115. block->err("Cannot read data file");
  116. size = int hd lst;
  117. blocks = Point(int hd tl lst, int hd tl tl lst);
  118. bsize = Point(int hd tl tl tl lst, int hd tl tl tl tl lst);
  119. blockimg = display.newimage(((0,0),bsize), draw->RGB24,0,draw->Red);
  120. }
  121. blocks, bsize: Draw->Point;
  122. size: int;
  123. newimg: ref Draw->Image;
  124. getxy(i, w: int): (int, int)
  125. {
  126. y := i / w;
  127. x := i - (y * w);
  128. return (x,y);
  129. }
  130. master(filename: string)
  131. {
  132. block->cleanfiles(path);
  133. img := display.open(filename);
  134. if (img == nil)
  135. block->err("cannot read image: "+filename);
  136. if (img.chans.depth() != 24)
  137. block->err("wrong image depth! (must be 24bit)\n");
  138. sys->create(path, sys->OREAD, 8r777 | sys->DMDIR);
  139. blocks.x = img.r.dx() / 70;
  140. if (blocks.x < 1)
  141. blocks.x = 1;
  142. blocks.y = img.r.dy() / 70;
  143. if (blocks.y < 1)
  144. blocks.y = 1;
  145. bsize = Point(img.r.dx()/blocks.x, img.r.dy()/blocks.y);
  146. data := sys->sprint("%d\n%d\n%d\n%d\n%d\n",size,blocks.x,blocks.y,bsize.x,bsize.y);
  147. noblocks := blocks.x * blocks.y;
  148. n := 0;
  149. for (y := 0; y < blocks.y; y++) {
  150. for (x := 0; x < blocks.x; x++) {
  151. r2 := Rect(((x*bsize.x)-size, (y*bsize.y)-size),
  152. (((1+x)*bsize.x)+size, ((1+y)*bsize.y)+size));
  153. if (r2.min.x < 0)
  154. r2.min.x = 0;
  155. if (r2.min.y < 0)
  156. r2.min.y = 0;
  157. if (r2.max.x > img.r.max.x)
  158. r2.max.x = img.r.max.x;
  159. if (r2.max.y > img.r.max.y)
  160. r2.max.y = img.r.max.y;
  161. tmpimg := display.newimage(r2,draw->RGB24,0,draw->Black);
  162. tmpimg.draw(r2, img, nil, r2.min);
  163. fdtmp := sys->create(path+"imgdata."+string n+".bit", sys->OWRITE, 8r666);
  164. if (fdtmp == nil)
  165. sys->print("couldn't write image: '%s' %r\n",path+"imgdata."+string n+".bit");
  166. display.writeimage(fdtmp, tmpimg);
  167. n++;
  168. }
  169. }
  170. block->writedata(data);
  171. block->masterinit(noblocks);
  172. (top, titlebar) := tkclient->toplevel(context, "", "Blur", Tkclient->Hide);
  173. tkcmd(top, "frame .f");
  174. r2 := Rect((0,0),(blocks.x*bsize.x,blocks.y*bsize.y));
  175. newimg = display.newimage(r2,draw->RGB24,0,draw->Black);
  176. newimg.draw(r2,img,nil,(0,0));
  177. tkcmd(top, sys->sprint("panel .f.p -height %d -width %d", r2.dy(), r2.dx()));
  178. tk->putimage(top, ".f.p", newimg, nil);
  179. tkcmd(top, "label .f.l1 -text {Processed: }");
  180. tkcmd(top, "label .f.l2 -text {0%} -width 30");
  181. tkcmd(top, "grid .f.p -row 0 -column 0 -columnspan 2");
  182. tkcmd(top, "grid .f.l1 -row 1 -column 0 -sticky e");
  183. tkcmd(top, "grid .f.l2 -row 1 -column 1 -sticky w");
  184. tkcmd(top, "pack .f");
  185. tkcmd(top, "bind .Wm_t <Button-1> +{focus .}");
  186. tkcmd(top, "bind .Wm_t.title <Button-1> +{focus .}");
  187. tkcmd(top, "focus .; update");
  188. tkchan := chan of string;
  189. sync := chan of int;
  190. spawn block->reader(noblocks, tkchan, sync);
  191. readerpid := <-sync;
  192. spawn window(top, titlebar, newimg, tkchan, readerpid);
  193. }
  194. blockimg: ref Draw->Image;
  195. doblock(block: int, bpath: string)
  196. {
  197. (x,y) := getxy(block, blocks.x);
  198. procimg := display.open(path+"imgdata."+string block+".bit");
  199. if (procimg == nil)
  200. sys->print("Error nil image! '%s' %r\n",path+"imgdata."+string block+".bit");
  201. blurred := procblock(procimg, x,y,0,size,bsize);
  202. sketched := procblock(procimg, x,y,1,3,bsize);
  203. for (i := 0; i < len blurred; i++) {
  204. if (sketched[i] != byte 127)
  205. blurred[i] = sketched[i];
  206. }
  207. blockimg.writepixels(((0,0),bsize), blurred);
  208. fd := sys->create(path + bpath+"/img.bit",sys->OWRITE,8r666);
  209. display.writeimage(fd, blockimg);
  210. fd = nil;
  211. sys->create(path + bpath+"/done", sys->OWRITE, 8r666);
  212. }
  213. window(top: ref Tk->Toplevel, titlebar: chan of string,
  214. img: ref Image, tkchan: chan of string, readerpid: int)
  215. {
  216. total := blocks.x * blocks.y;
  217. done := 0;
  218. tkclient->onscreen(top, nil);
  219. tkclient->startinput(top, "kbd"::"ptr"::nil);
  220. finished := 0;
  221. main: for(;;) alt {
  222. s := <-top.ctxt.kbd =>
  223. tk->keyboard(top, s);
  224. s := <-top.ctxt.ptr =>
  225. tk->pointer(top, *s);
  226. inp := <- tkchan =>
  227. (n, lst) := sys->tokenize(inp, " \n\t");
  228. case hd lst {
  229. "done" =>
  230. done++;
  231. tkcmd(top, ".f.l2 configure -text {"+string ((100*done)/total)+"%}");
  232. tkcmd(top, ".f.p dirty");
  233. "time" =>
  234. tkcmd(top, ".f.l1 configure -text {Time taken:}");
  235. tkcmd(top, ".f.l2 configure -text {"+hd tl lst+"} -width 80");
  236. finished = 1;
  237. * =>
  238. tkcmd(top, ".f.l2 configure -text {"+inp+"%}");
  239. }
  240. tkcmd(top, "update");
  241. title := <-top.ctxt.ctl or
  242. title = <-top.wreq or
  243. title = <- titlebar =>
  244. if (title == "exit") {
  245. if (finished) {
  246. kill(readerpid);
  247. break main;
  248. }
  249. }
  250. else
  251. tkclient->wmctl(top, title);
  252. }
  253. spawn block->cleanfiles(path);
  254. }
  255. readblock(block: int, dir: string, chanout: chan of string): int
  256. {
  257. img := display.open(dir+"img.bit");
  258. if (img == nil)
  259. return -1;
  260. (ix,iy) := getxy(block, blocks.x);
  261. newimg.draw(img.r.addpt(Point(ix*bsize.x, iy*bsize.y)),img,nil,(0,0));
  262. chanout <-= "done";
  263. return 0;
  264. }
  265. finish(waittime: int, tkchan: chan of string)
  266. {
  267. hrs := waittime / 360;
  268. mins := (waittime - (360 * hrs)) / 60;
  269. secs := waittime - (360 * hrs) - (60 * mins);
  270. time := addzeros(sys->sprint("%d:%d:%d",hrs,mins,secs));
  271. if (hrs == 0) time = time[3:];
  272. tkchan <-= "time "+time;
  273. block->cleanfiles(path);
  274. }
  275. procblock(procimg: ref Image, x,y, itype, size: int, bsize: Point): array of byte
  276. {
  277. r := Rect((x*bsize.x, y*bsize.y), ((1+x)*bsize.x, (1+y)*bsize.y));
  278. r2 : Rect;
  279. if (itype == 0)
  280. r2 = procimg.r;
  281. else
  282. r2 = Rect((x*bsize.x, y*bsize.y), (((1+x)*bsize.x)+1, ((1+y)*bsize.y)+1));
  283. if (r2.min.x < 0)
  284. r2.min.x = 0;
  285. if (r2.min.y < 0)
  286. r2.min.y = 0;
  287. if (r2.max.x > procimg.r.max.x)
  288. r2.max.x = procimg.r.max.x;
  289. if (r2.max.y > procimg.r.max.y)
  290. r2.max.y = procimg.r.max.y;
  291. buf := array[3 * r2.dx() * r2.dy()] of byte;
  292. procimg.readpixels(r2,buf);
  293. pad := Rect((r.min.x-r2.min.x, r.min.y-r2.min.y), (r2.max.x - r.max.x, r2.max.y-r.max.y));
  294. if (itype == 0)
  295. return blurblock(size,r,pad,buf);
  296. if (itype == 1)
  297. return gradblock(10,r,pad,buf);
  298. return nil;
  299. }
  300. makepic(buf: array of int, w,nw,nh: int): array of byte
  301. {
  302. newbuf := array[3*nw*nh] of byte;
  303. n := 0;
  304. for (y := 0; y < nh; y++) {
  305. for (x := 0; x < nw; x++) {
  306. val := byte buf[(y*w)+x];
  307. if (val < byte 0) val = -val;
  308. if (val > byte 255) val = byte 255;
  309. for (i := 0; i < 3; i++)
  310. newbuf[n++] = val;
  311. }
  312. }
  313. return newbuf;
  314. }
  315. gradblock(threshold: int, r, pad: Rect, buffer: array of byte) : array of byte
  316. {
  317. gradbufx := array[3] of array of int;
  318. gradbufy := array[3] of array of int;
  319. width: int;
  320. cleaning := 3;
  321. for (rgb := 0; rgb < 3; rgb++) {
  322. greybuf := array[len buffer] of { * => 0 };
  323. n := 0;
  324. width = r.dx()+pad.max.x;
  325. for (y := 0; y < r.dy()+pad.max.y; y++) {
  326. for (x := 0; x < r.dx()+pad.max.x; x++) {
  327. greybuf[n++] = int buffer[(3* ((y*width) + x ))+rgb];
  328. }
  329. }
  330. for(i := 0; i < 2; i++) {
  331. padx := pad.max.x;
  332. pady := pad.max.y;
  333. width = r.dx();
  334. height := r.dy();
  335. gradbuf: array of int;
  336. (gradbuf, width, height, padx, pady) = getgrad(greybuf, i, width,height, padx, pady);
  337. width = r.dx();
  338. if (i == 0) {
  339. gradbufx[rgb] = clean(hyster(gradbuf,1,width,threshold), width,5,4);
  340. for (k := 0; k < cleaning; k++)
  341. gradbufx[rgb] = clean(gradbufx[rgb], width,2,2);
  342. }
  343. else {
  344. gradbufy[rgb] = clean(hyster(gradbuf, 0,width,threshold), width,5,4);
  345. for (k := 0; k < cleaning; k++)
  346. gradbufy[rgb] = clean(gradbufy[rgb], width,2,2);
  347. }
  348. }
  349. }
  350. newbuf := array[len gradbufx[0]] of int;
  351. for (i := 0; i < len newbuf; i++) {
  352. val := 127;
  353. n := 0;
  354. for (rgb = 0; rgb < 3; rgb++) {
  355. if (gradbufx[rgb][i] != 127) {
  356. n++;
  357. val = gradbufx[rgb][i];
  358. }
  359. else if (gradbufy[rgb][i] != 127) {
  360. val = gradbufy[rgb][i];
  361. n++;
  362. }
  363. }
  364. if (n > 1)
  365. newbuf[i] = val;
  366. else
  367. newbuf[i] = 127;
  368. }
  369. if (sat(newbuf) > 25 && threshold > 4)
  370. return gradblock(threshold - 2,r,pad,buffer);
  371. return makepic(newbuf,width,r.dx(),r.dy());
  372. }
  373. X: con 0;
  374. Y: con 1;
  375. getgrad(buf: array of int, dir, w,h, px, py: int): (array of int, int, int, int, int)
  376. {
  377. npx := px - 1;
  378. npy := py - 1;
  379. if (npx < 0) npx = 0;
  380. if (npy < 0) npy = 0;
  381. gradbuf := array[(w+npx)*(h+npy)] of int;
  382. n := 0;
  383. val1, val2: int;
  384. for (y := 0; y < h+npy; y++) {
  385. for (x := 0; x < w+npx; x++) {
  386. val1 = buf[(y*(w+px)) + x];
  387. if ((dir == X && x-w >= npx) ||
  388. (dir == Y && y-h >= npy))
  389. val2 = val1;
  390. else
  391. val2 = buf[((y+dir)*(w+px)) + x + 1 - dir];
  392. gradbuf[n++] = val2 - val1;
  393. }
  394. }
  395. return (norm(gradbuf,0,255), w, h, px,py);
  396. }
  397. sat(a: array of int): int
  398. {
  399. n := 0;
  400. for (i := 0; i < len a; i++)
  401. if (a[i] != 127)
  402. n++;
  403. return (100 * n)/ len a;
  404. }
  405. hyster(a: array of int, gox, width: int, lim: int): array of int
  406. {
  407. min, max: int;
  408. av := 0;
  409. for (i := 0; i < len a; i++) {
  410. if (i == 0)
  411. min = max = a[i];
  412. if (a[i] < min)
  413. min = a[i];
  414. if (a[i] > max)
  415. max = a[i];
  416. av += a[i];
  417. }
  418. # sys->print("%d/%d = %d\n",av,len a,av / len a);
  419. av = av/len a;
  420. upper := av + ((max-av)/lim);
  421. lower := av - ((av-min)/ lim);
  422. low := 0;
  423. # sys->print("len a: %d %d %d %d\n",len a,av,min,max);
  424. i = 0;
  425. x := 0;
  426. y := 0;
  427. height := len a / width;
  428. newline := 1;
  429. # sys->print("width: %d gox: %d\n",width,gox);
  430. for (k := 0; k < len a; k++) {
  431. i = (y*width) + x;
  432. if (newline) {
  433. # if (a[i] < av) low = 1;
  434. # else low = 0;
  435. low = a[i] > av;
  436. newline = 0;
  437. }
  438. oldlow := low;
  439. if (low == 0) {
  440. if (a[i] > upper)
  441. low = 1;
  442. }
  443. else if (low == 1) {
  444. if (a[i] < lower)
  445. low = 0;
  446. }
  447. # sys->print("a[i]: %d bound: %d %d low %d => %d\n",a[i],lower,upper,oldlow,low);
  448. if (oldlow == low)
  449. a[i] =127;
  450. else
  451. a[i] = low * 255;
  452. if (gox) {
  453. i++;
  454. x++;
  455. if (x == width) {
  456. x = 0;
  457. y++;
  458. newline = 1;
  459. }
  460. }
  461. else {
  462. i += width;
  463. y++;
  464. if (y == height) {
  465. # sys->print("y: %d\n",y);
  466. y = 0;
  467. i = x;
  468. x++;
  469. newline = 1;
  470. }
  471. }
  472. }
  473. return a;
  474. }
  475. clean(a: array of int, width, r, d: int): array of int
  476. {
  477. height := len a / width;
  478. csize := (2*r) ** 2;
  479. for (y := 0; y < height; y++) {
  480. for (x := 0; x < width; x++) {
  481. i := (width*y)+x;
  482. if (a[i] != 127) {
  483. sx := x - r;
  484. if (sx < 0) sx = 0;
  485. ex := x + r;
  486. if (ex > width) ex = width;
  487. sy := y - r;
  488. if (sy < 0) sy = 0;
  489. ey := y + r;
  490. n := 0;
  491. if (ey > height) ey = height;
  492. for (iy := sy; iy < ey; iy++) {
  493. for (ix := sx; ix < ex; ix++) {
  494. if (a[(width*iy)+ix] == a[i])
  495. n++;
  496. }
  497. }
  498. #sys->print("%f\n",real ((ex-sx)*(ey-sy))/ real csize);
  499. # if (n < int (real d * (real ((ex-sx)*(ey-sy))/ real csize)))
  500. if (n < d)
  501. a[i] = 127;
  502. }
  503. }
  504. }
  505. return a;
  506. }
  507. norm(a: array of int, lower, upper: int): array of int
  508. {
  509. min, max: int;
  510. for (i := 0; i < len a; i++) {
  511. if (i == 0)
  512. min = max = a[i];
  513. if (a[i] < min)
  514. min = a[i];
  515. if (a[i] > max)
  516. max = a[i];
  517. }
  518. multi : real = (real (upper - lower)) / (real (max - min));
  519. add := real (lower - min);
  520. for (i = 0; i < len a; i++) {
  521. a[i] = int ((add + real a[i]) * multi);
  522. if (a[i] < lower)
  523. a[i] = lower;
  524. if (a[i] > upper)
  525. a[i] = upper;
  526. }
  527. return a;
  528. }
  529. opt := 2;
  530. blurblock(size: int, r, pad: Rect, buffer: array of byte) : array of byte
  531. {
  532. newbuf := array[3 * r.dx() * r.dy()] of byte;
  533. n := 0;
  534. width := r.dx()+pad.min.x+pad.max.x;
  535. for (y := 0; y < r.dy(); y++) {
  536. for (x := 0; x < r.dx(); x++) {
  537. r2 := Rect((x-size,y-size),(x+size+1,y+size+1));
  538. if (r2.min.x < -pad.min.x)
  539. r2.min.x = -pad.min.x;
  540. if (r2.min.y < -pad.min.y)
  541. r2.min.y = -pad.min.y;
  542. if (r2.max.x > r.dx()+pad.max.x)
  543. r2.max.x = r.dx()+pad.max.x;
  544. if (r2.max.y > r.dy()+pad.max.y)
  545. r2.max.y = r.dy()+pad.max.y;
  546. nosamples := r2.dx()*r2.dy();
  547. r2.min.x += pad.min.x;
  548. r2.min.y += pad.min.y;
  549. r2.max.x += pad.min.x;
  550. r2.max.y += pad.min.y;
  551. pixel := array[3] of { * => 0};
  552. for (sy := r2.min.y; sy < r2.max.y; sy++) {
  553. for (sx := r2.min.x; sx < r2.max.x; sx++) {
  554. for (i := 0; i < 3; i++)
  555. pixel[i] += int buffer[(3* ( ((sy)*width) + (sx) ) )+ i];
  556. }
  557. }
  558. for (i := 0; i < 3; i++) {
  559. if (opt == 0)
  560. newbuf[n++] = byte (pixel[i] / nosamples);
  561. if (opt == 1)
  562. newbuf[n++] = byte (255 - (pixel[i] / nosamples));
  563. if (opt == 2)
  564. newbuf[n++] = byte (63 + (pixel[i] / (2*nosamples)));
  565. }
  566. }
  567. }
  568. return newbuf;
  569. }
  570. tkcmd(top: ref Tk->Toplevel, cmd: string): string
  571. {
  572. e := tk->cmd(top, cmd);
  573. if (e != "" && e[0] == '!') sys->print("tk error: '%s': %s\n",cmd,e);
  574. return e;
  575. }
  576. addzeros(s: string): string
  577. {
  578. s[len s] = ' ';
  579. rs := "";
  580. start := 0;
  581. isnum := 0;
  582. for (i := 0; i < len s; i++) {
  583. if (s[i] < '0' || s[i] > '9') {
  584. if (isnum && i - start < 2) rs[len rs] = '0';
  585. rs += s[start:i+1];
  586. start = i+1;
  587. isnum = 0;
  588. }
  589. else isnum = 1;
  590. }
  591. i = len rs - 1;
  592. while (i >= 0 && rs[i] == ' ') i--;
  593. return rs[:i+1];
  594. }
  595. kill(pid: int)
  596. {
  597. pctl := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE);
  598. if (pctl != nil)
  599. sys->write(pctl, array of byte "kill", len "kill");
  600. }
  601. badmod(path: string)
  602. {
  603. sys->print("Blur: failed to load: %s\n",path);
  604. exit;
  605. }