/xielib

Sample code for the book Developing Imaging Applications with XIElib by Syd Logan

Primary LanguageC

XIElib Sample Client Release Notes
----------------------------------

Bug reports
-----------

This software was developed on Linux 1.0.9 and Linux 1.2.13 with the July 
1994 X11R6 release, as well as the more recent X11R6.1 and X11R6.3 releases. 
The compiler used for this build was gcc version 2.7.0. The Imakefiles have
been made to work with R6.3 but should be fine for whatever version of R6 
you have installed on your host. 

This release was built and lightly tested on a 16bpp TrueColor RedHat Linux
system. A few problems with 16bpp support in the backend code (lib/backend.c)
for TrueColor and StaticColor visuals were detected and patches have been
applied. The backend code now, for all visuals with a bpp greater than 8, 
will automatically make use of a StandardColormap. RGB_BEST_MAP is used if
the image is color, and RGB_GRAY_MAP is used if the image is grayscale (and 
not bitonal). 

Please report any and all problems, bugs, questions, etc. to me, Syd 
Logan, at slogan@cts.com. I am particularly interested in hearing about 
problems with imake files and compiler warning/ error messages that you 
might encounter as the software is ported to various Unix platforms. If 
the software happens to port happily to your system, I'd like to hear 
about that too. Please include the output of:

$ uname -a

when reporting any successes (or failures for that matter) so I can keep 
track of things accurately. 

Currently, the samples are known to build on:

- SunOS 5.3 (presumably other variants of Solaris as well)
- OSF1V3

as well as Linux, as described above.

If you have any suggestions for samples, or need some help, don't hesitate
to ask.
 
A bug report form similar to that used by the X Consortium is provided as a 
template for bug reports/suggestions. It is located in the file bugs.template. 
If you want to supply any fixes or changes, please provide context diffs so 
that it is easier for identify and integrate the changes:

$ diff -c old_version.c your_version.c > paste_this_into_report

Most clients now use the backend code which is provided in lib/backend.c to
prepare image pixels for display. See backend/backendtext.c for the most
comprehensive example of this technique. Clients which don't make use of the
backend code as of this release include average, balance, modify, redefine, 
and the clients found in the xlib directory. An effort is being made to modify 
these clients, and a release is forthcoming. You may experience problems with 
these clients unless you are running on an 8-bit PseudoColor display.

Release Contents
----------------

The release itself consists of 3 logical components, stored as 3 separate
subdirectories in the distribution:

libtiff - this contains the Sam Leffler/SGI 3.30beta version of libtiff. 
Several of the sample clients require a libtiff.a to link properly. While 
they have only been tested with this version of libtiff, later (and possibly 
earlier) versions of the library will probably work as well. Consult the 
readme files provided for information on obtaining the latest version of 
libtiff. I will probably upgrade in the next release of this software.

Follow the instructions provided with the libtiff release to build libtiff.a 
library. This should be done before you attempt to compile the sample code 
which is located in the "samples" directory (as described below).

jpeg - this is release 4A of the Independent JPEG Group's JPEG software. A
few clients refer to headers located in this directory, and link to libjpeg.a
which can be built from the sources found here. 

samples - this directory contains all of the sample XIElib code developed for 
this release. To build these clients, you will need to first compile libtiff.a 
as described above. For this release, you also must have an X11R6 release 
installed on your host so that you can generate makefiles from the provided 
imake files. X11R6 libXIE.a and libX11.a plus the appropriate header files 
must also be present to build the clients. 

A fourth directory, images, may be provided if this distribution media can 
support its large size. Most of the samples work with grayscale JPEGs, a few 
work with CCITT images stored in TIFF files, PGM, PPM, color JPEGs, or raw 
SingleBand (grayscale) images. With the only exception of raw SingleBand 
images, which need to be of a specific size, you should be able to provide 
your own image data (xv can be used to generate any of the above types - to 
date I have not had a problem reading xv-generated image files). 

Building the software
---------------------

First, you'll need to build libtiff and libjpeg. The instructions for 
building libtiff are provided in release notes in the libtiff directory. 
libtiff provides several makefiles which you can use, for my Linux system 
which uses gcc, I simply cd to libtiff/libtiff, and type:

$ make -f Makefile.gcc

Libjpeg is a little more difficult. The file SETUP contains instructions. On
my Linux system, I make the following symlink: 

$ ln -s jmemansi.c jmemsys.c

and then type: 

$ make -f makefile.ansi libjpeg.a

Once libtiff and libjpeg are built, cd into xiesamples and type the following:

$ /usr/X11R6/bin/xmkmf		-- your path may vary
				  
$ make Makefiles

$ make

That's it. 

Running The Clients
-----------------

Instructions including usage are included below. Most clients can be exited 
by clicking the mouse in the main window displayed by the client. Most clients 
are designed to wait for their windows to be mapped before photoflo creation 
and execution is performed. With a few exceptions (the nails and scale clients 
for example) clients are not designed to redraw their contents should exposures
occur on their contents. Setting the backing store to always on your server 
when possible will compensate for this, but the better thing to do would be 
to route the image data sent to ExportDrawable also to a photomap resource 
and execute a simple photoflo consisting of ImportPhotomap -> ExportDrawable 
if and when exposures occur. At some time I may make all examples do this 
but for now I guess it is "left to the reader" as an exercise to do this.

Similarly, some clients only are designed to work with 8-bit PseudoColor 
visual classes. You are encouraged as X client developers to develop 
photoflos which work on *any* X terminal or server, be it 1-bit "monochrome", 
8-bit PseudoColor, or 24-bit TrueColor. The client backend_test in backend.c 
provides an example of how one might attack the problem of developing a 
visual class-neutral XIElib client; most other clients also make use of the
backend code which is supplied and can be used as examples.

Chapter 19 in the book is devoted to the issues addressed by the client 
backend_test, and the code provided in lib/backend.c which was used to 
implement it. 

Sample descriptions
-------------------

As of yet, I don't have README files for the individual samples. Probably I 
will do something in man page format when I get the time. For now, you can 
type:

$ foo -?

(foo represents the name of a binary)

to get a usage statement if you need to know the arguments. Almost all of the 
clients will accept a '-i' argument to specify the name of the image file to 
be processed/displayed:

$ histo -i ../../images/jpeg/gray/dadgray.jpg

for example. 

Here are the contents of the samples directory as of this release and brief 
descriptions of each client and the arguments that they accept:

arith/

	arith [-c constant] [-d display] -i image -o operator

Operator can be one of the following strings (the corresponding Arithmetic
element operator is listed to the right of the argument):

Argument	Arithmetic Operator
---------	------------------

"ADD"		xieValAdd
"SUB"		xieValSub
"SUBREV"	xieValSubRev
"MUL"		xieValMul
"DIV"		xieValDiv
"DIVREV"	xieValDivRev
"MIN"		xieValMin
"MAX"		xieValMax
"GAMMA"		xieValGamma

constant represents the second operand of the arithmetic operation performed,
and should be a value in the range [0,255]. If constant is not specified, 
then it defaults to 1.

For each pixel Pi in the image, arith will perform the operation 

Pi = Pi operator constant

For example, if Pi is 128, operator is ADD, and constant is 12:

Pi = 128 + 12 = 140

The effect would be to increase the brightness of the image by a constant 
factor of 12.

average/

	average [-d display] [-r reps] -i image

Average takes an image, and creates and initializes two photomap resources, 
one which contains the image after decode, the other which contains a version 
of the image after a low-pass filter has been passed over the image using a 
Convolve element. Once these two photomaps have been generated, the client 
then loops reps times. In each loop, the client reads the photomaps, adds 
them together with an Arithmetic element, divides the result by two using 
another Arithmetic element, storing the result in one of the photomaps, and 
displaying the result in a new X window. The image specified by the client
must be JPEG, but can be SingleBand or TripleBand.

	frame [-d display] [-r frames] [-r rate] -i image

Frame is similar to average. Shot noise (random pixels set to white and 
black) is added to a number of images (specified by -r or default 50).
These images are added together and divided by the number of frames in 
a somewhat successful attempt to rid the image of the shot noise. Frame
accepts either a Portable Pixmap (PPM) TripleBand image or a Portable
Graymap (PGM) SingleBand image, and illustrates the use of Uncompressed
Single and UncompressedTriple decode techniques. 

Both frame and average make use of Dither (only if the image is TripleBand), 
ConvertToIndex, and ExportDrawable as backend elements, and assume an 8 bit
-per-pixel display. This scheme is intended to work with X displays which 
are PseudoColor and 8-bit deep. 

backend/

	backendtest [-d display] [-m StandardColormap ] [-c visual class] 
		-i image

This may be the most important client provided.

This client illustrates the use of the photoflo backend code in lib/backend.c 
designed to do the image class and levels attribute processing required to 
display any given image (bitonal, color or grayscale of arbitrary depth) on 
any given display (to a window belonging to an arbitrary visual class and 
having an arbitrary depth).

The client accepts TripleBand, SingleBand, and bitonal image data. TripleBand 
and SingleBand image data must be supplied as JPEG (JFIF files); the bitonal 
image data must be CCITT FAX (G32D, G32D, or G42D) which has been stored in a 
TIFF file.

To cause the client to use a StandardColormap, specify the standard colormap 
atom as the -m argument, which can be one of:

Argument	StandardColormap Atom
---------	----------------------

"BEST"		XA_RGB_BEST_MAP
"DEFAULT"	XA_RGB_DEFAULT_MAP
"GRAY"		XA_RGB_GRAY_MAP
"RED"		XA_RGB_RED_MAP
"GREEN"		XA_RGB_GREEN_MAP
"BLUE"		XA_RGB_BLUE_MAP

The user can also specify the use of one of the 6 visual classes defined by X, 
if supported by the X server. The -c argument accepts the following:

StaticGray
GrayScale
StaticColor
PsuedoColor
TrueColor
DirectColor

Some visual classes do not support certain standard colormaps. If the -m and 
-c arguments conflict, a message stating this will be displayed by the client.

balance/

	balance [-d display] [-r red] [-g green] [-b blue] [-c cyan] 
		[-m magenta] [-y yellow] -i image

Balance accepts a TripleBand JPEG image, converts it from YCbCr to RGB. The
RGB image is then passed through an Arithmetic element, which multiplies each
pixel by coefficients which are designed to enhance the color associated with 
the -r, -g, -b, -c, -m, -y arguments specified by the user. For example, the
command line

	balance -i foo.jpg -r 1

causes the image to be multiplied by the coefficients 1.025, 0.985, and 0.985
before display. Specifying -r 2 causes the coefficients to be applied twice, 
intensifying the dominance of the red component of the image.

bands/

	bands [-d display] [-c] -i image

Bands accepts a TripleBand JPEG image and displays each of its bands as a
grayscale image in a window. By default, the program displays Y, Cb, and
Cr components. Specifying -c causes the image to be converted to RGB before
the components are extracted, causing the R, G, and B components of the
image to be displayed instead. Notice that the Y component represents the
grayscale component of the image, and displays as a grayscale version of
the original color image. The Cb and Cr components of the image contain 
color information, and while when displayed they resemble a grayscale 
version of the image, neither can be used for this purpose. None of the R, G
or B components provide acceptable grayscale representations of the original
color image, since each band is a combination of grayscale and color content.

blend/

	blend [-display display]

Blend illustrates the use of the Blend process element. Blend is an Xt client
which uses the Athena Widget set. 

A Blend element is used to combine two images, or an image and a constant src.
The blend operation is controlled by an alpha constant and an optional alpha
image input. If an alpha image is used, then each output pixel is defined as:

(eq. 1)	output = src1 * ( 1 - alpha / alphaC ) + src2 * ( alpha / alphaC )

If no alpha image is used, then each output pixel is defined as:

(eq. 2)	output = src1 * ( 1 - alphaC ) + src2 * alphaC

when output is the value at pixel i in the result, src1 is pixel i in source
image 1, alpha is pixel i in the alpha image, alphaC is the alpha constant,
and src2 is pixel i in source image 2.

The File menu is used to select JPEG grayscale images corresponding to src1,
src2, and alpha. As each image is selected, it is displayed along with its
grayscale histogram. The Options menu can be used to display each of these
images upon selection of the appropriate menu item, as well as the result of
the images being passed through a Blend process element.

The toggle "Use Alpha" can be used to control the use of the alpha image. If
set, the alpha image is used e.g. (eq. 1) is used by the Blend element to 
compute the result. If unset, then (eq. 2) is used by Blend.  

The toggle "Use Constant" determines if src2 is based upon the image data 
selected by the user, or a constant specified by the "Const" slider above
it in the GUI. 

The "Const" slider can be used to specify a constant which will be used as
src2 if either the "Use Constant" toggle is selected, or no alpha image 
has yet been selected via the File menu option, regardless of the 
toggle's value. A value in the range of 0 (black intensity) to 255 (white 
intensity) may be chosen using the slider. 

The "Alpha" slider can be used to select a value for alphaC used in eq. 1 
and eq. 2 above. The "Alpha" slider allows the user to select a value in
the range of [0.0, 1.0]. If eq. 1 is used by Blend, the selected value
is automatically converted (not by XIE or the Blend element, but by code
in the client) to a value in the range of [0.5, 255.0] by multiplying the
slider value by 255, and setting it to 0.5 if the result is equal to zero.
Note that we cannot use zero because that would result in a divide by zero
error (this is checked for by XIE, a Value error is returned if zero is
sent by the client with a non-zero alpha phototag input). If eq. 2 is used
by Blend, the the slider's value in the range [0.0, 1.0] inclusive is used.

To see how Blend works, consider eq. 2. If alphaC is zero, then src1 will
dominate (e.g. the resulting image is src1 with no contribution of src2). 
If alphaC is one, then src2 dominates, with no contribution of src1 to the 
result. Values of alphaC between 0.0 and 1.0 are used to incorporate both
src1 and src2 in the computation of the resulting image. As alphaC tends
to 0.0, src1 has increasing influence over the result, and as alphaC tends
to 1.0, src2 has similar influence.

Things are similar for eq. 1, but in this case alphaC and alphaP are used 
to compute a value in the range [0.0, 1.0], after which we regress to the
behaviour of eq. 2. In this client, alphaC is scaled to [0.5, 255] since
we are using it to divide pixels in the range [0, 255] (again, we use 0.5
as a lower bound to avoid Value errors as described above).

clientio/

	cliodemo [-d display] -i image

This client demonstrates how to read client data from photoflos which have
more than one ExportClient element asynchronously using the library function
ReadNotifyExportVector (see clientio.c in the lib directory). 

constrain/

	constrain [-d display] -i image [-h] [-j inLow ] [-k inHigh ] 
		[-l outLow] [-m outHigh]

Constrain demonstrates the use of the Constrain element and it's supported 
techniques. The -h flag causes Constrain to use the HardClip technique, with 
pixels in the image being clipped to the range [0, outHigh], where outHigh is 
specified by the -m argument. If -h is not specified, the ClipScale technique 
is used instead, with the result defined by the -j, -k, -l and -m arguments.  
Constrain accepts a SingleBand JPEG image as input.

Constrain also demonstrates the use of ExportClientHistogram, and it displays
histograms of the image before and after application of the Constrain element
to illustrate how the intensity values in the image are redistributed.

convolve/

	convolve [-d display] -i image -k kernel_file [-c constant] 

Convolve accepts a SingleBand or TripleBand JPEG image. The image is passed
though a Convolve element, with the size and contents of the convolution 
kernel defined by the file specified by the -k argument. Several kernel files 
are provided along with the client in the kernel subdirectory.

dither/

	dither [-d display] -i image [-l levels] [-o threshold]

Dither takes a SingleBand JPEG Baseline image and dithers it for display
based upon the arguments provided. XIE supports two dither techniques; 
Error Diffusion (also known as Floyd-Steinberg dithering), and Ordered. 
In general, ordered is faster, but less satisfactory than Error Diffusion.
This client allows you to play with both to get an idea of how they compare
to each other. Two sh scripts, compare and ordered, are provided to help you
get started in making a comparison of the supported dither techniques. The 
script named Ordered compares ordered dither using thresholds of 1 and 8 
(1 will give less satisfactory results than 8 but will be faster, and the
quality difference is greater as dither levels becomes smaller e.g. dither
to 64 levels from 256 won't produce as dramatic a difference between the
two thresholds as will dither to 4 levels from 256 will). The compare sh
script compares Error Diffusion to Ordered for the same amount of levels
reduction for the same image. The speed difference may not be perceivable 
on your server, but the quality differences will be for sure. 

dumptech/

	dumptech [-d display]

Dumptech queries XIE and displays to stdout information about the techniques 
which are supported by the server to which the client is connected. Notice
that in the XIE-SI, all techniques have the same speed rating, and so the
"Fastest technique" output should be viewed with some skepticism. It is up
to server vendors to supply meaning values in their ports.

edraw/

	edraw [-d display] [-c] [-s] [-p planemask] [-x xOffset] [-y yOffset] 
		[-f function] -i image

Edraw allows the user to experiment with various GC attributes and arguments
to XieFloExportDrawable to determine how they affect the display of an image. 
The arguments supported are:

-c	the GCClipMask attribute of the GC is set, and the bitmap
	stored in the file "bitmap" provides the clipmask pixmap.	

-s	the subwindow_mode of the GC is set to IncludeInferiors

-p planemask	the GC plane_mask is set to planemask

-x xOffset	the origin in the drawable of the displayed image is located
		with an x coordinate of xOffset

-y yOffset	the origin in the drawable of the displayed image is located
		with an y coordinate of yOffset

-f function	the GC function is set based upon one of the following values:

Argument		GC function
---------		----------
"GXcopy"		GXcopy
"GXclear"		GXclear
"GXand"			GXand
"GXandReverse"		GXandReverse
"GXandInverted"		GXandInverted
"GXnoop"		GXnoop
"GXxor"			GXxor
"GXor"			GXor
"GXnor"			GXnor
"GXequiv"		GXequiv
"GXinvert"		GXinvert
"GXorReverse"		GXorReverse
"GXcopyInverted"	GXcopyInverted
"GXorInverted"		GXorInverted
"GXnand"		GXnand
"GXset"			GXset

The image specified by -i must be JPEG and SingleBand for it to work with 
edraw.

edrawp/

	edrawp [-d display] [-c] [-s] [-p planemask] [-x xOffset] [-y yOffset] 
		[-f function] [-h fill-style] -i image

Edrawp is similar to edraw except that ExportDrawablePlane is used instead
of ExportDrawable. The arguments accepted by edrawp are identical to those
accepted by edraw. An additional argument, -h fill-style, can be specified.
fill-style can take on one of the following values:

Argument			Fill Value
---------			--------

"FillSolid"			FillSolid
"FillTiled"			FillTiled
"FillStippled"			FillStippled
"FillOpaqueStippled"		FillOpaqueStippled

While edrawp accepts an image file argument (-i), it currently only is able 
to read the G31D image stored in the file images/bitonal/g31d.raw. The next 
version of this program should be able to read any CCITT bitonal image stored 
in a TIFF file.

emp/

Emp is a Motif application that implements a small employee database, and 
illustrates basic intergration of XIE into a simple Motif application. The
design of the client is described in the September 1998 issue of Linux 
Journal (www.ssc.com).

errors/

	generrs [-d display] [h][r]

This client demonstrates how to write code which can handle XIE error events 
as opposed to having XIElib handle them on the client's behalf. In XIElib, 
as in Xlib, the default error handlers exit after displaying a message to 
the screen; in many cases, such behavior is not acceptable since a client may
need to perform cleanup and recovery before the application exits. In XIE, as 
opposed to X, errors are not necessarily fatal; while the photoflo may 
terminate its execution, recovery by the client is often possible. A good
example of this is sending a poorly encoded image to ImportClientPhoto. It
is perfectly likely in some applications that a user will select a corrupt
image, and XIE will generate an error from ImportClientPhoto when trying to
decode it. It is much better for the client to capture this event and put
up a dialog such as "Image data was corrupt - unable to decode" as opposed
to allowing XIElib to capture the error, dump a terse error to stderr, and
exit.

The argument -h causes the client to use its own error handler. Specifying 
-r causes a LUT resource error to be generated by the client. Otherwise, a 
FloLUT error is generated.

expose/

	expose [-d display] -i image [-p] [-a] 

Expose illustrates two basic strategies for handling expose events in 
windows to which a photoflo has displayed an image. The first strategy,
which is the default if -p is not specified, is to send the output of
the photoflo (prior to the image data being processed by the backend)
to a photomap, and then run the following photoflo:

	ImportPhotomap -> (Backend)

to display it. A derivative of this method would be to take the result
of the photoflo, including any elements in the backend up to but not
including the ExportDrawable(Plane) element, and place it in a photomap,
and run:

	ImportPhotomap -> ExportDrawable(Plane).

The problem with this photoflo is that the backend may be needed. For
example, putting the image data through ConvertToIndex would be useful
in dealing with colormap changes which may have occured between expose
events on the window (that brings up another issue; refreshes generally
should be considered also if ColormapNotify events are received since 
the changes to the colormap might invalidate the image data rendered
to a window).

Specifying -p causes the sample to route the result of the backend
(again up to but not including EDP or ED) to a Pixmap. The photoflo 
which is executed to handle refreshes is:

	ImportDrawable(Plane) -> ExportDrawable(Plane).

where the drawable associated with ID(P) is the Pixmap, and the drawable
associated with ED(P) is of course the client window.

Normally, ID(P) only snarfs the portion of the Pixmap which corresponds
to the expose event (using the report x, y, width and height fields of
the event). The entire Pixmap is read and displayed if the -a argument
is specified.

Surely reading from a Pixmap only those bits corresponding to the actual
exposed area is faster than using IP -> ED(P) (e.g. reading from a 
photomap) even if the backend is considered and the photomap is storing
colormap index data directly displayable in the window. This is because
the IP -> ED(P) strategy requires the entire area of the window to be
updated, regardless of how much is actually in need of refreshing.

The client is capable of dealing with grayscale or color JPEG data. It
uses backend code (like most samples do) so it should work on any 
display. Note that most of the sample clients do not have a refresh
strategy. This does not imply that a strategy for handling refreshes
is unimportant in your applications.

faxview/

	faxview [-d display] -i image [-a angle]

Faxview scales a FAX using Geometry so that the height of the image is within 
the limits of the display and then displays it in an appropriately sized 
window. The fax image is read from a TIFF file and can be encoded as G31D, 
G32D, or G42D. If the -a argument is specified, the image is rotated about 
its center by the number of degrees specified by angle. The sample technique
used for the scaling and rotating is bilinear interpolation. 

geometry/ 

	geometry [-d display] [-s a] | [-s b] -i image -t transforms

Geometry illustrates an approach to dealing with the specification of the 
affine transforms required by the Geometry process element. The geometric 
operations to be performed on the image are specified in the file identified 
by the -t argument.

Any number of transformations can be specified in the file; geometry 
represents each as a 3x3 transformation matrix and concatenates these 
together to arrive at a single 3x3 matrix from which the coefficients 
needed by the Geometry element are extracted. See concat, below.

	scale [-d display] -i image [-s a] | [-s b]

Scale displays the grayscale JPEG image specified by the -i argument in
a window. As the window is resized, the image is passed through a 
Geometry element which rescales it to the window's dimensions. It is then 
redisplayed. The image data is cached on the server in a photomap after
being decoded to facilitate its display upon window exposures. 

	concat [-d display] -i image [-s a] [-s b] [-a angle] [-x scaleX]
		[-y ScaleY] 

Concat illustrates the results of applying geometry elements to an image
in series, as opposed to constructing a single set of transformation 
coefficients as is done by "geometry" (above).

Try comparing the results of executing geometry using the provided coeffs 
file:

rotate 45
scale 0.5 0.5

and an execution of concat with arguments of -a 45 -x 0.5 -y 0.5 by running
xmag to view portions of the resulting output. Although the transformations 
applied are the same, doing the sampling only once, as done by geometry, as
opposed to twice, as is done by concat, will generate a better result. This
can perhaps be seen best if pixels along borders in the image are inspected.
The effect of placing geometry elements in series will worsen as the number
of elements in the series is increased (depending upon which transformations 
are performed, the data being transformed, and the sampling technique used).

The sample technique used by the above clients is nearest neighbor. If -s b 
is specified, then bilinear interpolation is used. If -s a is specified, 
the sample technique used is antialias. 

hasxie/

	hasxie (no arguments, set your DISPLAY variable before executing)

Hasxie is everything you'd want in an XIE "Hello World" program, and less :-)
It simply calls XieInitialize, and exits with a 0 if XIE is supported by the
server, or a 1 otherwise.  
	
hist_slide/

	hist_slide [-d display] [-s constant | -a constant] [-m factor] 
		-i image

Hist_slide demonstrates how to perform some simple histogram stretching and
manipulation tasks on an image in addition to those of the type performed by
MatchHistogram. The following options are supported by hist_slide:

-s constant		subtract constant from each pixel, sliding the 
			histogram to the left

-a constant		add constant to each pixel, sliding the histogram 
			to the right

-m factor		multiply each pixel by factor; stretching the 
			histogram within the range of the image

icr/

	icr [-d display] -m max -i image

Icr demonstrates the ImportClientROI element and the use of process domains. 
The image data is passed through an Arithmetic element which computes each 
pixel in the grayscale JPEG image as the max of its previous value or that 
specified by the -m argument. This processing is restricted to the regions of 
the image coinciding with the ROIs which were sent by the client and which 
form the process domain of the Arithmetic element.

idraw/

	idraw [-d display] [-f output_file] [-c]

This client demonstrates the use of the ImportDrawable element. This client is
somewhat similar to the X client xwd; some portions of xwd were borrowed in
order to implement this client. If the -f argument is supplied, a JPEG (JFIF) 
file containing the imported image data will be written. The image data which 
is retrieved is displayed in a window using ExportDrawable.

If -c is specified, a TripleBand JPEG will be written. Otherwise, the result
is SingleBand. 

idrawp/

	idrawp [-d display]

The photoflo build by idrawp imports two raw SingleBand images, image.001
and image.002, and displays them in a window. The client creates a pixmap 
resource, and uses Xlib graphics calls to render polygons and cicles, etc., 
into the pixmap. Then, ImportDrawablePlane is used to retrieve a plane from
the pixmap. This bitonal image is used as a control plane (process domain) for
a Logical process element which uses a copy operator to copy portions of one
of the images into the other in the areas corresponding to the control plane.

jpeg/

	qtables [-d display] -i image -o output [-h horizontal sample] 
		[-v vertical sample] [-q quality] [-s] [-f] [-a] [-c]

Qtables illustrates the various technique parameters which are supported by 
the JPEGBaseline encode technique. The client accepts the following arguments:

-s		display image in a window
-q		quality factor in range [0,100]
-f		use quantization tables provided by XIE (ignoring -q)
-a		use ac tables provided by XIE
-c		use dc tables provided by XIE

The code is extensively commented; be sure to read the comments which describe
the -f, -a, and -c arguments.

Perhaps the most outstanding feature of the client is the -q argument. Many 
JPEG encoders (at least, most of those seen by me anyway) allow the user to 
specify a tradeoff between image quality and compression. The issues behind 
the tradeoff are well documented in the book. This tradeoff is generally 
specified as a value between 0 and 100, where 100 represents high image 
quality and low compression, and 0 represents very bad quality but exceptional 
compression. Usually, a value close to 75 or so is used which results in no 
noticeable image degradation and an acceptable amount of compression. XIE 
does not accept a quality factor, but this client illustrates how one can be 
implemented by clients which desire it.

jpegtoraw/

	jpegtoraw [-d display] -i image -o output [-f fillOrder] 
		[-p pixelOrder] [-s pixelStride] [-c scanlinePad] 
		[-w number of output levels]

Jpegtoraw accepts a SingleBand JPEG image as input, and converts the image to
UncompressedSingle which is exported from the photoflo and stored in a file.
The attributes of the uncompressed encoding can be specified as command line
arguments.

lib/

This directory contains the source and makefiles used to build libsamp.a, 
which contains routines needed by many of the sample clients on the CD. 
Please take the time to look through this source; the intent is that the 
routines it provides will help you in building your own XIElib clients.

match_hist/

	histo [-d display] [-f] [-g mean sigma] [-h const [True|False]] 
		-i image

Histo demonstrates the XIE MatchHistogram element. 
 
Histo allows you to experiment with the various histogram equalization
techniques of XIE 5.0. Which technique is used is defined by command line
arguments to histo:
 
Flag Parameters    Matching Technique   Example Command Line
 
-f   None          Flat                 histo -f -i image.001
-g   mean sigma    Gaussian             histo -g 128.0 64.0 -i image.001
-h   const shape   Hyperbolic           histo -h 32.0 False -i image.001
                                        histo -h 32.0 True -i image.001

Histo only supports SingleBand JPEG image data, but can be easily modified
to support TripleBand image data as well.

modify/

	modify [-d display] [-s sleeptime ] -i image -o offsetfile

Modify illustrates the use of the XIElib function XieModifyPhotoflo. The 
client executes the stored photoflo 

ImportClientPhoto -> ConvertToIndex -> ExportDrawable

once for each x, y offset in the file offsetfile. The client modifies the
ExportDrawable element in the photoflo after each iteration, changing the x 
and y offset of the image in the drawable to the next coordinate read from 
the file, using XieModifyPhotoflo. 

Note: a more efficient strategy would be to execute two photoflos. The first,

ImportClientPhoto -> ExportPhotomap

would be executed only once to obtain the image data from the client and 
store it in a photomap resource. This photoflo would be an immediate photoflo 
executed by XieExecuteImmediate. The next photoflo

ImportPhotomap -> ConvertToIndex -> ExportDrawable

would be the stored photoflo which would be iterated for each x, y offset in 
the offsetfile.

pasteup/

	nails [-d display] -i directory

The client nails scans the directory specified by the -i argument for any
SingleBand JPEG files. The following stored photoflo is then created:

ImportClientPhoto -> Geometry -> ExportPhotomap

Each file is then read and stored in its own photomap resource, scaled to the 
dimensions 64x64.  XieModifyPhotoflo is used to change each of the elements in
the above photoflo for each image read; ImportClientPhoto is modified because 
the attributes (e.g. width and height) of the image may change, Geometry is 
modified because the width and the height of the image affects the scaling 
coefficients used, and ExportPhotomap iis modified because the target photomap
changes for each image.

Once this is done, the client goes into an X event loop processing expose 
events on the window to which the thumbnails are to be drawn. Whenever an 
expose event is seen, the client creates a photoflo which has n ImportPhotomap 
elements (n is the number of images displayed as thumbnails). For each of the 
thumbnails the client creates a tile and places the tiles as best as possible 
in the window based upon the window's geometry at the time of the expose 
event. A PasteUp element is added to the photoflo downstream of the 
ImportPhotomap elements, and PasteUp feeds ConvertToIndex and then an 
ExportDrawable element which displays the image which was formed by the 
PasteUp element.

point/

	falsecolor [-d display] -i image [-s [contour rainbow sin]] [-c incr]

Falsecolor uses the Point element to generate a falsecolor version of the
SingleBand JPEG image specified by the -i argument. The -s and -c arguments
define the LUT which is used by Point. The type of falsecolor effect acheived
is specified by the -s argument, which determines how the LUT is initialized.
If the selected effect is contour, the increment can be specified by the -c 
argument (the default contour increment is 16). The SingleBand image is 
converted to TripleBand by passing it though a Point element which uses a 
TripleBand LUT. Falsecolor uses backend code defined in lib/backend.c to 
prepare and display the image after the falsecolor operation is performed.

	trig [-d display] -i image -f [sin cos tanh] [-p period] [-a amplitude]

Trig also accepts a SingleBand JPEG input. A LUT is created, with each cell 
in the LUT initialized using one of the following equations based upon the 
function selected by the -f argument:

lut[ i ] = sin( TORAD( i * (360.0 / period) ) ) * amplitude;
lut[ i ] = cos( TORAD( i * (360.0 / period) ) ) * amplitude;
lut[ i ] = tanh( TORAD( i ) ) * amplitude;

Amplitude is defined by the -a argument, and period is defined by the -p. The
default period is 360 (degrees), and the default amplitude is 1.0. 

Trig is intended to show how Point can be used to perform a math operation on 
an image much like is done by the Math or Arithmetic elements for operator 
which neither element supports.

redefine/

	redefine [-d display] [-s sleeptime ] -i image -o offsetfile

Redefine is similar to the client modify, described above. In the modify 
client, XieModifyPhotoflo is used to change the ExportDrawable element in 
the photoflo once for each offset in offsetfile, causing the image to be 
displayed in the client window at that offset. In addition, the modify 
client uses the topology

ImportClientPhoto -> ConvertToIndex -> ExportDrawable

and executes this once for each image, requiring the image to be transmitted 
multiple times from the client. The redefine client acheives the same result 
as modify, but implements a more efficient scheme in which the image is sent 
to the server once using the stored photoflo

ImportClientPhoto -> ExportPhotomap

Once the above photoflo is executed, but is replaced using XieRedefinePhotoflo
with the following topology:

ImportPhotomap -> ConvertToIndex -> ExportDrawable

XieRedefinePhotoflo was required for this task since the number of elements 
in the photoflo changed from 2 to 3.

From this point on, redefine reads from the offsetfile and executes the 
photoflo above once for each offset read. XieModifyPhotoflo is used to change 
the offset by replacing ExportDrawable before execution. XieModifyPhotoflo 
can be used here because only one element needs changing and the size of the 
photoflo is to remain the same. 

rgb/

	white_adjust [-d display] -i image

White_adjust illustrates performs white point adjustment of a TripleBand JPEG
image to the following white points, displaying the result in an X window:

Illuminant			Position in CIE coordinates
---------			---------------------------

Full Intensity White		1.000, 1.000, 1.000 
Illuminant A			1.099, 1.000, 0.356 
Illuminant B			0.991, 1.000, 0.853 
Illuminant C			0.981, 1.000, 1.182 
Illuminant D55			0.957, 1.000, 0.921 
Illuminant D65			0.950, 1.000, 1.089 
Illuminant D75			0.949, 1.000, 1.225 

Once the TripleBand JPEG image is decoded, it is passed to ConvertToRGB to 
convert the image from YCbCr space to RGB space. For each illuminant above, 
the following elements are added to the photoflo:

ConvertFromRGB -> ConvertToRGB -> Constrain

The ConvertFromRGB element uses the RGBToCIEXYZ technique and also performs 
the white adjustment using the xieValWhiteAdjustCIELabShift white adjust 
technique. ConvertToRGB generates image data in the range [0.0, 1.0]; 
Constrain is used to convert the image data to the range of [0, 255].

scale_to_gray/

	scale_to_gray [-d display] -i image [-a angle]

Scale_to_gray accepts bitonal CCITT image data from a TIFF format file as 
input.  If the size of the image exceeds the dimensions of the display, or 
if a non-zero angle is specified by the -a argument, the levels attibute of 
the bitonal image is converted to 256 levels using Point, and a filter is 
passed over the image using Convolve, prior to sending the image to Geometry 
for image scaling and/or rotation. If the image is scaled and/or rotated, 
ConvertToIndex is used to generate colormap index data which can be sent to 
ExportDrawable for display. Otherwise, if the image is displayed directly 
after decoding by sending it to an ExportDrawablePlane element.

Contrast displaying a fax using scale_to_gray:

scale_to_gray -i ../../images/bitonal/ccitt_8.tif

with the faxview sample client:

faxview -i ../../images/bitonal/ccitt_8.tif

Faxview is far speedier (the image is big, and convolve is expensive), but 
the accuracy, if you look close, is far better using scale_to_gray.

showdiff/

	showdiff [-d display] -i image1 -b image2

Showdiff accepts two SingleBand JPEG images or two TripleBand JPEG images as
input. The images are imported and if TripleBand are converted from YCbCr to 
RGB using ConvertToRGB. Image1 is then subracted from image2 using an 
Arithmetic element. The original images, and their difference, are displayed 
into separate X windows by the client.

simple/

	simple [-d display] -i image [-s]

Simple is, well, perhaps too simple. It reads in a SingleBand JPEG image 
using ImportClientPhoto and sends it unprocessed to ExportDrawable. This 
client is a good template for more ambitious photoflos; the first thing to 
do might be to add backend processing as described in chapter 12 of the
book and illustrated by the sample given in /backend/backendtest.c and by
most other clients. 

sobel/

	sobel [-d display] -i image -v vert_kernel_file -h horiz_kernel_file

Sobel accepts a SingleBand or TripleBand JPEG image and applies back-to-back
Convolve elements to implement a Sobel edge enhancement. The first Convolve 
element uses the kernel specified by the -v argument; the second Convolve 
element uses the kernel which is specified by the -h argument.

threshold/

	threshold [-d display] [-t threshold] -i image

Threshold illustrates how Point can be used to perform a binary thresholding 
operation on a grayscale image. Intensity values in the grayscale image which
fall below the -t argument will be mapped to 0 (black), and those which fall 
above are mapped to 255 (white). 

	slice [-d display] [-l lower_threshold] [-u upper_threshold] -i image

Slice is similar to threshold. Intensity values below lower_threshold are 
mapped to 0, intensity values above upper_threshold are mapped to 255, and 
intensity values between are left as is.

tiff/

	tiffconv [-d display] -e [G31D | G32D | G42D | TIFF2 | TIFFPackBits] 
		-f file -o outfile

Tiffconv accepts a TIFF file containing G31D, G32D, G42D, TIFF2, or 
TIFFPackBits encoded bitonal image data from the file specified by the -f 
argument and creates a TIFF file specified by the -o argument. The generated 
image will be encoded as specified by the -e argument.

unsharp_mask/

	unsharp [-d display] -i image -k kernel_file -s scale

Unsharp_mask implements an unsharp masking operation on the image specified by 
the -i argument (the image must be JPEG, but can be SingleBand or TripleBand).
The image, after decode, is passed to Convolve, which applies the kernel 
specified by the -k argument. Each intensity value in the result is then 
multiplied by scale (specified by the -s argument), and then is subtracted 
from the original image. The result of the subtraction is then displayed in 
a window. The multiplication and subtraction operations are performed in 
series by Arithmetic elements.

xiegc/

	xiegc src1 src2

The source code for xiegc for the most part is identical to that of the X 
client xgc.  Hence its strange name.

Xiegc allows the user to experiment with the various operators supported by 
the following elements:

Logical

Arithmetic

Math

Compare

Most of the XIE code is implemented in xiestuff.c, which contains the 
functions which are described briefly below. Xiegc accepts two SingleBand 
JPEG images as input, and displays them in separate xiegc windows. A third 
window is used to display the results of the operation which is performed by 
the client when the user presses the "run" button. The operation performed 
is specified by various settings which are provided in the xiegc user 
interface. The following functions are implemented in xiestuff.c:

int
LoadSingleBandJPEGPhotomap(display, file, photomap)
Display		*display;
char		*file;
XiePhotomap	*photomap;

The above function reads a SingleBand JPEG image from the file specified by 
the argument file and stores it in a photomap resource allocated by the 
function and returned to the caller through the argument photomap. The image 
is scaled to the dimensions of the xiegc window used to display the image. 
The function is called once for src1 and src2 at the start of client execution. 
From that point image data is imported to photoflos directly from the photomap 
resources when needed.

int	
BuildRefreshPhotoflos( X, XIE )
XStuff *X;
XIEStuff *XIE;

The above function creates two stored photoflos, both:

ImportPhotomap -> ConvertToIndex -> ExportDrawable

One photoflo reads from the photomap containing the image data read from src1,
and displays it in the first window of xiegc, while the other photoflo reads 
from the photomap containing the image data read from src and displays it in 
the second xiegc window. These photoflos are executed by the client whenever 
expose events are received to refresh window contents. This is done by 
RefreshSources, below:

int
RefreshSources( X, XIE )
XStuff *X;
XIEStuff *XIE;
{
	XieExecutePhotoflo( X->dpy, XIE->refresh1, False );
	XieExecutePhotoflo( X->dpy, XIE->refresh2, False );
	return( 1 );
}

The following functions are called by the "Run" button callback; which 
function is called is based upon the test selected by the user using the 
buttons which are supplied by the user interface. Most of the tests support 
dyadic (two image) and monadic (one image and a constant) modes of operation, 
for example, the Arithmetic element can execute:

image1 operator image2

or

image1 operator constant

depending upon whether or not the dyadic or monadic button is selected. The 
routines below create and execute photoflos which are based upon which of the
above two modes are selected by the user at the time the test is executed. 

The results of the tests are displayed in the third xiegc window, as well as 
the histogram of the resulting image.

int
DoLogicalFlo()

int
DoArithmeticFlo()

int
DoMathFlo()

int
DoCompareFlo()

xlib/

This directory contains clients which are xlib only, or which are based upon a
hybrid approach in which XIE and the client cooperate in performing the image
processing tasks because XIE does not provide a Process element or elements 
which provide the necessary functionality. For example, say we wish to perform 
the following operations on a JPEG image:

Image decode -> scale -> proprietary magic -> low pass ->  export to window

Clearly, ImportClientPhoto, Geometry, Convolve, and ExportDrawable elements
are capable of satisfying the image decode, scale, low pass,  and export to 
window components of the desired operation. Sad to say, XIE does not have a
"proprietary magic" element. Therefore the following strategy can be adopted:

(XIE)
Image decode -> scale -> export to client

(Client)
Read image from XIE
Perform proprietary magic
Send image to XIE

(XIE)
Image decode -> low pass -> export to window

The client then might create and execute the following photoflos corresponding
to the above:

ImportClientPhoto -> Geometry -> ExportClientPhoto

ImportClientPhoto -> Convolve -> ExportDrawable

The client usages are:

	hybrid [-display display] [other x args]

Hybrid is an Xt/Xaw application which shows how to combine XIElib programming 
with Xt/Widget applications. It implements two image processing controls, 
median filter, and match histogram. Because XIE does not have a median filter 
element, the client must export the image back to the client for median filter 
processing (the code which implements the median filter is in median.c). 
Histogram matching is implemented entirely in XIE using the MatchHistogram 
element. The client also illustrates how to cache images in photomap resources. 
Image refresh (the Revert To Original menu item) is implemented by redisplaying
a copy of the original image which was stored in a photomap resource once the 
image was selected by the user. A second photomap is used a source for image 
data by the photoflos which implement the median filter and histogram matching 
operations. The photoflos which implement these controls write the resulting 
image back to this photomap using ExportPhotomap in addition to displaying 
the result in a client window.  

Try displaying an image and then applying a median filter repeatedly (say,
10 or 12 times). Notice the posterization effects that occur as a result.

        put_scaled [-d display] [-s scale] -i image

Put_scaled implements a routine called XiePutScaledImage(). XiePutScaledImage()
is similar to XPutImage in that it is designed to display an XImage in a 
drawable. 

The client accepts a PPM (color Portable Pixmap) or PGM (grayscale Portable 
graymap) image as input. An XImage is created from this data and is sent to 
the routine XPutScaledImage along with a scaling factor which was specified 
by the -s argument. If the scaling factor is 1.0, the image is displayed using 
XPutImage. Doing this will result in an image which is displayed with false 
colors unless the window's colormap contains colors which are suitable for 
the image that is being displayed and the image indexes these colors correctly. 
If the scale factor is not equal to 1.0 (e.g. 0.8 or 1.1 are good values to 
start with) then a photoflo is created which accepts the image data as 
UncompressedSingle if the image was grayscale or UncompressedTriple if the 
image was TripleBand, scales the image using a Geometry element, and displays 
the image in the drawable specified using ExportDrawable. Improvements to 
XiePutScaledImage would be to use XIE even if the scaling factor is 1.0, and 
to replace ConvertToIndex and ExportDrawable with a backend which is more 
appropriate to the image and the visual/colormap of the drawable using the 
techniques illustrated in chapter 19 of the book and in the client 
backend/backendtest.c.

        median [-s] [-m width] [-d display] [-r repeat] -i image

Median accepts a PGM grayscale image as input. If -s is specified, the image 
is displayed in a window using colors allocated from the server's default 
colormap, otherwise the client creates its own colormap from which a linear 
ramp of grayscale colors. If -m is specified, the client adds white and black 
shot noise to the image, and will apply a median filter of the specified width 
to the noisy image once as many times as specified by the -r argument. The 
result of the median filtering is displayed in a separate X window.