This is the README file for version 2.3 of the photo widget,
which is designed for use with Tk version 3.3.


DESCRIPTION
-----------

This distribution contains the source for version 2.3 of the "photo"
Tk widget.  A photo widget displays an image, in color if you have a
color workstation, otherwise in monochrome.  The photo widget will
dither the image if necessary, using the Floyd-Steinberg dithering
algorithm.  It should be able to produce some reasonable
representation of the image on any X workstation, including 1-bit
monochrome workstations.  The widget accepts image data in memory in a
fairly general 24-bit/pixel format.  If you have an image in a file,
you need a C procedure to read it into memory for the photo widget to
display.  The distribution includes a procedure to do this for raw PPM
files.

This distribution also includes patches to tk.h, tkInt.h, tkWm.c and
tkWindow.c to maintain a priority-ordered list of windows whose
colormaps the application wants installed, and supply this list to the
window manager using the WM_COLORMAP_WINDOWS property on the
application's top-level windows.  This is the preferred way to get
colormaps installed, according to the ICCCM.  These patches also
implement a "colorfocus" Tcl command which allows the user to control
the priority ordering.  These patches are not part of the photo
widget, but are necessary for the correct appearance of a photo
widget's window when it is not using the default colormap.

Unfortunately there appears to be a bug in olwm and olvwm which causes
them to crash under certain conditions when using the colorfocus stuff
with more than one top-level window.  I am working on a work-around
for this.  If it appears that using the colorfocus facility has
crashed your window manager, I would appreciate knowing the details.

This code has been compiled and tested on Sun-4's running SunOS 4.1.3
and on a Decstation 5000 running Ultrix 4.2 (including running the
widget on one architecture with the X server on the other).

If you find any bugs, or have any comments, suggestions, questions,
etc., contact me via email; my address is paulus@cs.anu.edu.au.  If
you modify the source, to improve functionality or to port it to
another platform, I would appreciate receiving the changes;
context-style diffs are best.


NEW FEATURES AND CHANGES
------------------------

Version 2.3 of the photo widget differs from the version 2.0 in
the following ways:

* A new configuration option has been added to control whether the
photo widget will use a private colormap:

	-owncmap arg

If `arg' is "always", the photo widget will have its own colormap.  If
`arg' is "never", the photo widget is forced to use the default
colormap.  If `arg' is "ifneeded", the widget will use a private
colormap only if it can't allocate all the colors it needs in the
default colormap.

* There is now a photo item for canvases, thus you can put an image on
a canvas and draw on top of it.  For a demonstration, source the file
photoitem_test.  This code is still somewhat experimental.  A photo
item has to use the same visual and colormap as the canvas it's on,
which at present can only be the default visual and colormap.

A photo item is created on a canvas by a command like:

	.c create photo x1 y1 x2 y2

where .c is the canvas, (x1,y1) are the coordinates of the top-left
corner of the photo item, and (x2,y2) are the coordinates of the
bottom-right corner.  This command returns the item number of the
photo item; the name to give to FindPhoto is <canvas>-<item number>,
e.g. if the above command returned 23, the name is ".c-23".

If the image data in the photo is changed, you'll have to execute a
command like

	.c move tag 0 0

to get the image redrawn.

The photo item has several configuration options that can be set with
the itemconf canvas option.  They are -blank, -ditherlevel,
-drawinterval, -gamma, -imagesize, -palette, -xshift and -yshift.  All
except the last two are the same as for the photo widget.  The last
two specify the image coordinates to appear at the top-left corner of
the item.

The photo item cannot generate Postscript at present.

* There is now a C procedure, PhotoPutZoomedBlock, which is like
PhotoPutBlock except that the image can be enlarged (by pixel
replication) or reduced (by pixel selection) as it is displayed.

* The readppm now takes options for enlarging and reducing the image:
-zoom x y and -decimate x y.  For instance:

	readppm -zoom 10 10 -decim 10 10 .p.f.p teapot.ppm

after you've sourced photo_test.

* For real wizards only: there is now a PhotoPutXImage which accepts
an XImage struct to be displayed.  Users of this procedure are
responsible for translating colors into pixel values.

* There is now a PhotoGetInfo procedure which returns the visual
information and colormap for a photo widget.
		
* It frees large blocks of memory used for temporary image storage
promptly.


INSTALLATION
------------

The source for the photo widget is in tkPhoto.h and tkPhoto.c, with
documentation in doc/photo.n and doc/FindPhoto.n.  Files readppm.c,
writeppm.c and photocopy.c contain C code implementing some useful
Tcl commands for dealing with photo widgets (reading PPM image files,
copying the contents of one photo widget to another, and writing the
contents of a photo widget to a PPM format file).  File photoInit.c
contains initialization code for the photo widget and associated
commands, to be called from tkAppInit.c.

To build a wish with the photo widget included, plus the readppm,
writeppm and photocopy commands, all that is required is (a) to
include the necessary object files in libtk.a and (b) to call
Photo_Init from tkAppInit.c.  The file photo.patch contains patches to
make these changes to Makefile.in and tkAppInit.c.  After applying
these patches, you will need to run configure again to update the
Makefile.

You should also install the patches in the file colorfocus.patch.
This modifies tk.h, tkInt.h, tkWindow.c and tkWm.c to maintain the
WM_COLORMAP_WINDOWS property and add the "colorfocus" command.
Documentation for the colorfocus command is in doc/colorfocus.n.
Strictly speaking, this is not absolutely essential if you plan never
to use a workstation with a writable colormap, but it is recommended.

The installation procedure is as follows:

	1. Get photo-2.3.tar.Z and unpack it in your tk3.3 directory.
	   (e.g. zcat photo-2.0.tar.Z | tar xvf -)

	2. patch <photo.patch

	3. patch <colorfocus.patch

	4. ./configure

	5. make

This will recompile tk*.c (because of the changes to tk.h and
tkInt.h), and make libtk.a and wish.  Note that if you are using
shared libraries, you may have switches like `-L/usr/local/tk3.3/lib -L.'
in the command line for linking wish.  If this is the case, and you
have an old version of libtk.so in /usr/local/tk3.3/lib, you will need
to either delete the old version or reverse the order of the -L
switches to pick up the new version of the library.

You can then test the photo widget with the command:

	./wish -f photo_test

This should display the image in teapot.ppm, which is a ray-traced
image of a teapot.  Move the cursor into the image and press 'q' to
quit, '1' .. '9' to change the gamma value ('4' gives a gamma of 1),
'a', 'b', 'f', 'n' or 'm' to change the palette, 'r' to reread the
image, 'd' to dither the image, or 'c' to copy it into a new photo
widget.  You will have to press 'd' to get the image displayed
correctly after changing the palette or gamma value; after switching
between a color palette ('a', 'b', or 'f') and a monochrome palette
('m' or 'n'), you will have to re-read the image ('r').  See
photo_test for details.

To try out the photo item, use the command

	./wish -f photoitem_test

This should display the teapot image on a canvas with a red diagonal
line across it.  If you click with the left mouse button, a small
green square should appear centered on the point where you clicked.

To include the photo widget in your program, you need to add a call to
Tcl_CreateCommand in your main program to establish the `photo' Tcl
command.  Linking with libtk.a should then include tkPhoto.o, assuming
you have followed the steps above.  You will probably need to write a
C language procedure to supply image data to the widget; look at
readppm.c to see how this is done.


COLORMAP CONSIDERATIONS
-----------------------

If the photo widget is using a visual other than the default, or if
its palette requires more colors than are available in the default
colormap, then it will use a private colormap.  The patches to
tkWindow.c and tkWm.c ensure that the window then gets put in the
colormap-windows list (i.e. the WM_COLORMAP_WINDOWS property).  With
some window managers and some workstations (e.g. those with several
colormaps), this is sufficient to ensure that the window's colormap
will get installed.  For instance, olwm (and olvwm) have a `colormap
focus follows mouse' mode in which olwm installs the colormap of the
window in the list which the cursor was most recently in.

In other cases, it will be necessary to bring the window to the front
of the list to ensure that its colormap gets installed.  This can be
accomplished using the "colorfocus" Tcl command.  When to do this is a
question of user interface policy; my suggestion is to include class
bindings such as

	bind Photo <Enter> {colorfocus %W}
	bind Toplevel <Enter> {colorfocus %W}

This will have the effect of installing a photo's colormap whenever
the pointer enters it; its colormap will stay installed until the user
moves the pointer into another photo widget, or out of the top-level
window and back into any of the top-level windows of the application.

I have chosen to implement a global colormap focus policy by
maintaining a single priority-ordered list of windows for each screen
which an application is using.  This same list is placed in the
WM_COLORMAP_WINDOWS property for all top-level windows of the
application on that screen.  Thus, the window manager should install
the colormap for the window with the Tk colormap focus whenever it
assigns its colormap focus to any of the application's top-level
windows.

The Tk colormap focus was implemented this way partly for conformity
with the way that the Tk input focus operates, but the situation is
confused somewhat by the fact that it is possible to have more than
one colormap installed, and thus more than one colormap focus, on some
workstations.  Also, it is not completely clear from the ICCCM whether
it is legal for a top-level window to have another top-level window's
descendent in its WM_COLORMAP_WINDOWS property (some of the discussion
seems to presuppose that this won't ever happen, but it's not
prohibited anywhere).

One alternative would be to have a separate local Tk colormap focus
for each top-level window.  I would be interested to hear people's
views on the pros and cons of the global colormap focus policy I have
implemented versus other alternatives.


IMAGE FORMAT
------------

The photo widget accepts most formats which have one byte (unsigned char)
for red, green and blue for each pixel.  The image data supplied to the
widget (from C code) are described by the following header:

	typedef struct image_block {
	    unsigned char *ptr;		/* points to image data */
	    int		width;		/* horiz # pixels in block */
	    int		height;		/* vert # pixels in block */
	    int		pitch;		/* # bytes stored per line */
	    int		pixel_size;	/* # bytes per pixel */
	    int		comp_off[3];	/* address offset to R,G,B components */
	} PhotoImage;

The photo widget uses this as follows: the components of the first pixel
of the first line are at ptr[comp_off[0]], ptr[comp_off[1]], and
ptr[comp_off[2]].  The next pixel on the same line is at ptr + pixel_size,
and the first pixel on the next line is at ptr + pitch.

Having the pitch, pixel_size and comp_off[] fields lets the widget handle
all formats in which the component bytes are regularly spaced, including:

* the 'standard' RGBRGB... format stored by scan-lines, with an arbitrary
  amount of padding at the end of each scan-line (e.g. PPM format).

* formats where the components are in a different order (e.g. BGR)

* formats where there are extra components (e.g. an alpha channel)

* line-interleaved formats (where you get a red scan-line, then a green
  scan-line, then a blue scan-line, or some other order).

* formats where the components are stored by plane (e.g. a complete red
  image, then a green image, then a blue image).

* formats where the pixels are stored by columns rather than scan-lines.

* formats where the pixels in a row are stored in reverse order, or where
  the scan-lines are stored in reverse order (you need to make ptr point
  to the end of the row or image respectively).

It won't cope with an interlaced format, where you get an array of even
lines followed by an array of odd lines.


Paul Mackerras
Dept. of Computer Science
The Australian National University.
paulus@cs.anu.edu.au
