1 ;; macros to handle volumes
5 (defmacro with-arrays
(arrays &body body
)
6 "Provides a corresponding accessor for each array as a local macro,
7 so that (ARRAY ...) corresponds to (AREF ARRAY ...)."
8 `(macrolet ,(mapcar (lambda (array)
9 `(,array
(&rest indices
) `(aref ,',array
,@indices
)))
13 (defmacro with-linear-arrays
(arrays &body body
)
14 "Exposes the linear array for each of the supplied arrays. When a
15 and b are multidimensional arrays you can use (with-arrays (a
16 b) (setf (a1 0) (b1 324))) to access their storage vectors."
17 (let* ((arrays1 (mapcar #'(lambda (x)
19 (error "only symbols are allowed in with1."))
20 (intern (format nil
"~a1" x
)))
22 `(let (,@(mapcar #'(lambda (x y
) `(,x
(sb-ext:array-storage-vector
,y
)))
27 (defmacro do-region
((indices end
&optional
(start '(0 0 0))) &body body
)
28 "Write intertwined loops to traverse a vector, an image or a volume."
29 (unless (and (= (length indices
)
31 (error "Number of indices and interval-ends are not equal."))
32 (labels ((rec (ind end start acc
) ;; several loops
35 (rec (cdr ind
) (cdr end
) (cdr start
)
36 `((loop for
,(car ind
) from
,(car start
)
37 below
,(car end
) do
,@acc
))))))
38 (first (rec (reverse indices
) ;; first index is outermost loop
40 (reverse start
) body
))))
43 (do-region ((k j i
) (4 4 5))
48 (defmacro with-slice
((slice-array array slice-nr
) &body body
)
49 "Returns SLICE-NRth slice of ARRAY as the 2D SLICE-ARRAY."
50 (alexandria:with-gensyms
(x y z
)
51 `(destructuring-bind (,z
,y
,x
)
52 (array-dimensions ,array
)
53 (when (or (< ,slice-nr
0) (<= ,z
,slice-nr
))
54 (error "slice-nr=~d out of range [0,~d]" ,slice-nr
(1- ,z
)))
55 (let* ((,slice-array
(make-array (list ,y
,x
)
56 :element-type
'(unsigned-byte 8)
58 :displaced-index-offset
(* ,slice-nr
,x
,y
))))