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 -, 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 {colorfocus %W} bind Toplevel {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