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
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
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
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 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