tags:

views:

609

answers:

2

I have written code to read a windows bitmap and would now like to display it with ltk. How can I construct an appropriate object? Is there such functionality in ltk? If not how can I do it directly interfacing to tk?

+1  A: 

Tk does not natively support windows bitmap files. However, the "Img" extension does and is freely available on just about every platform. You do not need to read the data in, you can create the image straight from the file on disk. In plain tcl/tk your code might look something like this:

package require Img
set image [image create photo -file /path/to/image.bmp]
label .l -image $image
pack .l

a little more information can be found at http://wiki.tcl.tk/6165

Bryan Oakley
In that case my question is: How do I get to the data? I would like to apply some image filters.
Corporal Touchy
+3  A: 

It has been a while since I used LTK for anything, but the simplest way to display an image with LTK is as follows:

(defpackage #:ltk-image-example
  (:use #:cl #:ltk))

(in-package #:ltk-image-example)

(defun image-example ()
  (with-ltk ()
    (let ((image (make-image)))
      (image-load image "testimage.gif")
      (let ((canvas (make-instance 'canvas)))
        (create-image canvas 0 0 :image image)
        (configure canvas :width 800)
        (configure canvas :height 640)
        (pack canvas)))))

Unfortunately what you can do with the image by default is fairly limited, and you can only use gif or ppm images - but the ppm file format is very simple, you could easily create a ppm image from your bitmap. However you say you want to manipulate the displayed image, and looking at the code that defines the image object:

(defclass photo-image(tkobject)
  ((data :accessor data :initform nil :initarg :data)
   )
  )

(defmethod widget-path ((photo photo-image))
  (name photo))

(defmethod initialize-instance :after ((p photo-image)
                                       &key width height format grayscale data)
  (check-type data (or null string))
  (setf (name p) (create-name))
  (format-wish "image create photo ~A~@[ -width ~a~]~@[ -height ~a~]~@[ -format \"~a\"~]~@[ -grayscale~*~]~@[ -data ~s~]"
               (name p) width height format grayscale data))

(defun make-image ()
  (let* ((name (create-name))
     (i (make-instance 'photo-image :name name)))
    ;(create i)
    i))

(defgeneric image-load (p filename))
(defmethod image-load((p photo-image) filename)
  ;(format t "loading file ~a~&" filename)
  (send-wish (format nil "~A read {~A} -shrink" (name p) filename))
  p)

It looks like the the actual data for the image is stored by the Tcl/Tk interpreter and not accessible from within lisp. If you wanted to access it you would probably need to write your own functions using format-wish and send-wish.

Of course you could simply render each pixel individually on a canvas object, but I don't think you would get very good performance doing that, the canvas widget gets a bit slow once you are trying to display more than a few thousand different things on it. So to summarize - if you don't care about doing anything in real time, you could save your bitmap as a .ppm image every time you wanted to display it and then simply load it using the code above - that would be the easiest. Otherwise you could try to access the data from tk itself (after loading it once as a ppm image), finally if none of that works you could switch to another toolkit. Most of the decent lisp GUI toolkits are for linux, so you may be out of luck if you are using windows.

Alasdair