/*
 * Copyright (c) 1996 Picture Elements, Inc.
 *    Stephen Williams
 *
 *    This source code is free software; you can redistribute it
 *    and/or modify it in source code form under the terms of the GNU
 *    General Public License as published by the Free Software
 *    Foundation; either version 2 of the License, or (at your option)
 *    any later version. In order to redistribute the software in
 *    binary form, you will need a Picture Elements Binary Software
 *    License.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 *
 *    You should also have recieved a copy of the Picture Elements
 *    Binary Software License offer along with the source. This offer
 *    allows you to obtain the right to redistribute the software in
 *    binary (compiled) form. If you have not received it, contact
 *    Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
 */
#ident "$Id: README,v 1.29 1997/07/07 22:50:41 steve Exp $"
/*
 * $Log: README,v $
 * Revision 1.29  1997/07/07 22:50:41  steve
 *  Add the 1d median color quantization
 *
 * Revision 1.28  1997/07/07 03:29:27  steve
 *  Add the red332 color map reduction.
 *
 * Revision 1.27  1997/07/03 00:27:26  steve
 *  Add ability to write JFIF files.
 *
 * Revision 1.26  1997/07/02 22:30:07  steve
 *  Introduce JPEG support.
 *
 * Revision 1.25  1997/06/04 08:30:42  steve
 *  Add support for pbm.
 *
 * Revision 1.24  1997/06/01 21:10:47  steve
 *  Start Windows NT support.
 *
 * Revision 1.23  1997/06/01 06:45:13  steve
 *  Make file formats optional.
 *
 * Revision 1.22  1997/03/17 21:37:07  steve
 *  Put matrix access in seperate function.
 *
 * Revision 1.21  1997/02/14 20:54:36  steve
 *  Add the rgbmatch function.
 *
 * Revision 1.20  1997/02/01 07:27:25  steve
 *  Add pixel replicate function.
 *
 * Revision 1.19  1997/02/01 02:11:43  steve
 *  Add planing to cut planes out of images.
 *
 * Revision 1.18  1997/01/31 18:31:11  steve
 *  PNG support.
 *
 * Revision 1.17  1997/01/31 02:03:48  steve
 *  Add the square-error comparison.
 *
 * Revision 1.16  1997/01/30 23:32:17  steve
 *  Add the ik_destroy command
 *
 * Revision 1.15  1997/01/30 00:15:27  steve
 *  Add the croop function.
 *
 * Revision 1.14  1997/01/29 02:06:09  steve
 *  Add the threshold algorithm.
 *
 * Revision 1.13  1997/01/28 19:55:37  steve
 *  Add support for diffusion filters.
 *
 * Revision 1.12  1997/01/28 06:17:57  steve
 *  Document the compression flags.
 *
 * Revision 1.11  1997/01/28 04:43:59  steve
 *  Add the round function.
 *
 * Revision 1.10  1997/01/28 04:06:19  steve
 *  Add the compare operation.
 *
 * Revision 1.9  1997/01/28 01:25:16  steve
 *  Describe diffusion.
 *
 * Revision 1.8  1997/01/22 02:24:32  steve
 *  Add the ik_image command
 *
 * Revision 1.7  1997/01/21 07:10:02  steve
 *  Separate the Tk support from the Tcl support,
 *  and add the ik_create command so that tclsh
 *  scripts can use ikit.
 *
 * Revision 1.6  1997/01/21 03:30:21  steve
 *  Add the ik_store command, and the ability for
 *  TIFF files to be stored. Also, add a preferences
 *  menu item and functions to populate it.
 *
 * Revision 1.5  1997/01/10 00:31:43  steve
 *  Add the null ik_image file type, and support
 *  shared-object type packages.
 *
 * Revision 1.4  1997/01/09 03:16:13  steve
 *  Allow for huge colormaps.
 *
 * Revision 1.3  1997/01/04 02:17:10  steve
 *  Add the convolute transformation
 */

IKIT IMAGING EXTENSION

This package is intended to add image manipulation capabilities to
Tcl/Tk. The new tools are intended for more precise image processing
and study then the typical image tools included in the Photo image
extensions. Whereas the photo image type is a good citizen and tries
to cooperate with the other widget wrt the color map, this kit has a
``precise'' image type that will steal as much of the hardware as
needed to get colors for the image.

Because the processing is intended to be precise, the following
documentation will contain detailed descriptions of the functions
applied to images, and how images are translated to
display. Documentation that says ``it smooths the image'' is not at
all helpful.

REQUIREMENTS

The ikit extensions require tcl 7.5 or later, and Tk 4.1 or later. The
C code is compiled as a loadable module, so tcl must support dynamic
loading, which it does on most platforms.

Optional packages are:

- libtiff is needed for support of TIFF image files.

- libpng is needed for support of PNG image files.

- zlib is required for PNG support, and if so configured, libtiff can
use this library for compression of grey images.

- jpeg-6 or later is needed for support of JPEG.

Although none of these file format tools are required, ikit is not
particularly useful if no image file formats are supported -- unless
add-on packages are supplied that get images in and out of the
program. In any case, ikit has some basic support for PBM file
formats that requires no external libraries.

NOTE: See README.NT for information about Windows-NT support.

PROGRAMMING ik_image IMAGES

The IKit extension is broken into two parts. The basic extension has
image processing functions, but does not do any Tk display, and the
extended extension has Tk interfaces. The parts are called IKIT and
IKITX when it is necessary to distinguish between the two.

The IKIT extension to some degree takes advantage of existing image
support in Tcl. Every reasonable effort has been made to build upon
the existing interface, rather then arbitrarily create new ones. One
of the existing interfaces is the Tcl ``image'' command.

IKIT needs to perform detailed pixel manipulation so a new image type
is necessary, but the Tcl programmer can use ``image create'' to
create an ``ik_image'' (IKITX only) just like one would create a photo
or bitmap image. Furthermore, the ik_image can be used wherever other
images can be used.

Create an ik_image like so:

	set name [image create ik_image tiff foo.tiff]
	image create ximage ik_image tiff foo.tiff

either form will work, just like other image types. All the other
image commands work just like with other images.

The ik_image stores the images as interleaved planes of intensity
samples, i.e. one plane of black or three planes of RGB, for ease of
per-pixel processing. The idea is to provide support for image
computations in this form, so palate color form, though compact, is
not really appropriate. However, displays into the image generally use
palate color so copies will be periodically transformed for cases
where this is necessary.

There are some limitations. Currently, each plane is assumed to be
16bits. Grey images are a single plane of 16bit samples, and color
images are 3 planes, red, green and blue. Most frame buffers are
even more limited so increasing the depth would apparently increase
memory use with very little gain in visual quality. However, precision
may be lost if the hardware really is capable of 16bits per plane.

SUMMARY

These are the commands and features added by the IKIT and IKITX
extensions. To get the IKIT features, load (in tclsh or wish) the
libikit.so object file from the ikit library. The IKITX functions are
in the libikitx.so object file.

	ikit
		ik_create
		ik_destroy
		ik_image
		ik_palette
		ik_store
	ikitx
		ik_pane
		ik_viewport
		ik_set_photo
		The ik_image image type (image create ik_image)

	Image processing sources (for ik_create and image create ik_image)
		JPEG (JFIF)
		null
		pbm (including PBM, PGM, and raw forms)
		png
		tiff

		compare
		convolute
		crop
		diffuse
		laplace
		red1dmed
		red332
		replicate
		rgbmatch
		round
		square-error
		threshold

MATRICES

There are a few cases where a parameter is a matrix, instead of a
single value. These routines takt matrix values as the name of an
array variable, filled with the dimensions and contents of the
matrix. The dimensions of the matrix m are in the elements m(x) and
m(y). The values are then stored in the elements m(a,b) where a is
an unsigned integer [0 x) and b is an unsigned integer [0 y).

TCL EXTENSION DETAILS

- ik_create (IKIT)

This command supports creating IKit images that can be passed around
just like other ik_image images, except they cannot be displayed in an
X window. Use ``image create ik_image'' for that. ik_create takes any
of the image types supported and described below in IMAGE PROCESSING.

- ik_destroy (IKIT)

This command support destroying images created with the ik_create
command. The only parameter is names of images to be destroyed. Many
images can be destroyed in one command.

- ik_image (IKIT)

This gets a few interesting parameters about the named image, and
returns them as integer strings.

	ik_image <image> width
	ik_image <image> height
	ik_image <image> planes


- ik_palette (IKIT)

Get as a list the palette of some specified image. Each color in the
image is a sublist of three intensities: red, green and blue.

	ik_palette <ik_image> palette

This returns a list of colors, or an error if the image is not an
ik_image object. If only the color at a specific pixel is required,
the form:

	ik_palette <ik_image> pixel <x> <y>

returns a list of three numbers, the intensities as the specified
location.


- ik_pane (IKITX)

This new widget type simply provides a base for displaying images. It
can display any widget type that ``image create'' can generate, but
can only display a single image. This is much more simplistic then the
canvas widget, but that is intentional.

ikit_pane can display any Tk image, but it is intended for the
most precise image type, the ik_image type.


- ik_store (IKIT)

This command stores the image using an image format as described
below.

	ik_store <ik_image> <type> <options...>

The image type is any type that supports writing, and the options are
specific to the format. Supported types are:

	null ...
		Write the file to nowhere at all. All options are
		ignored. This is kinda like writing to /dev/null.

	jpeg <file>
		Write the file in JPEG compressed form. The output
		file becomes a JFIF data stream which can be
		interpreted by most imaging tools.

		(NOTE: The ability to set JPEG parameters is
		forthcomming, but not supported yet.)

	png <file>
		Write a PNG formatted file. If the image is RGB, then
		write a 16bit RGB file, otherwise write a gray
		file. The PNG format supports 16bit depths directly,
		so there is no need to reduce the image as with
		TIFF. Also, compression is always used.

		This is far less complicated then TIFF.

	tiff <file>
		Write to a TIFF formatted file.

		If the image has one plane and palette has only two
		colors, and they are 0xffff and 0, the image will be
		written as TIFF binary with binary compression. The
		reproduction is exact.

		The -comp-bin flag flag can be used to select other
		compression schemes. The accepted values are none,
		ccitt-fax3 (good) and ccitt-fax4 (best).

		If the image is gray, the image is written to the tiff
		file as 8bit gray. Since the TIFF format specifies
		8bit, and ikit uses 16bit internally, the low order 8
		bits for each pixel are truncated out when copied into
		the TIFF file. The image is compressed using Deflate
		compression.

		For gray images, the default compression is none, but
		the -comp-gray flag can change it to one of the values
		packbits (yuck), lzw (good) or deflate (best). Only
		packbits is guaranteed to be supported, lzw support
		requires a Unisys license so should be avoided and
		deflate is experimental.

	pbm [-raw|-ascii] <file>
		Write in the appropriate PBM file format, ppm for
		color (3 planes) pgm for gray and pbm for binary. The
		-raw or -ascii flags select either ASCII output (for
		transmitting through 7bit data paths) or raw output
		(for speed and space.)

		NOTE: Currently only -raw binary are supported.

- ik_viewport (IKITX)

This widget is a frame that holds a single child widget that may be
bigger then itself. It allows a simple interface to scrollbars for
moving a viewport over any single widget displayed in the
viewport. This is especially handy for displaying an ikit_pane widget,
but may display anything.

	configure - Reconfigure the widget. Any of the widget
		    parameters can be passed.

	place - Manage the named child widget. The only parameter is
		the path to a child widget, which is then mapped in
		the viewport.

	xview
	yview - These methods move the placed widget under the
		viewport to make portions visible. These methods are
		intended to be used by scrollbar widgets. The
		parameters are:

			scroll <x> units
			scroll <x> pages
			moveto <x>

		See the scrollbar man page. The viewport widget
		supports any signed value for the scroll, not just 1
		and -1.

	xyview - This method supports 2-dimensional scrolling by
		 allowing the programmer to specify the scroll in x
		 and y direction together. This makes for a smoother
		 2D motion.

			scroll <x> <y>
			    Move the pane the specified number of
			    pixels in x and y dimension.

			set <x> <y>
			    Set the upper left corner to be here on
			    the viewport widget.

			scroll-start <x> <y>
			scroll-rel <x> <y>
			    Save the start coordinates, then scroll
			    the placed widget rel-start pixels in both
			    dimensions. This is specifically used for
			    drag type scrolling with the mouse.

When the child widget is placed, the following binding is added to it:

     bind .child "<ButtonPress-2>" "$parent xyview scroll-start %X %Y\n"
     bind .child "<Button2-Motion>" "$parent xyview scroll-rel %X %Y\n"

Note that these bindings are attached to the child, because it covers
the viewport widget.

The supported configure options are:

	-width	- Maximim width of the viewport
	-height	- Maximum height of the viewport

	-xbar	- X scrollbar widget command. The viewport will call
		  set for the named command in order to show what of
		  the child widget is currently displayed.

	-ybar	- Same as xbar, but for the Y direction.

the viewport widget will request smaller if the placed widget is
smaller the the configured size. It will not request bigger, however,
and the user will have to scroll. If the dimensions are set to 0,
however, the viewport will try to be as big as the placed child.

- the ``ik_image'' image type. (IKITX)

This image type is intended for precise image display in the ikit_pane
widget. It stores images with minimum loss of pixel information. When
it is displayed in a window, it will do all it can to get every color
represented, including changing the color map of the destination
window. (It will try to use the existing color map first.) This image
type is intended to be precise. If you want polite, use the photo
image type.

      NOTE: The photo image type will dither, if necessary, to fit in
      the existing color map. This can cause very slow display of
      large images. The ik_image knows up front what the colors are,
      and allocates them as exactly as the hardware allows. Thus, no
      image munging is needed and the ik_image will display difficult
      images faster.

This image type can display in canvases, etc., but because of its
nasty behavior wrt color maps, it works best displayed in an ikit_pane
widget.


IMAGE PROCESSING (IKIT,IKITX)

Image processing operations that generate an ik_image use the
``image create'' paradigm to take a source data set and generate an
image result. For example:

      image create ik_image source -tiff foo.tif
      image create ik_image result -laplace source -gain 10

reads the file foo.tif into the source image, then places into the
result image the result of the laplacian operator applied to every
pixel in the source image. The final image can be displayed like any
other ik_image.

The formats that can be used to create ik_image images are listed
below. When passed to the image create command, include a '-' in front
of the following word, turning it into an option.

        IMAGE FILE SOURCES

	null
		Read a null image. That is, an image with 0 dimensions
		and no data. You never know, this might be useful.

	jpeg <file>
		Load a JFIF formatted image. This uses the IJG library
		to interpret the image, so any limitations that apply
		to the IJG source apply here. The image is expanded to
		16 bits per intensity, and translated (by the IJG
		software) to RGB form if the image is color.

	pbm <file>
		Read the PBM formatted file and return an
		ik_image. The reader automatically detects the kind of
		image, binary or gray, ascii or raw, and translates it
		to the internal form.

		PBM (binary) files are translated from the PBM
		1-is-black to the intermal 1-is-white form. Although
		ikit keeps the image in binary form in memory, it
		behaves as if black is 0 and white is 0xffff.

		PGM (gray) files contain gray intensities, with a
		sertain maximum value identified in the file
		header. For example, an 8bit grey PGM file has a
		maxgray value of 255. ikit scales the pixel value to a
		16bit value with the formula:

			(pixel * 0x10000) / (maxgray + 1)

		which gets the desired results. NOTE that PGM allows
		for *any* maxgray value, although 3, 15 and 255 are by
		far the most common.

	png <file>
		Read the PNG formatted file and return an
		ik_image. The source may be 16bit gray or RGB color,
		and is loaded directly into the image space.

	tiff <file>
		Read the tiff formatted file and return an
		ik_image. The source file may contain 8 bit grey or
		8bit palette color images.

		1bit grey (i.e. binary) images are translated to 16bit
		grey with 0xffff for white dots and 0x0000 for black
		dots. The Photometric is correctly interpreted in this
		translation.

		8bit grey images are expanded to 16bit grey by
		applying the following formula to the intensity for
		each pixel:

			I = (i * 256) + i

		This for example converts the grey pixel value 0x5e to
		be read as 0x5e5e. 4bit grey images are handled
		similarly.

		Palette color images use the colors in the palette
		directly, since the color values are already 16bit, by
		the TIFF standard.


	IMAGE FILE OPERATIONS

	compare <image1> <image2>
		Calcuate a comparison image that is the absolute
		difference between two images. Each intensity in
		the result is the difference between intensities in
		the source images as the same point and plane. This
		function can be applied to any two images as long as
		their geometries match exactly.

	convolute <image> [-gain <n>[/<n>]] [-bias <n>] [-matrix <name>]
		Create an image from the convolution of the input
		image. Each plane is transformed independently.

		Each pixel of the output image is created from the
		weighted sum of surrounding pixels of the source
		image. After adding all the pixel values, the result
		is multiplied by the gain, then added to the bias.

		The weight matrix is understodd as described above in
		the section ``MATRICES.'' For example, to calculate
		the simple average of the pixel neighborhood, try
		this:

			set m(x) 3
			set m(y) 3
			set m(0,0) 1; set m(1,0) 1; set m(2,0) 1
			set m(0,1) 1; set m(1,1) 1; set m(2,1) 1
			set m(0,2) 1; set m(1,2) 1; set m(2,2) 1
			image create ik_image  -convolute source \
				-matrix m -gain 1/9

		Note in this example the gain is set to 1/9 so that
		the overall image doesn't get brighter.

		All the arithmetic for this function is done with
		32bit signed integers, then clipped to fit back in the
		16bit unsigned integer where the value came from. The
		generated image is smaller then the original by the
		size of the weight matrix for that dimension, in order
		to truncate data without sufficient context.

	crop <image> [-cut <x> <y> <wid> <hei>] [-plane <p>]
		Generate a new image with pieces of the original. If
		no options at all are given, this reduces to a simple
		copy.

		The -cut option causes the new image to be smaller
		then the original. The parameters to the cut form the
		rectangle of the region to be copied out of the original.

		The -plane option causes the new image to include only
		the specified plane. For RGB images, 0 is red, 1 is
		green and 2 is blue. The output image has only a
		single plane, copied from the original image.

	diffuse <image>
		Convert a gray image to binary using error
		diffusion. The -filter option tells the diffuser how
		to disperse the error by giving a matrix of
		weights. The predefined filters are (with the
		appropriate normalizing constant):

		floyd-steinberg
			    * 7
			  3 5 1

		jjn (Jarvis, Judice and Ninke)
			    * 7 5
			3 5 7 5 3
			1 3 5 3 1

		stucki (Like jjn, but with powers of 2 for weights)
			    * 8 4
			2 4 8 4 2
			1 2 4 2 1

		All the arithmetic is done with signed long integers,
		and converted to unsigned 16bit integers only when the
		pixel is finished and stored in the resulting image.

		If the name passed to -filter is not one of the
		standard names, it is a custom filter and the diffuse
		looks in the Tcl array for the values needed:

			A(x), A(y)  -- dimensions of matrix
			A(div)	    -- divisor to normalize (i.e. 16)
			A(%x,%y)    -- The weights of the matrix.

		The width must be odd, so that the hot spot is placed
		in the middle top row. The height can be anything.

	laplace <image> [-out-gain <n>]
		Apply to every pixel the laplacian operator, and
		multiply the result by the gain (default 1). The
		source image must be grey, and the output image is RGB
		color.

		The laplacian of a two-dimensional grey image treats
		the image as a cartesian scaler field -- the intensity
		is the scaler value of the function at the x,y
		location in the image -- and is calculated as a
		descrete approximation of the formula:

		       /d^2    d^2 \
		      ( ---- + ---- ) . f
		       \dx^2   dy^2/

		in words, the second directional derivitive in the x
		direction plus the second directional derivitive in
		the y direction. The values are numerically calculated
		using 5 points that form a "+" centered around the point
		being worked on.

		laplace(f at (x y)) is calculated as:

			  (f(x+1,y) - f(x,y)) - (f(x,y) - f(x-1,y))
			+ (f(x,y+1) - f(x,y)) - (f(x,y) - f(x,y-1))

		The output of this calculation is multiplied by the
		output gain as a performance convenience, because all
		the arithmetic is done with truncating integers.

		The result of the laplacian can be positive or
		negative, so is expressed with false color. Green
		points are positive, red points are negative and black
		points zero. The signed gain is applied after the
		calculation, so the colors can be reversed with
		-out-gain -1.

		Because the edges do not have useful values, the
		resulting image is 2 pixels smaller in both
		dimensions.

	red1dmed <image> [-counts <list>]
		This function reduces the image color map by
		quantizing each of the colors as independent
		planes. Up to 4 planes are supported. The number of
		colors in each plane are 8, 8, 4 and 8. (The 4th plane
		is rarely used.

		The counts for each plane can be specified with the
		counts parameter. The list is a list of unsigned
		integers (C syntax) that must have at least as many
		numbers as there are planes.

		This technique has poor results for more then 1 plane
		because the resulting chroma of the pixels are shifted
		due to the independent quantization. These results
		clearly show that colors must be quantized together.

	red332 <image>
		This function reduces an image to 256 colors by
		truncating the red to 3 bits, the green to 3 bits and
		the blue to 2 bits. The bits are repeated to fill 16
		bits of the internal representation.

		Note that in general this is not a very effective way
		to reduce the color palette of an image. However,
		people tend to think of it as a way to reduce colors
		so this function teaches you why you don't want to do
		it this way.

	replicate <image> [-xrep <n>] [-yrep <n>]
		Create a new image from the specified original with
		pixels duplicated on the x and y axis by the amount
		specified. This is a simple replication scale, and the
		duplication amounts must be unsigned integers. Each
		dimension can be replicated independently.

	rgbmatch <image> [-proj|-match] [-red <n>] [-green <n>] [-blue <n>]
		Compare the pixels in an RGB color image with the
		specified color (normalized) and generate a gray
		comparison result.

		The -proj is the projection of the image color onto
		the reference color.

		The -match will normalize the projection so that the
		result is really cos(A) where A is the angle between
		the colors in the RGB coordinate space. This give a
		bright result where the colors are similar,
		independent of the original intensity.

	round <image>
		Round the image from 16bits per intensity to
		8bits. This converts a 16bit number to the nearest
		16bit number where the higher 8bits match the lower
		8bits. For example, 0x0081 rounds to 0x0101, and 0x80
		rounds to 0x0000.

		This rounding policy matches the expanding policy that
		the various readers use to convert 8bit data to the
		16bit data of ikit, and tend also corresponds to
		typical X application behavior.

	square-error <image1> <image2>
		This is similar to compare, in that it calculates the
		difference between two images. In the case of
		compare, the intensity is absolute value of the
		difference. The square error makes the difference into
		a positive number, however, by squaring the result.

		The range for this function is much greater (32bits)
		so only the top 16 of the 32bit result is used.

	threshold <image> [-thresh <value>]
		Threshold the source image and generate a binary
		result. The algorithm is a simple global threshold
		with a default value of 32767 (right in the
		middle). Any unsigned integer value is acceptable as
		long as it fits in 16 bits.

OTHER IMAGE FORMATS (IKITX)

The ik_image can be copied into a photo image (created seperately with
the ``image create photo'' command) with the following
command:

	ik_set_photo <photo> <ik_image>

The Tk photo image has only 8 bits per plane, whereas the ik_image has
16 bits per plane, so some loss of information is probable. The
transformation deals with the difference by dividing each pixel value
from the ik_image by 256.

THE C PROGRAMMING INTERFACE

The Ik.h header file describes the C interface to the package. There
are functions for adding image file drivers, and for manipulating the
images in memory.

Ik_Image images are stored internally as pixels that have some number
of planes. Each plane is an unsigned short integer.
