[Minor bug]: Some(?) nodes which perform conversion from float types to 8-bit image data create less 0 and 255 data than they should because of default round() behavior
- Dominant language
- Python
- Stars
- 133k
- Forks
- 15.7k
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 155
Description
The comy_extras/nodes_mask.py has some code like this:
```python3
temp = (torch.clamp(image, 0, 1.0) * 255.0).round().to(torch.int)
temp = torch.bitwise_left_shift(temp[:,:,:,0], 16) + torch.bitwise_left_shift(temp[:,:,:,1], 8) + temp[:,:,:,2]
mask = torch.where(temp == color, 255, 0).float()
return (mask,)
```
Basically this is just a simple floating point behavior that causes 0s and 255s to occur half as often as other numbers in a random distribution and half as often as they should in any conversion from the [0.0, 1.0) range. tensor.round() is a round nearest function, so in order to be integer 0, an input has to be between 0.0 and 1.0 / 512. Then anything in ((1.0/512), (3.0/512)] is an int 1, and so on until you've got (509.0/512, 511.0] in 254 and finally another half-sized (511.0, 512.0] for 1.0.
In the above code it'll mean the generally-selected mask colors (full saturation for one or two colors and zero for another) have less probability of existing if any math has been done on the tensor since it was loaded from whatever source.
It creates something of an absense of true blacks and whites as well as fully saturated other colors although I haven't hacked anything in to see how often it occurs. It shouldn't be too terrible loading from file because things will be more quantized, it's only generated data like decoded latents or file data that's been manipulated.
Compensating for things either by adding 0.5 after multiplying by 255.0 or multiplying by 255.9 and using floor() instead fixes it... I spotted torchvision doing this using a fixed epsilon correction at one point which is the correct way, since it removes that half-bin offset that messes stuff up before rounding although they just sorta winged that too and went ((255 + 1 - 1e-3) * image...), PIL doesn't seem to deal with float types at all just like they've managed to not support 16 bit color somehow (but they also call image color channels "bands" in that project which is a neat term for it that nobody in the history of computer graphics has ever used, so I'm somehow not too surprised).
Lots of custom nodes do this too. Like I said it's minor and I don't know if anybody is doing enough image manipulation directly in comfy to end up with issues from it. Still, might as well make sure everything gets distributed like it should.
Contributor guide
Assessment
This issue has not been assessed yet.