-
Notifications
You must be signed in to change notification settings - Fork 0
/
images.lisp
59 lines (53 loc) · 2.63 KB
/
images.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
;;;; images.lisp
(in-package #:apex7tkl)
(defparameter +max-image-width+ 128 "Horizontal pixel size of the OLED screen.")
(defparameter +max-image-height+ 40 "Vertical pixel size of the OLED screen.")
(defun format-for-oled (image-data &optional (threshold 1))
"Formats the IMAGE-DATA for tramission to the oled screen.
Optional argument THRESHOLD indicates the maximum value a pixel must have to be painted
white or black. Defaults to 1, ie paint everything not strictly black in the original.
This function is not very lispy. It is a rough conversion of the one in the original Python
code. I will probably revisit this later..."
(labels ((zero-or-one (pixel)
(if (> threshold pixel)
#\0
#\1)))
(let ((byte-data (make-array 8))
(index 0)
(translated nil))
;; Conveniently, cl-gd:get-pixel returns 0 for (x,y) out of bounds for
;; the image so we can loop for max image width/height and everything
;; over limits will be black :)
(loop for y from 0 below +max-image-height+
do (loop for x from 0 below +max-image-width+
do
(setf (elt byte-data index) (zero-or-one
(cl-gd:get-pixel x y :image image-data)))
(incf index)
(when (= index 8)
;; compute and start over
(push (parse-integer (concatenate 'string byte-data) :radix 2) translated)
(setf index 0))))
;; The original code goes over the pixels backwards, reversing the output...
(nreverse translated))))
(defun detect-threshold (image-data)
"Go over the image's raw pixels and get the average value.
The average is a good value to use as threshold for `format-for-oled'."
(let ((counter 0)
(total 0))
(cl-gd:do-pixels (image-data)
(setf total (+ total (cl-gd:raw-pixel)))
(incf counter))
(ceiling (/ total counter))))
(defun image-for-text (lines)
"Writes LINES list of strings in the oled screen."
;; Used the first cl-gd sample code as a starting point:
(cl-gd:with-image* (+max-image-width+ +max-image-height+)
(cl-gd:allocate-color 0 0 0) ; First color is the background (black)
(let ((white (cl-gd:allocate-color 255 255 255)))
(cl-gd:with-default-color (white)
(cl-gd:with-default-font (:small)
(cl-gd:draw-string 1 0 (or (first lines) ""))
(cl-gd:draw-string 1 11 (or (second lines) ""))
(cl-gd:draw-string 1 22 (or (third lines) "")))))
(format-for-oled cl-gd:*default-image*)))