Provided with this layered definition, functions manipu-
lating rgb values can in turn be specialized with type infor-
mation. Listing 3 exhibits a layered definition for the make-
grayscale constructor, which creates a grayscale value
from an rgb one.
( de f ine-l a yered - meth o d make - g rayscal e
: in-layer va l ue-sim p le-co l or (( rgb rgb ))
( declare ( optimize ( speed 3) ( sa f e ty 0)))
( mak e -instanc e ’ grayscale
: intensi t y
( the simpl e - color
( round ( the f loat
(+ ( the f loat (* ( red rgb )
0.299))
( the float (* ( green rgb )
0.587))
( the float (* ( blue rgb )
0.114 ) )))))))
Listing 3: Layered definition for method make-grayscale
Provided with such type information, and along with ap-
propriate compiler optimization settings, this code will effec-
tively be compiled as statically (and weakly) typed code with
fully dedicated arithmetic operations. It has been shown
that the level of performance hereby achieved can be similar
to that of semantically equivalent C code[21].
Specializing the code in such a way is only a fraction of
the possibilities offered by the context-oriented approach.
In particular, one limitation to this approach is that the
object-oriented interfaces need to remain unchanged in or-
der to stay compatible with the rest of the library. The
next section presents another approach where the interfaces
themselves are modified in order to obtain further perfor-
mance improvements.
4.2 Structural Optimization: Classless Rep-
resentation
In “generic” Climb, a pixel value is an aggregation of sev-
eral color channels. In the previous section, we demon-
strated how pixel value classes can be specialized with type
information while leaving the oriented-object design of the
library unchanged.
Another approach towards performance, however, is to in-
line such values directly within the images themselves. By
default, nD images are represented with an n-dimensional
array containing indirect references to pixel values. In a
fully dedicated version however, a more efficient represen-
tation would be to use a 1-dimensional array concatenating
the image lines, and in which every cell represents one com-
ponent of a pixel value. For instance, in the case of an RGB
image, the first cell would contain the red component of the
first pixel, the second cell the green component, the third cell
the blue component etc. The advantage of this approach is a
more compact memory representation and at the same time
a more efficient pixel access (a slight arithmetic overhead for
indexation instead of using accessor functions to intermedi-
ate site-set, site and value objects). Implementing this
optimization in a contextual fashion is outlined below.
We define one layer for every possible number of color
components in an image, and as before, one layer for ev-
ery type of pixel value. For instance, there is a channel-3
layer corresponding to RGB images. Note that as soon as
we know on which particular image we’re working, we have
all the required information to activate the appropriate lay-
ers. Once activated, these layers induce the specialization
of I/O functions such as load-image, which in turn use the
appropriately optimized image memory representation.
With this optimized design in place, images no longer con-
tain references to value objects, which is normally expected
by the rest of the library. At the same time, we don’t want
to recreate such objects on the fly, only for the sake of pro-
tocol compatibility. So instead, we need to propagate those
structural changes to the whole library.
The solution we adopt here is the following. A specialized
version of the value type (not a class anymore) is defined
as a pair containing a reference to the image, and the index
of the first component of the concerned value (red for RGB
or RGBA). Provided with this new definition, we also rede-
fine methods that operate on values. Listing 4 details the
implementation of the vref method which returns one com-
ponent from a 3-components value. Note that values are not
objects in the CLOS sense anymore. On top of this func-
tion, a small layer of macrology defines direct red, green and
blue accessors by calling vref with the appropriate channel
number.
( de f ine-l a yered - meth o d vref : in- l a y e r ch a n n e l-3
( value & optional ( channel 0))
( declare ( optimize ( speed 3) ( sa f e ty 0)))
( let (( img ( car value ))
( index ( cadr value )))
( declare ( type fixnum index channel ))
( aref ( im a g e-raw- d a ta img)
(+ channel index ))))
Listing 4: Implementation of vref in the channel-3 layer
A similar optimization can be achieved on the site hier-
archy. For classical nD images, sites boil down to a set of
nD coordinates, and, as mentioned before, we don’t want to
recreate fully generic site objects on the fly, only for the
sake of protocol compatibility with the rest of the library.
So for instance, we define a 2d-coordinates layer, in which
sites are now represented by a pair of x and y coordinates.
This structural change impacts the rest of the library, and
functions such as iref (image sites accessor) are layered in
order to take into account both the optimization on values
and the specialization on sites.
5. PERFORMANCE RESULTS
In order to get an idea on the performance improvements
entailed by the contextual optimizations described in the
previous section, we analyze various low-level aspects of the
library, plus one particular example of a more general im-
age processing chain, depicted in listing 5. In this example,
we load an image, convert it to a gray-scale one, apply the
Sauvola binarization algorithm [15] and finally save the re-
sult back to a file.
( let * (( origi n a l ( im a g e -load " rgb . bmp "))
( graysca l e
( make- i m a ge ( i mage-dom a i n original )
: initfunc ( lambda ( site )
( ma k e -graysc a le
( iref original site )))))
( binary ( sauvola graysc a l e ( box2d 1))))
( image - s a ve binary " bw. jpg" ))
Listing 5: Example of an image processing pipeline
In this particular case, the original is a 2D RGB image, so
the optimized version activates the channel-3 and value-
simple-color layers, as described earlier. Note that turning