#|
Jammed the pbm file format. Reading is slow.
Header lines (including space/newline) is all ascii
P4
16 2
11001100100011101100110010001110
The 1s and 0s are bits.
Junk at the end to make it a multiple of 8.
(defun test-p4-pbm () "
Check that it works for a hardcoded 1x16 vector 8x2 geom.
"
(let* ((path #p"my.pbm") (writer (write-bin path))
(pattern '( #b11100001 #b10100001))
(header #(#\P #\4 #\newline #\8 #\space #\2 #\newline)))
(unwind-protect
(loop for x across header for g = (bitgen x) do
(loop repeat 8 do (funcall writer (funcall g)))
finally
(loop for p in pattern for g = (bitgen p) do
(loop for b = (funcall g) while b do (funcall writer b))))
(funcall writer 'end))))
(defun arr2pbm (arr path dims)
(let* ((writer (write-bin path))
(header (format nil "P4~%~{~d~^ ~}~%" dims)))
(loop for x across header for g = (bitgen x) do
(loop repeat 8 do (funcall writer (funcall g))))
(loop for x across arr do (funcall writer x)
finally (funcall writer 'end))))
(defun chop (reader)
(loop repeat 8 do (funcall reader)))
(defun bits2no (list &key opposite-day)
(loop initially (when opposite-day (setf list (nreverse list)))
for l in list for x downfrom 7 for n = (ash l x) ; do (princ l)
sum n))
(defun read-header-line (reader &optional (maxlen 69))
(coerce
(loop for chlist = (loop repeat 8 collect (Funcall reader))
for no = (bits2no chlist) for ch = (code-char no)
for x from 0 ; do (format t "~@{~a ~}~%" chlist no ch x)
while (not (or (char= ch #\newline) (> x maxlen)))
collect ch)
'string))
(defun read-header (reader &optional print-comments)
(assert (string= "P4" (read-header-line reader)))
(loop for line = (read-header-line reader)
while (char= #\# (char line 0))
when print-comments do (print line)
finally (with-input-from-string (in line)
(return-from read-header (list (read in) (read in))))))
(defun pbm2ascii (pbm-path &key (foreground "%") (background "."))
(let* ((rdr (read-bin pbm-path))
(dims (prog1 (read-header rdr) ))
(flat (* (second dims) (first dims)))
(arr (make-array flat :element-type '(integer 0 1) :initial-element '1)))
(loop for n below flat sum (if (not (ignore-errors (setf (aref arr n)
(funcall rdr)))) 1 0))
(loop for a across arr for n from 1
for eol = (and (not nil) (zerop (mod n (first dims))))
do (mapc 'princ (case a (0 (list *cmd-fgfg-color* *cmd-fgbg-color*))
(1 (list *cmd-bgfg-color* *cmd-bgbg-color*))))
do (princ (case a (1 background) (0 foreground)))
do (princ *cmd-unset-color*)
do (when eol (terpri)))))
(defun arr2ascii (arr cols &optional (stream *standard-output*))
(loop for a across arr for n from 1
for lineendp = (zerop (rem n cols))
do (progn (princ a stream) (when lineendp (terpri stream)))))
(Defun test-matrix (n)
(let ((arr-len (expt n 2)))
(make-array (expt n 2)
:element-type '(integer 0 1)
:initial-contents
(loop for row below n nconcing
(loop for col below n
collecting (if (< col (/ n 2)) 1 0))))))