You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
tkinter askcolor returning floats for r, g, b values instead of ints #77470
Even though the underlying tcl/tk interpreter is returning ints, askcolor is converting the values to floats. My guess is this is an oversight related to the change in functionality of the / operator in python3.
For future reference, 3.4 and 3.5 only get security fixes.
The quoted line of code is from the main part of tkinter.colorchooser,Chooser._fixresult:
r, g, b = widget.winfo_rgb(result)
return (r/256, g/256, b/256), str(result)
where tkinter.Misc defines
def winfo_rgb(self, color):
"""Return tuple of decimal values for red, green, blue for
COLOR in this widget."""
return self._getints(
self.tk.call('winfo', 'rgb', self._w, color))
The code in tkColorChooser and Tkinter in 2.x is the same.
The docstring for winfo_rgb is wrong as it returns a tuple of ints in range(2**16256). For red, the results are
>>> Tk().winfo_rgb('red')
(65535, 0, 0) # 2.x and 3.x
>>> cc.askcolor('red')
((255, 0, 0), '#ff0000') # 2.7
>>> cc.askcolor('red')
((255.99609375, 0.0, 0.0), '#ff0000') # 3.8
In addition to fixing the winfo_rgb docstring (in all versions), and adding doc strings to colorchooser, it seems that '/' should be '//' in 3.x. I don't know if I would fix this in 3.6.
changed the title [-]askcolor is returning floats for r,g,b values instead of ints[/-][+]tkinter askcolor returning floats for r,g,b values instead of ints[/+]on Apr 21, 2018
Good catch! A color tuple will likely be used in '#%02x%02x%02x' % color, and this will fail because %x works only with integers (in general sense). Therefore returning a tuple of floats is a bug.
The downside is that we loss some information. Tk supports up to 16 bit per color component, and askcolor() keeps only higher 8 of them. This can't be changed for backward compatibility, but it may be worth to add an option for control the representation of the result. winfo_rgb() returns 16-bit color components. This is a separate issue.
yes, this is a well known backwards incompatibility. In python 2, the
division operator returns an integer if both operands are integers. In
python 3 it returns a float.
changed the title [-]tkinter askcolor returning floats for r,g,b values instead of ints[/-][+]tkinter askcolor returning floats for r, g, b values instead of ints[/+]on Jul 12, 2018
https://www.tcl.tk/man/tcl8.6/TkCmd/winfo.htm says
"winfo rgb window color
Returns a list containing three decimal values in the range 0 to 65535, which are the red, green, and blue intensities that correspond to color in the window given by window. Color may be specified in any of the forms acceptable for a color option."
Since tk represents data as strings, 'decimal value in [0, 65535)' means 'integer value represented by decimal digits'. 'correspond to color in the window' implies that the mapping from color to decimal value could depend on the window. The mapping *does* differ between systems (see below).
https://www.tcl.tk/man/tcl8.6/TkLib/GetColor.htm
Lists possible return values, hence acceptible forms, as name or '#' followed by 1 to 4 hex digits. It continues with "Each R, G, or B represents a single hexadecimal digit. The four forms permit colors to be specified with 4-bit, 8-bit, 12-bit or 16-bit values. When fewer than 16 bits are provided for each color, they represent the most significant bits of the color, while the lower unfilled bits will be repeatedly replicated from the available higher bits. For example, #3a7 is the same as #3333aaaa7777."
This omits to say what happens when there are 2 or 3 hex digits. Windows ignores 3rd and 4th hex digits. On Windows, dividing by 257 instead of 256 would be correct. However, 256 works because the 'error', represented by the remainder, is always in [0, 256). MacOS does not ignore digits.
The PR is blocked because the new colorchooser tests pass on Windows and macOS but fail on Ubuntu. Cheryl speculated that the color names values vary across systems. I think that it might instead be a coding issue, but I want to understand coding on Windows and Mac better before looking into Linux.
On Windows, each r, g, b value is n * 257 for n in range(256) (see attached file). The precision loss happens when colors are stored, before the division in winfo_rgb. Perhaps 8 bits/channel (including alpha) is baked in.
Since divmod(n * 257, 257) = (n, 0) and divmod(n * 257, 256) = (n, n),
(n*257) // m = divmod(n*257, m)[0] = n whether m is 256 or 257.
---
macOS appears (from limited experiments) to handle 1 and 2 digits the same as Windows (repeat 4 or 2 times): val('#a00') = val('#aaaa00000000') = 0xaaaa, val('#ab0000') = val('#abab00000000') = 0xabab. 4 digits are left alone while 3 digits use the 1st as the 4th val('#abc000000') = val('#abca00000000') = 0xabca.
I do not understand why #abc000000 and #abcd00000000 give 0xabab on my computer (Linux) and even weirder result on Ubuntu on CI. Reading the code I expected the same behavior as on macOS.
Your Linux result is the same as on Windows. Given strings 'abc' or 'abcd', ignore 'c' or 'cd' and expand 'ab' to 'abab', making value 0xabab. Is your computer Ubuntu (implying that personal Ubuntu != CI Ubuntu) or a different Linux? Are there tk/tcl compilation flags or X window options that could affect stored color values?
New changeset 6713e86 by Cheryl Sabella in branch 'master': bpo-33289: Return RGB triplet of ints instead of floats from tkinter.colorchooser (GH-6578) 6713e86
New changeset 3d5434d by Serhiy Storchaka in branch '3.9':
[3.9] bpo-33289: Return RGB triplet of ints instead of floats from tkinter.colorchooser (GH-6578). (GH-24318) 3d5434d
New changeset 96bcf6f by Miss Islington (bot) in branch '3.8':
[3.9] bpo-33289: Return RGB triplet of ints instead of floats from tkinter.colorchooser (GH-6578). (GH-24318) 96bcf6f
Activity
BryanOakley commentedon Apr 16, 2018
Even though the underlying tcl/tk interpreter is returning ints, askcolor is converting the values to floats. My guess is this is an oversight related to the change in functionality of the / operator in python3.
this:
should probably be this:
terryjreedy commentedon Apr 21, 2018
For future reference, 3.4 and 3.5 only get security fixes.
The quoted line of code is from the main part of tkinter.colorchooser,Chooser._fixresult:
r, g, b = widget.winfo_rgb(result)
return (r/256, g/256, b/256), str(result)
where tkinter.Misc defines
def winfo_rgb(self, color):
"""Return tuple of decimal values for red, green, blue for
COLOR in this widget."""
return self._getints(
self.tk.call('winfo', 'rgb', self._w, color))
The code in tkColorChooser and Tkinter in 2.x is the same.
In addition to fixing the winfo_rgb docstring (in all versions), and adding doc strings to colorchooser, it seems that '/' should be '//' in 3.x. I don't know if I would fix this in 3.6.
[-]askcolor is returning floats for r,g,b values instead of ints[/-][+]tkinter askcolor returning floats for r,g,b values instead of ints[/+]serhiy-storchaka commentedon Apr 21, 2018
Good catch! A color tuple will likely be used in '#%02x%02x%02x' % color, and this will fail because %x works only with integers (in general sense). Therefore returning a tuple of floats is a bug.
The downside is that we loss some information. Tk supports up to 16 bit per color component, and askcolor() keeps only higher 8 of them. This can't be changed for backward compatibility, but it may be worth to add an option for control the representation of the result. winfo_rgb() returns 16-bit color components. This is a separate issue.
csabella commentedon Apr 22, 2018
Adding to what Serhiy said about the askcolor() return value is an issue that also affects input:
Changing _fixoptions to format initialcolor using "#%04x%04x%04x" % color.
allows for 16-bit hex values, but it's not the same as 8-bit.
(255, 0, 0) in the second call is black and not red.
vstinner commentedon Jul 12, 2018
Is this issue a regression of Python 3? red/256 gave an integer on Python 2?
terryjreedy commentedon Jul 12, 2018
It appears so.
BryanOakley commentedon Jul 12, 2018
yes, this is a well known backwards incompatibility. In python 2, the
division operator returns an integer if both operands are integers. In
python 3 it returns a float.
https://www.python.org/dev/peps/pep-0238/
On Thu, Jul 12, 2018 at 8:48 AM STINNER Victor <[email protected]>
wrote:
[-]tkinter askcolor returning floats for r,g,b values instead of ints[/-][+]tkinter askcolor returning floats for r, g, b values instead of ints[/+]terryjreedy commentedon Jan 21, 2021
https://www.tcl.tk/man/tcl8.6/TkCmd/winfo.htm says
"winfo rgb window color
Returns a list containing three decimal values in the range 0 to 65535, which are the red, green, and blue intensities that correspond to color in the window given by window. Color may be specified in any of the forms acceptable for a color option."
Since tk represents data as strings, 'decimal value in [0, 65535)' means 'integer value represented by decimal digits'. 'correspond to color in the window' implies that the mapping from color to decimal value could depend on the window. The mapping *does* differ between systems (see below).
https://www.tcl.tk/man/tcl8.6/TkLib/GetColor.htm
Lists possible return values, hence acceptible forms, as name or '#' followed by 1 to 4 hex digits. It continues with "Each R, G, or B represents a single hexadecimal digit. The four forms permit colors to be specified with 4-bit, 8-bit, 12-bit or 16-bit values. When fewer than 16 bits are provided for each color, they represent the most significant bits of the color, while the lower unfilled bits will be repeatedly replicated from the available higher bits. For example, #3a7 is the same as #3333aaaa7777."
This omits to say what happens when there are 2 or 3 hex digits. Windows ignores 3rd and 4th hex digits. On Windows, dividing by 257 instead of 256 would be correct. However, 256 works because the 'error', represented by the remainder, is always in [0, 256). MacOS does not ignore digits.
https://www.tcl.tk/man/tcl8.6/TkCmd/colors.htm
Lists current color names and their values as 16 bit decimals.
The PR is blocked because the new colorchooser tests pass on Windows and macOS but fail on Ubuntu. Cheryl speculated that the color names values vary across systems. I think that it might instead be a coding issue, but I want to understand coding on Windows and Mac better before looking into Linux.
terryjreedy commentedon Jan 21, 2021
On Windows, each r, g, b value is n * 257 for n in range(256) (see attached file). The precision loss happens when colors are stored, before the division in winfo_rgb. Perhaps 8 bits/channel (including alpha) is baked in.
Since divmod(n * 257, 257) = (n, 0) and divmod(n * 257, 256) = (n, n),
(n*257) // m = divmod(n*257, m)[0] = n whether m is 256 or 257.
---
macOS appears (from limited experiments) to handle 1 and 2 digits the same as Windows (repeat 4 or 2 times): val('#a00') = val('#aaaa00000000') = 0xaaaa, val('#ab0000') = val('#abab00000000') = 0xabab. 4 digits are left alone while 3 digits use the 1st as the 4th val('#abc000000') = val('#abca00000000') = 0xabca.
serhiy-storchaka commentedon Jan 21, 2021
I do not understand why #abc000000 and #abcd00000000 give 0xabab on my computer (Linux) and even weirder result on Ubuntu on CI. Reading the code I expected the same behavior as on macOS.
terryjreedy commentedon Jan 21, 2021
Your Linux result is the same as on Windows. Given strings 'abc' or 'abcd', ignore 'c' or 'cd' and expand 'ab' to 'abab', making value 0xabab. Is your computer Ubuntu (implying that personal Ubuntu != CI Ubuntu) or a different Linux? Are there tk/tcl compilation flags or X window options that could affect stored color values?
serhiy-storchaka commentedon Jan 21, 2021
New changeset 6713e86 by Cheryl Sabella in branch 'master':
bpo-33289: Return RGB triplet of ints instead of floats from tkinter.colorchooser (GH-6578)
6713e86
serhiy-storchaka commentedon Jan 25, 2021
New changeset 3d5434d by Serhiy Storchaka in branch '3.9':
[3.9] bpo-33289: Return RGB triplet of ints instead of floats from tkinter.colorchooser (GH-6578). (GH-24318)
3d5434d
miss-islington commentedon Jan 25, 2021
New changeset 96bcf6f by Miss Islington (bot) in branch '3.8':
[3.9] bpo-33289: Return RGB triplet of ints instead of floats from tkinter.colorchooser (GH-6578). (GH-24318)
96bcf6f