[PYTHON IMAGE-SIG] Problems (and solutions) for Tk 4.2 on Windows

Fredrik Lundh fredrik_lundh@ivab.se
Wed, 6 Nov 1996 12:35:24 +0100

(a similar message was just posted to the wintcl discussion list)

As some of you might have noticed, the Tk 4.2 PhotoImage code is
seriously broken for 16-bit "HighColor" Windows displays, at least on
Windows 95.

  The first of the attached patches fixes the bug in a rather crude
fashion (tested on win95 only).

  The second patch is a Windows-specific patch that boosts performance
for 16/24-bit displays.  Here's the result from a sample program which
loads two 512x512 greyscale PGM's, and two 512x512 colour PPM's, and
displays each of them in a separate toplevel windows.  Tcl/Tk was
compiled with Visual C 4.0, and run on a P100 under Win95.  Image load
times are not included in the timings:

			8-bit		16-bit		24-bit
1. original 4.2 code	5.52 s		8.57 s		3.79 s
2. booster patch	5.49 s		1.87 s		1.82 s

   speedup		None		4.6x		2.1x

Tk is pretty nice, but Tk with decent performance is even nicer.

Regards	/F


(Sorry for the patch format; don't have a decent diff on my PC...)

1. For portability and speed, the best thing under Windows is to treat
   16-bit displays as if they were 24-bit. The Windows device drivers
   takes care of the rest.  In tkWinImage.c, change:

    imagePtr->bits_per_pixel = depth;


    if (visual->class == TrueColor)
	/* true colour is stored as 3 bytes: (blue, green, red) */
	imagePtr->bits_per_pixel = 24;
	imagePtr->bits_per_pixel = depth;

NOTE: This turned out to be quite similar to how this was done in 4.1,
which worked fine (but much too slow) on 16-bit displays.  There's
probably some reason for the change; it is mentioned in the CHANGES
file as a fix to make sure *image* depths other than 8 and 24 bits
works, but I have still to find a machine where 4.2 works for
*display* depths other than 8 and 24 bits...

2. The DitherInstance implementation is not good.  It's especially
bad on highend truecolour displays; it crawls under Windows, it
crawls on my fast 64-bit workstation.  IMO, it should be rewritten
from scratch (stay tuned ;-)...

  Anyway, the following band-aid makes the situation a little bit
better under Windows.  This hack trades some marginal quality (no
dithering on 16-bit displays) for a dramatic performance boost.
Requires patch 1 to be in place.

    for (; height > 0; height -= nLines) {
	if (nLines > height) {
	    nLines = height;
	dstLinePtr = (unsigned char *) imagePtr->data;
	yEnd = yStart + nLines;
#ifdef __WIN32__
	if (colorPtr->visualInfo.class == TrueColor
		&& instancePtr->gamma == 1.0) {
	    /* Windows hicolor/truecolor booster */
	    for (y = yStart; y < yEnd; ++y) {
		destBytePtr = dstLinePtr;
		srcPtr = srcLinePtr;
		for (x = xStart; x < xEnd; ++x) {
		    destBytePtr[0] = srcPtr[2];
		    destBytePtr[1] = srcPtr[1];
		    destBytePtr[2] = srcPtr[0];
		    destBytePtr += 3; srcPtr += 3;
		srcLinePtr += lineLength;
		dstLinePtr += bytesPerLine;
	} else
	for (y = yStart; y < yEnd; ++y) {
	    srcPtr = srcLinePtr;
	    errPtr = errLinePtr;
	    destBytePtr = dstLinePtr;


IMAGE-SIG - SIG on Image Processing with Python

send messages to: image-sig@python.org
administrivia to: image-sig-request@python.org