Images must have exactly 2 dimensions, and they may have one or more channels, such as red, green, blue, and alpha. Images in this protocol also have horizontal and vertical step factors that indicate the the offset of the next horizontal and vertical picture element from the current one, thereby allowing one to subsample or isolate parts of images for an operation without incurring any extra overhead.
An image may be either planar or interleaved when it is first allocated. In planar images, all of the samples in each channel are stored consecutively, and the channels themselves are consecutive in memory as well (RRR...GGG...BBB...). In interleaved images, the samples from the individual channels are interleaved with each other in memory (RGBRGBRGB...). You may explicitly allocate either type of image, but in most cases there is no reason to choose one or the other format. However, certain libraries will function more efficiently when you use certain formats. For example, OpenGL works better with interleaved images, whereas the DAT library requires the use of planar images. See the documentation of each library for more details.
Isis lists are used to store information about images. You can access the fields of these lists to obtain information about an image, including the addresses of its memory buffers. Normally, you will not need to look inside these lists at all.
new-standard-image allocates a planar byte-sampled image buffer suitable for visual data. chans should be an integer number of channels, and dims should be a list of 2 integers [xsize ysize] indicating the size of the image. All dimensions and step factors should be specified this way.
new-image allows you to create images of any sample type (not just bytes). There are two ways to use it. The first way (3 arguments) allocates a new planar image buffer with the specified sample type, channels, and dimensions. The sample type should be one of the C type constants from the memory manipulation library.
The second way of using new-image (5 arguments) allows you to refer directly to an image that already exists in memory. steps should be a list of 2 integers [xstep ystep] indicating the offset in samples (not bytes) of the next horizontal and vertical pixels from the current pixel. addrs should be list of addresses where the image data for each channel starts. The number of items in this list should match the number of channels.
new-planar-image and new-interleaved-image allow you to explicitly allocate planar or interleaved images. See the previous section for a discussion on the difference between planar and interleaved images. Note that new-planar-image works the same as the 3-argument form of new-image.
All of the image creation routines return an image description list that should be used in subsequent operations on the image.
free-image should be called on any image you do not intend to use any more. If the image memory was allocated directly by one of the functions above, it will be released. On the other hand, if the image refers to memory that was previously allocated or if it is actually a sub-image or sub-sampled version of another image, the memory will not be freed.
The following creates a new planar one-channel, integer-sampled, 512 by 512 pixel image. It might be suitable for use as a depth buffer, or as an accumulation buffer for summing several byte-sampled images.
(set image1 (new-standard-image 3 [320 240]))
In the example below, assume that addr is an address that points to the start of a memory buffer containing a byte-sampled, 640 by 480 pixel image that is stored in an interleaved fashion (RGBRGBRGB rather than RRRGGGBBB). The following creates an Isis image that refers to that memory. Recall that the addresses must point to the first element in each channel, hence the need to add the offsets.
(set intimage (new-image c-int 1 [512 512]))
The following frees all of the images created above. Recall that image2 refers to previously allocated memory, so calling free-image on it will have no effect.
(set image2 (new-image c-byte 3 [640 480] [3 (* 3 640)] [ addr (+ addr 1) (+ addr 2) ]))
(free-image image1) (free-image intimage) (free-image image2)
-> (image1 buf-dims) [ 320 240 ] -> (image1 buf-chans) 3 -> (image1 buf-addrs) [ 0x1402b84a0 0x1402cb0a0 0x1402ddca0 ] -> (image1 buf-steps) [ 1 320 ] -> (image1 buf-type) 2 -> c-byte 2
isolate-channel will isolate a particular channel from an image, and isolate-channels will isolate a range of channels, between lowchan and highchan inclusive.
Use isolate-sub-image to isolate a particular rectangle inside of an image. You must supply the location of the upper left corner of the rectangle, and the dimensions of the rectangle (both as lists of 2 integers of course).
To combine the channels of several images into one image, call combine-channels with all of the images in the desired channel order. The images must have the same type, dimensions, and step factors.
To simply create a new reference to an entire image as it stands, use refer-image.
The images returned from all of these procedures will always have an allocation status of False so that a subsequent call to free-image will not deallocate their memory buffers.
The following isolates a sub-image of the first and second channels (red and green) and fills that sub-image with a value of 255, thereby creating a yellow rectangle.
(set image1 (new-standard-image 3 [320 240])) (image-fill-constant 230 (isolate-channel 0 image1)) (image-fill-constant 128 (isolate-channel 1 image1)) (image-fill-constant 42 (isolate-channel 2 image1)) (set xwin (xwin-create)) (xwin-display-image xwin image1)
(set rgchans (isolate-channels 0 1 image1)) (set subimage (isolate-sub-image [30 30] [100 150] rgchans)) (image-fill-constant 255 subimage) (xwin-display-image xwin image1)
intersect-images expects 3 arguments: the position of origin of first buffer with respect to the origin the second, and then the first and second image buffers, respectively. A list of 2 corresponding sub-image buffers is returned. You can then apply the image processing operation on these sub-images.
intersect-rectangles does exactly the same thing with rectangles instead of actual images. You pass the relative position of R1 with respect to R2, and the sizes of the two rectangles being intersected. The return is a list of 3 items: the origin for the sub-rectangle in R1, the origin for the sub-rectangle in R2, and the size of the sub-rectangle. This procedure is called by intersect-images but can also be used independently.
# create an x window (set xwin (xwin-create)) # load an image from url using www utilities library (set url "file:/usr/local/isis/media/nick.gif") (set image1 (retrieve-url-image url)) # make a big red image (set image2 (new-standard-image 3 [640 480])) (image-fill-constant 255 (isolate-channel 0 image2)) (image-fill-constant 0 (isolate-channels 1 2 image2)) # transfer image1 into image2 at position [100 100] (set buflist (intersect-images [100 100] image1 image2)) (image-transfer (buflist 0) (buflist 1)) # display the image (xwin-display-image xwin image2)
For efficiency, if the step factor of the image buffer is not [ 1 xsize ], the image is first transferred to a temporary buffer so that only one read or write system call is necessary. This strategy speeds up transfer times greatly, especially when using an optimized version of Isis.
x1 < x2and
y1 < y2. bounding-rectangle returns the coordinates of a rectangle that bounds all of the points passed as arguments. rectangle-size returns the size of a rectangle.