to start off, let me introduce you to a real monstrosity encountered 4 years ago:
from a old forum discussion in Documentation (April, 2016), a real 'monstrosity'
Code: Select all
Type ColorType ' don't like it (see next evolution step)
Union
As Ulong value ' clr is preferred over value (of what?)
Type
blue As uByte ' if we are using long names then: _
green As uByte
red As ubyte
a As Ubyte ' I'd call it: alpha, instead of a
End Type ' (that is, if not short-cutting all)
End Union
End Type
Reasons (to call it monstrous):
1) enclosing Type is totally pointless, because the Union itself can be 'named'
2) switching declaration mode to data-type before name shows improvement potential
Both issues and above remarks (in the code) attended to, resulted in:
Code: Select all
Union Color_u ' preferred naming (for Union's, append _u)
As ULong clr ' indicates: 32 bit color
Type
As UByte b ' since I prefer short (over long)
As UByte g
As UByte r
As UByte a
End Type
End Union
Addressing the above mentioned improvement potential:
Code: Select all
Union Color_u
As ULong clr ' 32 bit color
Type
As UByte b, g, r, a ' color-channel's (UByte access)
End Type
End Union
Is this the best, that can be done?
Well, depends on whether we rely on the named UBytes or not ...
Without names for the UBytes we simply use a fixed-size UByte array and, at the
same time, getting rid of the Union's internal (unnamed) type:
Code: Select all
Union Color_u
As ULong clr
As UByte cc(0 to 3) ' cc() = short for color-channel
End Union
' cc(0) = blue; cc(1) = green; cc(2) = red; cc(3) = alpha (little-endian)
That now is the most compact Union possible (methinks), without loosing functionality,
that is ...
Below a proof of concept demo (short and sweet):
Code: Select all
' a union is global in FB, like a Type (can be used in procedures, too)
Union c_u ' c_u = color union (24/32 bit)
As ULong clr ' 32 bit color; little-endian = _
As UByte cc(0 To 3) ' BGRA = LSB to MSB memory-layout _
End Union ' color-channels (UByte access)
' use of Union inside procedure (Function here)
Private Function Swap_RB( _ ' WIN to FB or FB to WIN (both ways)
ByVal valu As ULong _ ' original color value (32 bit)
) As ULong ' swapped R and B channels
Dim As c_u u ' one instance of Union (scope: local)
u.clr = valu ' assign input value to Union
Swap u.cc(0), u.cc(2) ' swap blue-cc(0) / red-cc(2) UByte's
Return u.clr ' return with swapped B/R channels
End Function ' (alpha and green unmodified)
Const As ULong red = &hFFFF0000 ' unmodifiable (just used as source)
' use of Union in MAIN-code
Dim As c_u u ' one instance of Union (scope: global)
For i As UInteger = 0 To 255
Var inc = CUByte(i) ' conversion: UInteger to UByte
u.cc(3) = inc ' alpha-channel assign
'u.cc(2) = inc ' red-channel assign
u.cc(1) = inc ' green-channel assign
'u.cc(0) = inc ' blue-channel assign
Print inc, "&h"; Hex(u.clr, 8), _ ' show UByte's state in the ULong
, u.clr ' ULong in decimal is: useless! for _
Next ' this demo's purpose ...
Print : Print "red: "; Hex(red, 8) ' Hex() shows AARRGGBB, inverted memory _
Print ' layout (string is big-endian, always)
Print "red: "; Hex(Swap_RB(red), 8); " -- swapped red/blue channels"
Print : Print ' above: call Function (RB swapper)
Print "press a key to EXIT program ... ";
Sleep