Something that just occurred to me after 8 years o...
# android
t
Something that just occurred to me after 8 years of Android programming.. How is Android's colour system integer based? If a colour is represented in hex format, with an alpha channel - it's quite possible (and common) for the resultant decimal value to be Long. That colour value is then cast to integer, and overflows. How does Android's colour system work with overflowed integers? Are there any collisions? Could two different colours end up overflowing to the same value? Or is the explanation just that it's possible to map from the overflowed integer, back to the long value, because the set of possibilities is limited from 0x00000000 to 0xFFFFFFFF (there are no collisions)
stackoverflow 3
m
Not sure what problem you are trying to find here. Since you shouldn’t add two colors, only add the byte parts and clamp them before merging them together to an int, why would you ever overflow?
t
There's no problem. I'm just curious how Android handles this under the hood. When you specify an integer on Android as either a hex string ("#FFFF0000"), or a hexadecimal int (0xFFFF0000), the resultant decimal value is a Long. Android treats colours as integers, so eventually this long is cast back to int. At this point, the integer overflows. Yet Android is able to produce the correct colour.
E.g.
``0xFFFF0000``
(opaque red) - decimal value:
``4294901760``
(long). Cast to int:
``-65536``
(overflow) If you set an Android View's background colour to
``-65536``
, it will be red. I would like to know how this is possible..
e
just look at it as an unsigned integer
t
c
https://en.wikipedia.org/wiki/4,294,967,295 fits in an unsigned 32 bit int, so you can pretend your 32 bit signed int is unsigned and pretend that 0 is 2^31
If you wanted to represent even 1 more possibility, like 0xFFFF0000*1* then int overflows will start to actually be a problem 🙂 (so explanation you had first)
👍 1
m
this whole thing is a mental exercise just because Java decided to omit unsigned numbers 🙂
Also, unless you force a 32bit hex to behave as a long, it happily behaves as a negative integer.
Copy code
``````int col = 0xFFFF0000;
long coll = 0xFFFF0000;

System.out.println(col);
System.out.println(coll);``````
compared to
Copy code
``````int col = 0xFFFF0000;
long coll = 0xFFFF0000L;

System.out.println(col);
System.out.println(coll);``````
k
Nothing to do with Kotlin, but here goes. The overflow is only a thing if you look at the integer value - which is rather meaningless as a value. Color in RGBA_8888 format has four components: red, green. blue, alpha. Each component can have 256 distinct values. That's how it can be "packed" into a single integer. Some "combinations" or "packings" are represented by a negative underlying value at the Java level. Some are represented by a positive underlying value at the Java level. When these values are sent to lower layers of the rendering stack, they are converted to other types, like bytes (for Skia) or floats.
i
oooh, this is juicy, had never thought about the fact that the number was too large. @Tim Malseed — a short explanation is that overflows create negative numbers (because of the way the sign is encoded, you can read about “two’s complement” https://en.wikipedia.org/wiki/Two%27s_complement for more deets). So if no colors are too large or negative (hint: they aren’t) they don’t collide 😄
k
There is no such thing as color overflow or a negative color. The integer representation in the -2B/2B range is just that - representation. It is meaningless to think about the representation overflow in terms of color "overflow"
🔥 1
Same as in Skija (that is used under Compose Desktop). In N32/BGRA_8888 format each component is a byte, which goes from -128 to 127 - at Kotlin level. Not at Skia level. Byte representation overflow is meaningless to "extend" into the color channel overflow at the graphics engine level.
It's the same mental gymnastics as the difference between 1-based counting in real world and 0-based counting in array indexing.
t
Thanks everyone