Думаю, это простой вопрос для тех, кто имеет опыт работы с Common Lisp. Не так много для меня, который только начал с LISP.
Как вы видите в следующем фрагменте ниже, я создаю массив размером 800 на 600 типа UNSIGNED BYTE
.
(defun test-binary-save ()
(let*
((width 800)
(height 600)
(arr (make-array (list width height)
:element-type '(mod 256)
:initial-element 0)))
(utilities::save-array-as-pgm "test.pgm" arr)))
И функция в моем пакете утилит должна записать, что в формате P5 PGM
делает диск.
(defun save-array-as-pgm (filename buffer)
"Writes a byte array as a PGM file (P5) to a file."
(with-open-file
(stream filename
:element-type '(unsigned-byte 8)
:direction :output
:if-does-not-exist :create
:if-exists :supersede)
(let*
((dimensions (array-dimensions buffer))
(width (first dimensions))
(height (second dimensions))
(header (format nil "P5~A~D ~D~A255~A"
#\newline
width height #\newline
#\newline)))
(loop
:for char :across header
:do (write-byte (char-code char) stream))
;(write-sequence buffer stream) <<-- DOES NOT WORK - is not of type SEQUENCE
))
filename)
Эквивалентная (и работающая) C -функция, которая делает то же самое, выглядит следующим образом.
static
int
save_pgm
( const char* filename
, size_t width
, size_t height
, const uint8_t* pixels
)
{
if(NULL == filename)
return 0;
if(NULL == pixels)
return 0;
FILE *out = fopen(filename, "wb");
if(NULL != out)
{
fprintf(out, "P5\n%zu %zu\n255\n", width, height);
size_t nbytes = width * height;
fwrite(pixels,1,nbytes,out);
fclose(out);
return 1;
}
return 0;
}
Кто подскажет, как исправить мою save-array-as-pgm
функцию, желательно с записью массива в один go вместо использования al oop и (write-byte (aref buffer y x) stream)
?
Прежде чем я решил задать этот вопрос здесь, я много гуглил и нашел ссылки только на некоторые пакеты, которые делают причудливые двоичные вещи - но это простой случай, и я ищу простое решение.