cl-libheif ยป Examples

NB: On some platforms (OSes / Lisp implementations) it's necessary to mask floating point traps, otherwise the lisp would crash (I mean it). It can be done in a portable way with float-features:with-float-traps-masked.

Image decoding

This function decodes an image (in color) from a file and returns an array with 3 color components per pixel:

(serapeum:-> decode ((or pathname string))
             (values (simple-array (unsigned-byte 8)(* * 3)) &optional))
(defun decode (name)
  (with-libheif (+default-init-parameters+)
    (with-context (ctx)
      (context-read-from-file! ctx name)
      (with-primary-image-handle (handle ctx)
        (with-decode-image (image handle :rgb :interleaved-rgb +default-decoding-options+)
          (image-plane-data image :interleaved))))))
     

The same for a grayscale image:

(serapeum:-> decode ((or pathname string))
             (values (simple-array (unsigned-byte 8)(* * 1)) &optional))
(defun decode (name)
  (with-libheif (+default-init-parameters+)
    (with-context (ctx)
      (context-read-from-file! ctx name)
      (with-primary-image-handle (handle ctx)
        (with-decode-image (image handle :monochrome :monochrome +default-decoding-options+)
          (image-plane-data image :y))))))
     

The wrapper can also read from a stream:

(serapeum:-> decode (stream)
             (values (simple-array (unsigned-byte 8)(* * 3)) &optional))
(defun decode (stream)
  (with-libheif (+default-init-parameters+)
    (with-context (ctx)
      (with-stream-reader (reader stream)
        (context-read-from-stream! ctx reader)
        (with-primary-image-handle (handle ctx)
          (with-decode-image (image handle :rgb :interleaved-rgb +default-decoding-options+)
            (image-plane-data image :interleaved)))))))

(with-open-file (input "my-photo.heic" :element-type '(unsigned-byte 8))
  (decode input))
     

You can obtain a preferred colorspace with image-handle-preferred-decoding-colorspace.

Image encoding

Encode an image and write the result to a file.
(serapeum:-> encode ((simple-array (unsigned-byte 8)(* * 3))(or pathname string))
             (values &optional))
(defun encode (data name)
  (let ((height (array-dimension data 0))
        (width  (array-dimension data 1)))
    (with-libheif (+default-init-parameters+)
      (with-context (ctx)
        (with-image (image width height :rgb :interleaved-rgb)
          (image-add-plane! image :interleaved width height 24)
          (image-set-plane-data!  image :interleaved data)
          (with-encoder-for-format (encoder ctx :hevc)
            (encoder-set-lossy-quality! encoder 90)
            (context-encode-image! ctx image encoder
                                   +default-encoding-options+)
            (context-write-to-file! ctx name)))))))
     

Metadata

Read all metadata blocks in a list (each element is a simple array of octets):
(serapeum:-> read-metadata ((or pathname string))
             (values list &optional))
(defun read-metadata (name)
  (with-libheif (+default-init-parameters+)
    (with-context (ctx)
      (context-read-from-file! ctx name)
      (with-primary-image-handle (handle ctx)
        (mapcar
         (lambda (ref)
           (image-handle-metadata handle ref))
         (image-handle-metadata-refs handle))))))