Tk Source Code

View Ticket
Login
Ticket UUID: 919066
Title: Slow processing irregular transparencies
Type: Bug Version: obsolete: 8.4.5
Submitter: jaspert Created on: 2004-03-18 21:10:57
Subsystem: 41. Photo Images Assigned To: dkf
Priority: 8 Severity: Minor
Status: Open Last Modified: 2024-06-20 20:51:52
Resolution: Remind Closed By: nobody
    Closed on:
Description:
If you have a photo image with irregular transparent
patches dotted around it it takes an atrociously long
time to copy. It seems to be exponentially related to
image size. For instance, here it takes about 2.5
minutes of CPU time on my Athlon XP1600 to create this
fairly compact 750x500 image by tiling a small but
holey initial image (attached)...

% info patchlevel
8.4.2
% image create photo p1 -file flip_v.gif
p1
% image create photo p2
p2
% p2 copy p1 -to 0 0 750 500
< 150 second pause occurs here>
%
User Comments: fvogel added on 2024-06-20 20:51:52:

Duplicated one more time in [aa802cdecf].


chrstphrchvz added on 2023-12-02 07:45:32:

For reference, I proposed a way for the shape extension to work without TkPhotoGetValidRegion(): https://github.com/dkfellows/shape/pull/8

TkZinc uses regions extensively. My earlier assessment of it was incomplete.


dkf added on 2023-11-13 10:21:38:

I don't think it is a problem to ask for my shape extension to change. That's had extremely little attention over the years...

Alternatively, don't compute the region until it is asked for at least once. Like that, most code won't pay the costs associated.


chrstphrchvz added on 2023-11-09 16:26:19:

…if transparency get is not enough for extensions, then a new C API can be introduced…

Or not; extensions can already use Tk_PhotoGetImage() to get the alpha channel values.


oehhar added on 2023-07-22 18:27:28:

Dear Christopher,

thank you for looking into this, this is great.

We have two big performance issues in Tk, elided text in the text widget and photos with transparencies. The first is attacked by the new text widget (again emphasized by Csaba in the conference). Now, there is a solution for the 2nd.

I personally doN't care which solution is used, only that it is solved, sorry for my ignorance. And a first patch is a good start.

Thank you for that, great ! Harald


chrstphrchvz added on 2023-07-21 20:29:04:

As previously stated, this issue has to do with computing the valid region of a photo image, which takes a very long time for certain images with many transparent areas.

But from looking at what the valid region is used for, I find that the only uses of it in core Tk are not strictly necessary. Since TIP 98, photo images have 32-bit pixels to hold alpha channel. The transparency get subcommand, originally from TIP 14, could instead check whether the alpha channel of a pixel is 0 rather than test if it is in the valid region (see [2294f0694eda]). And when drawing a photo instance, the alpha channel can be used to construct a bitmap (i.e. pixmap with depth of 1) for use as a clipping mask, instead of clipping to the valid region. The somewhat more pervasive remaining usage is of the valid region’s clip box (i.e. bounding rectangle) as an optimization for copying and displaying; I suspect this is of negligible benefit on modern systems.

It would seem the only reason for computing the valid region at all is that the TkPhotoGetValidRegion() function is for use by extensions (see TIP 14).

Here are roughly what the alternatives seem to be:

  1. Remove use of a valid region entirely, despite extensions using TkPhotoGetValidRegion().
  2. Compute the valid region only when TkPhotoGetValidRegion() is called, but do not use or maintain it; only keep a handle so that it is eventually destroyed. If TkPhotoGetValidRegion() is called again then the valid region is assumed outdated and recomputed from scratch.
  3. Compute the valid region only when TkPhotoGetValidRegion() is called, but use and maintain it (reverting to the current behavior); the valid region is ready to use if TkPhotoGetValidRegion() is called again.

I have a draft implementation of approach 3: https://github.com/chrstphrchvz/tk/pull/4/files

But if approach 1 is preferred, and if transparency get is not enough for extensions, then a new C API can be introduced, such as one returning the alpha channel as an XImage bitmap that can then be passed to XGetPixel() or XPutImage(). For the only extensions I have found which use TkPhotoGetValidRegion(), I think this could work since they do not seem to truly require using a region:

  1. TkZinc, which retrieves alpha for the entire image by testing if each pixel in the valid region; an alternative would be to get the alpha bitmap XImage and use XGetPixel().
  2. DKF’s shape extension, which passes the valid region to XShapeCombineRegion(); an alternative would be to use XPutImage() to create a clip mask and then call XShapeCombineMask().

Any of these approaches are probably still less involved than getting alpha blending to work (properly) on all platforms. They also have no change to photo image drawing on Aqua, because it currently draws using a photo model rather than an instance (which I believe is erroneous: see [de6ef8276c]).


jan.nijtmans added on 2022-04-22 10:35:09:

Duplicated in [d9c8ccb042] and [b9827ece14]


chrstphrchvz added on 2022-02-13 21:20:28:

The example here starts with a small image and then creates a larger tiled version of it; loading the image from a file is fast, but creating the tiled copy is slow. The shade.png example in [b9827ece] happens to be an larger image of an already-tiled 2x2 pattern, and so loading it from the file is slow; if it instead started with an image containing only the 2x2 pattern, then loading from a file would be quick, but creating a tiled copy of it (as done in the example for this ticket) would be extremely slow.


andsaTk added on 2022-02-13 15:25:33:
I think this old example flip_v.gif is useless now,
because it opens on my Notebook in 0,0 seconds.

My example code in the other ticket creates
pictures in any size and color that lasts minutes
to open.

chrstphrchvz added on 2022-02-08 05:00:17:

[b9827ece] seems to be a duplicate of this.


dkf added on 2009-07-28 19:36:38:
Modern hardware speeds this up. 28 seconds on OSX... 8-(

dkf added on 2006-03-28 20:49:54:
Logged In: YES 
user_id=79902

A couple of other minor notes to save myself time when I
next come back to this:

The culprit is one (extremely long-lasting) call to
TkpBuildRegionFromAlphaData, and that already only processes
the part of the image being updated. There aren't multiple
calls to Tk_PhotoPutBlock to optimize out. :-(

The local-compositing scheme used with complex alpha is
probably the way to go, though that's got its own set of
performance troubles and has problems with partial image
drawing...

dkf added on 2006-03-28 20:35:20:
Logged In: YES 
user_id=79902

Bleah, still broken with 8.5a4rc2 even under Linux. :-(

% time {p2 copy p1 -to 0 0 750 500}
80670358 microseconds per iteration

The cost appears to be the region handling (or at least it's
deep in the guts of XShrinkRegion where I'm most likely to
interrupt inside a debugger, which serves as a very crude
kind of profiling). Fixing this is going to require enough
work that it isn't going to happen in time for 8.5a4

dkf added on 2006-03-27 19:19:09:
Logged In: YES 
user_id=79902

There was a separate performance problem too. Can you
recheck with 8.5a4 or 8.4.13? (I have site-specific build
problems.)

jaspert added on 2005-02-25 01:30:16:
Logged In: YES 
user_id=456242

A quick, unscientific test seems to indicate performance in
this respect is little changed between 8.4.9 and 8.5a2 --
sorry to say
    --Jasper

dkf added on 2004-10-26 20:16:32:
Logged In: YES 
user_id=79902

I think I've fixed this in 8.5 (or at least reduced the
number of regions that Tk on Win allocates and destroys as
part of processing such an image!)

Can someone check this out, and if it really is fixed, let
me know so I can backport it?

dkf added on 2004-05-17 21:17:28:
Logged In: YES 
user_id=79902

Perhaps it is better to use a thread-local or interp-local
region and SetRectRgn() instead?

http://msdn.microsoft.com/library/en-us/gdi/regions_8nqm.asp

dkf added on 2004-05-05 19:34:51:
Logged In: YES 
user_id=79902

Confirmed that the region code is *desperately* inefficient
as used by the photo code.  :^(  The problem is the way that
Tk_UnionRectWithRegion() allocates and disposes with a
temporary region.  (See tkWinRegion.c for the gory details.)

dkf added on 2004-05-05 19:21:43:
Logged In: YES 
user_id=79902

Duplicated.  Yuck.  Probably (i.e. I've not looked yet, but
it's where I think it'll be wrong) a fault in valid region
management....

jaspert added on 2004-03-19 04:11:01:

File Added - 80580: flip_v.gif

Attachments: