(ql:quickload :cl-netpbm)
(defun burkes (img thresh &aux
(x (array-dimension img 0))
(y (array-dimension img 1)))
(declare (type fixnum x y thresh)
(optimize (speed 3) (safety 0)))
(let ((res (make-array (array-dimensions img)
:element-type 'bit))
(cur (make-array (+ 4 x)
:element-type 'double-float))
(nxt (make-array (+ 4 x)
:element-type 'double-float)))
(declare (dynamic-extent cur nxt))
(loop for i from 0 to (1- y)
do (progn
(loop for j from 0 to (1- x)
do (let* ((s (+ (aref img j i)
(aref cur (+ j 2))))
(pix (if (< s thresh)
0
1))
(err (- s (* pix 255))))
(setf (aref res j i) pix)
(incf (aref cur (+ j 3)) (* err 0.25D0))
(incf (aref cur (+ j 4)) (* err 0.125D0))
(incf (aref nxt j) (* err 0.0625D0))
(incf (aref nxt (+ j 1)) (* err 0.125D0))
(incf (aref nxt (+ j 2)) (* err 0.25D0))
(incf (aref nxt (+ j 3)) (* err 0.125D0))
(setf (aref nxt (+ j 4)) (* err 0.0625D0))))
(let ((tmp cur))
(loop for i from 0 to 3
do (setf (aref tmp i) 0.0D0))
(setf cur nxt)
(setf nxt tmp))))
res))
(defun serria-lite (img thresh &aux
(x (array-dimension img 0))
(y (array-dimension img 1)))
(let ((res (make-array (array-dimensions img)
:element-type 'bit))
(cur (make-array (+ 2 x)
:element-type 'double-float))
(fwd (make-array (+ 2 x)
:element-type 'double-float)))
(loop for i from 0 to (1- y)
do (progn
(loop for j from 0 to (1- x)
do (let* ((s (+ (aref img j i)
(aref cur (1+ j))))
(pix (if (< s thresh)
0
1))
(err (- s (* pix 255))))
(setf (aref res j i) pix)
(incf (aref cur (+ j 2)) (* err 0.5D0))
(let ((n (* err 0.25D0)))
(incf (aref fwd j) n)
(setf (aref fwd (1+ j)) n))))
(let ((tmp cur))
(setf (aref tmp (1- x)) 0.0D0
(aref tmp 0) 0.0D0)
(setf cur fwd)
(setf fwd tmp))))
res))
(defun atkinson (img thresh
&aux
(x (array-dimension img 0))
(y (array-dimension img 1)))
(declare (type fixnum x y thresh)
(optimize (speed 3) (safety 0)))
(let ((res (make-array (array-dimensions img)
:element-type 'bit))
(cur (make-array (+ 3 x)
:element-type 'double-float))
(fwd1 (make-array (+ 3 x)
:element-type 'double-float))
(fwd2 (make-array (+ 3 x)
:element-type 'double-float)))
(declare (dynamic-extent cur fwd1 fwd2))
(loop for i from 0 to (1- y)
do (progn
(loop for j from 0 to (1- x)
do (let* ((s (+ (aref img j i)
(aref cur (1+ j))))
(pix (if (< s thresh)
0
1))
(err (* 0.125D0 (- s (* pix 255)))))
(setf (aref res j i) pix)
(incf (aref cur (+ j 2)) err)
(incf (aref cur (+ j 3)) err)
(incf (aref fwd1 j) err)
(incf (aref fwd1 (1+ j)) err)
(incf (aref fwd1 (+ j 2)) err)
(setf (aref fwd2 (1+ j)) err)))
(let ((tmp cur))
(setf (aref cur 0) 0.0D0
(aref cur (1- x)) 0.0D0
(aref cur (- x 2)) 0.0D0)
(setf cur fwd1)
(setf fwd1 fwd2)
(setf fwd2 tmp))))
res))
(defvar *value* 210)
(defvar *dither-function* #'atkinson)
(defun convert (file)
(netpbm:write-to-file
(make-pathname :name (pathname-name file) :type "pbm")
(funcall *dither-function* (netpbm:read-from-file file) *value*)
:format :pbm))