Tk Source Code

View Ticket
Login
Ticket UUID: 98c41cf3e7259ea0adab3e1e220dcf555d5bc88b
Title: ::tk::Darken does not properly brighten colors
Type: Bug Version: 8.6.0
Submitter: anonymous Created on: 2018-04-20 11:28:28
Subsystem: 29. Colormaps and Visuals Assigned To: fvogel
Priority: 5 Medium Severity: Minor
Status: Closed Last Modified: 2018-05-03 20:28:13
Resolution: Fixed Closed By: fvogel
    Closed on: 2018-05-03 20:28:13
Description:
In library/palette.tcl the comment to the procedure ::tk::Darken claims, that colors can be brightened (tinted versus white), "50 means darken by 50%, 110 means brighten by 10%". However, [::tk::Darken #ff0000 150] again yields #ff0000.

Either the comment with respect to brightening should be removed. Or, the code should be changed along the following lines:

# ::tk::Darken --
# Given a color name, computes a new color value that darkens (or
# brightens) the given color by a given percent.
#
# Arguments:
# color -	Name of starting color.
# percent -	Integer telling how much to brighten or darken as a
#		percent: 50 means darken by 50%, 110 means brighten
#		by 10%.

proc ::tk::Darken {color percent} {
    if {$percent < 0} {
	return "black"
    } elseif {$percent > 200} {
	return "white"
    } elseif {$percent <= 100} {
	foreach {red green blue} [winfo rgb . $color] {
	    set red [expr {($red/256)*$percent/100}]
	    set green [expr {($green/256)*$percent/100}]
	    set blue [expr {($blue/256)*$percent/100}]
	}
    } elseif {$percent > 100} {
	foreach {red green blue} [winfo rgb . $color] {
	    set red [expr {255 - ((65535-$red)/256)*(200-$percent)/100}]
	    set green [expr {255 - ((65535-$green)/256)*(200-$percent)/100}]
	    set blue [expr {255 - ((65535-$blue)/256)*(200-$percent)/100}]
	}
    }
    return [format "#%02x%02x%02x" $red $green $blue]
}
User Comments: fvogel added on 2018-05-03 20:28:13:
Merged to core-8-6-branch and trunk.

fvogel added on 2018-04-28 08:02:39:

I have committed your suggested code in branch bug-98c41cf3e7. This looks OK to me.


fvogel added on 2018-04-24 21:48:37:

Yeah a 'shade' routine can be found here for example. I'm using it successfully in an application.


bll added on 2018-04-24 21:03:41:
I don't know that my idea of jumping in and out of HSV or HSL is any good.

I think the OP's algorithm is fine, though I think it should always
return a # notation rather than 'black' or 'white'.

I also wonder if instead of using an unsupported routine, would it be better
for xfig to simply include a 'shade' changing routine as part of the tcl/tk
output it generates.  It sounds like xfig is already including a 'tint' routine.

::tk::Darken isn't used anywhere (internally or otherwise), so changing it
is not going to cause any issues. 
It appears to be a utility routine that was never published or documented.

Cleaned up version.  The version with foreach will work with 8.4 and earlier.

proc ::tk::Darken {color percent} {
  if {$percent < 0} {
    return #000000
  } elseif {$percent > 200} {
    return #ffffff
  } elseif {$percent <= 100} {
    lassign [winfo rgb . $color] r g b
    set r [expr {($r/256)*$percent/100}]
    set g [expr {($g/256)*$percent/100}]
    set b [expr {($b/256)*$percent/100}]
  } elseif {$percent > 100} {
    lassign [winfo rgb . $color] r g b
    set r [expr {255 - ((65535-$r)/256)*(200-$percent)/100}]
    set g [expr {255 - ((65535-$g)/256)*(200-$percent)/100}]
    set b [expr {255 - ((65535-$b)/256)*(200-$percent)/100}]
  }
  return [format #%02x%02x%02x $r $g $b]
}

fvogel added on 2018-04-24 20:15:00:

People using unsupported routines like tk::Darken are on their own. Use this as an engine for your 'tint' routine if you wish, this is your own choice to use internal stuff from Tk, with the usual warnings about the dangers of doing so.

Having said that: why wouldn't we take this opportunity the OP provides by kindly proposing improved code for the internal tk::Darken routine? From a few minutes of quick tests it looks indeed better than what we currently have.

If you wish to propose an even better algorithm jumping in and out the HSV space in the process, feel free to do so...?


anonymous (claiming to be original poster) added on 2018-04-24 13:00:59:
Xfig/fig2dev, beginning with the forthcoming release 3.2.7a, will create tcl/tk output files in which a "tint" routine is defined. In these files, ::tk::Darken will be used for shading colors, and the tint routine will be used to brighten colors.

bll added on 2018-04-23 10:21:17:
As far as I can tell, that's not a supported routine.
Can the xfig routines be used?

anonymous (claiming to be original poster) added on 2018-04-23 09:04:26:
What was reported is an issue that, I believe, classifies as a bug. Whether the issue can be resolved as outlined in the code is beyond my knowledge. In fact, the code was rather supplied to clarify the issue and to show the expected behavior. The request to use a different color model should probably be handled separately, as a feature request.
As a side note, working on the driver that generates tk-code from xfig/fig2dev, I would prefer the simple scaling in rgb space. The reason is, that xfig/fig2dev shades and tints colors in the same way.

bll added on 2018-04-20 17:51:26:
Actually, in HSV, to lighten, reduce the saturation, raise the value.
To darken, raise the saturation, reduce the value.
That's one possible method.
There are many algorithms available on the internet.

bll added on 2018-04-20 17:12:19:
The original code and your code is still very simplistic.
Try converting the RGB to HSV, adjust the value, then converting back.
This will produce a better lighten/darken model.