(let* ((indexed8-image-data (make-array '(30 30) :initial-element 0))
(qimage (make-qimage indexed8-image-data 30 30 |QImage.Format_Indexed8|)))
(qfun some-object "setImage" qimage))
I don't mind if INDEXED8-IMAGE-DATA needs to have :ELEMENT-TYPE '(unsigned-byte 8) and/or that it has to be a SIMPLE-ARRAY of rank 1.
I think requiring a (SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*)) would be the easiest solution as QImage can handle different pixel encoding strategies (see [1]). This way, MAKE-QIMAGE would only need to check that the length of the array matches the width, height and QImage::Format parameter.
ECL seems to do a good job at handling displaced arrays. This should provide an easy way of handling the formats Format_Indexed8 and Format_ARGB32 as multidimensional arrays. For example
> (type-of (make-array 900
:element-type '(unsigned-byte 8)
:displaced-to (make-array '(30 30) :element-type '(unsigned-byte 8))))
(VECTOR EXT:BYTE8 900)
So I would suggest something like this.
;; %make-qimage/dangerous is an embedded C function that requires a (SIMPLE-ARRAY (UNSIGNED-BYTE 8) (*))
(defun %make-qimage/dangerous (vector width height format))
(defun %make-qimage (vector width height format)
(check-type vector (vector (unsigned-byte 8) *))
(assert (= (length vector)
(* width height (ecase format
;; all format types
))))
(%make-qimage/dangerous vector width height format))
(defun make-qimage (array width height format)
(assert (equal '(unsigned-byte 8) (array-element-type array)))
(let ((vector (convert-array-if-necessary array)))
(%make-qimage vector width height format)))