error-diffusion.k 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. pk:{x@*<{x|-x}x-y}
  2. pre:{+/y*0^z@(!#z)+/:|x}
  3. pres:{g:+g@/:\:!g:(x[0;1];x[1])@\:=**x;({+/y*0^z@x-1}.*g;{+/x@'0^y@!#x}[pre.'1_g])}
  4. fldrow:{(e,*y;(*|y),'(e:z-n;n:x[0]@z:z+x[1][*y]%x[3]))}
  5. pr:{fldrow[x]/[(,0.0;(!0;!0)); z+x[2][y]%x[3]]}
  6. ediff:{|*|{(,'*|pr[x;*y;z]),'y}[x]/[(,&#*y;0#,!0);y]}
  7. setup:{l:(w:&0<y[1])-*+&^y[1];f:.[y[1];]'+w;pk[x],pres[(l;f)], y[0]}
  8. specs:!/+(("floyd-steinberg"
  9. (16;(0 0N 7
  10. 3 5 1)))
  11. ("sierra"
  12. (32;(0 0 0N 5 3
  13. 2 4 5 4 2
  14. 0 2 3 2 0)))
  15. ("sierraTwo"
  16. (16;(0 0 0N 4 3
  17. 1 2 3 2 1)))
  18. ("sierraLite"
  19. (4;(0 0N 2
  20. 1 1 0)))
  21. ("burkes"
  22. (32;(0 0 0N 8 4
  23. 2 4 8 4 2)))
  24. ("stucki"
  25. (42;(0 0 0N 8 4
  26. 2 4 8 4 2
  27. 1 2 4 2 1)))
  28. ("jarvis"
  29. (48;(0 0 0N 7 5
  30. 3 5 7 5 3
  31. 1 3 5 3 1)))
  32. ("atkinson"
  33. (8;(0 0N 1 1
  34. 1 1 1 0
  35. 0 1 0 0))))
  36. /
  37. Inspired by
  38. [[https://gist.github.com/0racle/f48586b6b2c05d13e3abbcb046e91dfb][0racle]]
  39. this is an implementation of several error diffusion dithering
  40. algorithms.
  41. Each spec is a divisor along with a distribution of the errors
  42. relative to the location of 0N.
  43. Each row is then scanned, collecting both output and errors
  44. (i.e. difference between the calculated input and the output). Error
  45. accumulated from a single previous row is calculated by pre. The
  46. function pres returns both a function which collects error for the
  47. current row and one which aggregates the calculated accumulated error
  48. for each previous row.
  49. The behavior of pres changes depending on the spec and are configured
  50. with setup. The first argument to setup is the range of output values
  51. the second is the spec which is parsed to produce pre and pres.