2009/06/13

McCLIM で PNG フォーマットの画像を表示する

McCLIM で画像を表示するには make-pattern-from-bitmap-file で画像ファイルを読み込み、draw-pattern* で描画すればいい。 bitamp と jpeg は対応したが png は対応していなかった。 CL-PNG を使って png 対応する。

新しい画像フォーマットに対応するためには clim-extensions:define-bitmap-file-reader でファイルを読み込んで (unsigned-byte 32) の2次元配列を返せばいいらしい。中身は RGB なんだけど、残りの 8 バイトが何だかよく分からない。そこはスルー。

mcclim/Extensions/Bitmap-formats/jpeg.lisp を参考しながら実装する。

(require :mcclim)
(require :png)

(in-package :clim-user)

(defparameter *png-file*
(merge-pathnames "letter/lisp/clbuild/source/cl-png/test/images/butterfly8.png"
(user-homedir-pathname)))

(clim-extensions:define-bitmap-file-reader :png (pathname)
(with-open-file (in pathname :element-type '(unsigned-byte 8))
(let* ((png (png:decode in))
(height (png:image-height png))
(width (png:image-width png))
(data (make-array (list height width)
:element-type '(unsigned-byte 32))))
(dotimes (y height)
(dotimes (x width)
(let ((red (aref png y x 0))
(green (aref png y x 1))
(blue (aref png y x 2)))
(setf (aref data y x)
(dpb red (byte 8 0)
(dpb green (byte 8 8)
(dpb blue (byte 8 16)
(dpb (- 255 0) (byte 8 24) 0))))))))
data)))

(define-application-frame my-frame ()
()
(:pane
(make-pane 'application-pane
:display-function
(lambda (frame stream)
(declare (ignore frame))
(let ((pattern (make-pattern-from-bitmap-file
*png-file* :format :png)))
(draw-pattern* stream
pattern
0 0))))))

;;(run-frame-top-level (make-application-frame 'my-frame))

0 件のコメント: