I'm little bit confused about Color Byte Order on different Systems
Posted: Mon Feb 03, 2025 11:10 am
The standard Color order on Windows AMD/Intel is little Endian. Lo-Byte first.
And I think on Linux AMD&Intel too!
in Memory: RGBA -> in the CPU registers ABGR That's clear!
But how is it on other Systems?
I'm actually coding/testing some functions for Color and Image processing!
Here is a part of my erarly code. It prints in the Debug Window the Color Order!
Can anyone tell me what's the output on Mac PowerPC, Mac Intel, MacArm, Raspii.
Or does anyone know the exact ColorOrder for all the Systems?
And I think on Linux AMD&Intel too!
in Memory: RGBA -> in the CPU registers ABGR That's clear!
But how is it on other Systems?
I'm actually coding/testing some functions for Color and Image processing!
Here is a part of my erarly code. It prints in the Debug Window the Color Order!
Can anyone tell me what's the output on Mac PowerPC, Mac Intel, MacArm, Raspii.
Or does anyone know the exact ColorOrder for all the Systems?
Code: Select all
CompilerIf #PB_Compiler_Processor = #PB_Processor_PowerPC
; ----------------------------------------------------------------------
; This is the exception Alpha first : Motorola PowerPC
; ----------------------------------------------------------------------
Structure TSystemRGBA ; here it's ABGR in Memory
A.a
B.a
G.a
R.a
; maybe it's BGRA
; B.a
; G.a
; R.a
; A.a
EndStructure
CompilerElse ; x86, x64; (ARM32; ARM64)???
; ----------------------------------------------------------------------
; This is the standard Windows alignment RED=LoByte .. Alpha=HiByte
; In Memory RGBA but in Processor Register ABGR
; ----------------------------------------------------------------------
Structure TSystemRGBA ; here it's RGBA in Memory
R.a
G.a
B.a
A.a
EndStructure
CompilerEndIf
Structure TSystemColor ; The SystemColorStructure to have multiple access to the Color Channels!
; This is the trick how it works! TSystem RGBA is integrated as complete Structure, not as Pointer!
; This is a documented feature. See the PB help for Structure Union. There you will find the RGB example!
; IDENTICAL POINTERS FOR:
; @TSystemColor= @TSystemColor\col= @TSystemColor\RGB = @TSystemColor\RGB\R = @TSystemColor\ch[0]
StructureUnion
RGB.TSystemRGBA ; Access single color channels by name
col.l ; Access as 32Bit Color
ch.a[4] ; Access single color channels by numger [0..3]
EndStructureUnion
EndStructure
; System Color Mask Structure to hold management data for the systems color order RGBA, ABGR or BGRA
; use the Function InitSytemColorMask() to intialize the Datas of a TSystemColorMask Structrue
Structure TSystemColorMask
idxRed.i ; 0 based ByteIndex for Red Channel
idxGreen.i ; 0 based ByteIndex for Green Channel
idxBlue.i ; 0 based ByteIndex for Blue Channel
idxAlpha.i ; 0 based ByteIndex for Alpha Channel
shlRed.i ; No of Bits to Shift for Red Channel
shlGreen.i ; No of Bits to Shift for Green Channel
shlBlue.i ; No of Bits to Shift for Blue Channel
shlAlpha.i ; No of Bits to Shift for Alpha Channel
maskRed.i ; BitMask to select Red value
maskGreen.i ; BitMask to select Green value
maskBlue.i ; BitMask to select Blue value
maskAlpha.i ; BitMask to select Alpha value
maskRedOff.i ; BitMask to reset Red Channel
maskGreenOff.i ; BitMask to reset Green Channel
maskBlueOff.i ; BitMask to reset Blue Channel
maskAlphaOff.i ; BitMask to reset Alpha Channel
EndStructure
Global _SCM.TSystemColorMask
; If Alpha = 0 Then Alpha = 255
; use it : SetAlphaIfNull(varColor)
Macro SetAlphaIfNull(varColor)
If Not (varColor & PB::_SCM\maskAlpha)
varColor = varColor | PB::_SCM\maskAlpha
EndIf
EndMacro
; Blend RedVal into ColorVar : Alpha [0..255] is the Blending for Red(ColorVar)
; use it : BlendRed(ColorVar, RedVal, Alpha)
; or : BlendRed(ColorVar, Red(MyColor), Alpha)
Macro BlendRed(ColorVar, RedVal, Alpha=127)
ColorVar = (ColorVar & PB::_SCM\maskRedOff) | (((Red(ColorVar)* Alpha + RedVal *(255-Alpha))>>8) << PB::_SCM\shlRed)
EndMacro
; Blend GreenVal into ColorVar : Alpha [0..255] is the Blending for Green(ColorVar)
; use it : BlendGreen(ColorVar, GreenVal, Alpha)
; or : BlendGreen(ColorVar, Green(MyColor), Alpha)
Macro BlendGreen(ColorVar, GreenVal, Alpha=127)
ColorVar = (ColorVar & PB::_SCM\maskBlueOff) | (((Green(ColorVar)* Alpha + GreenVal *(255-Alpha))>>8) << PB::_SCM\shlGreen)
EndMacro
; Blend BlueVal into ColorVar : Alpha [0..255] is the Blending for Blue(ColorVar)
; use it : BlendBlue(ColorVar, BlueVal, Alpha)
; or : BlendBlue(ColorVar, Blue(MyColor), Alpha)
Macro BlendBlue(ColorVar, BlueVal, Alpha=127)
ColorVar = (ColorVar & PB::_SCM\maskBlueOff) | (((Blue(ColorVar)* Alpha + BlueVal *(255-Alpha))>>8) << PB::_SCM\shlBlue)
EndMacro
; Blend 2 Colors and Return blended value
; use it : result = BlendColors(Color1, Color2, Alpha) : Alpha is the factor for COL1
Macro BlendColors(COL1, COL2, Alpha=127)
((((Red(COL1)*Alpha + Red(COL2)*(255-Alpha))>>8)<< PB::_SCM\shlRed) | (((Green(COL1)*Alpha + Green(COL2)*(255-Alpha))>>8)<< PB::_SCM\shlGreen) | (((Blue(COL1)*Alpha + Blue(COL2)*(255-Alpha))>>8)<< PB::_SCM\shlBlue))
EndMacro
; Methode | Weight Base % | Weight Base 1024 for >>10 use
; ------------------------|----------------------------|------------------------------
; Greyscale_Average | (33.3, 33.3, 33.3)% =99.9 | (341, 341, 341) =1023 = 99.9%
; Greyscale_Standard | (29.9, 58.7, 11.4)% =100 | (306, 601, 117) =1024 = 100%
; Greyscale_WeightedLight | (30.9, 60.9, 8.2)% =100 | (316, 624, 84) =1024 = 100%
; R = 333 ; factor = 0.333 we use integer multiplikation *1024>>10
; G = 333
; B = 333
Macro GreyScaleAverage(ColorValue)
(Red(ColorValue)341 + Green(ColorValue)341 + Blue(ColorValue)341)>>10)
EndMacro
; R = 299
; G = 587
; B = 114
Macro GreyScaleStandard(ColorValue)
(Red(ColorValue)306 + Green(ColorValue)*601 + Blue(ColorValue)117)>>10)
EndMacro
; R = 309
; G = 609
; B = 82
Macro GreyScaleWeightedLight(ColorValue)
(Red(ColorValue)*316 + Green(ColorValue)*624 + Blue(ColorValue)*84)>>10)
EndMacro
Procedure.i InitSytemColorMask(*SCM.TSystemColorMask)
; ============================================================================
; NAME: IntiSytemColorMask
; DESC: initialize a TSystemColorMask Structure with the correct management
; DESC: data for the systmens Color order RGBA, ABGR
; VAR(*SCM.TSystemColorMask): The SystemColorMask variable to initialize
; RET.i : *SCM
; ============================================================================
Protected SysCol.TSystemColor
Protected.a rd, gn, bl, al ; the standard Color oder in Memory
Protected I, CHval
; first initialize an unique value for each ColorChannel r,g,b,a
rd =$11 : gn =$22 : bl =$33 : al =$44
SysCol\col =RGBA(rd,gn,bl,al) ; Create the ColorValue with the unique Channel values
If *SCM
With *SCM
; Step 1 : step trough the 4 Bytes of the created Color and
; compare the value in memory with the unique Channel values
For I = 0 To 3
Select SysCol\ch[I] ; Access to Color with ChannelNo [0..3]
Case rd ; unique value for Red channel found
\idxRed = I ; save index for Red
Case gn ; unique value for Green channel found
\idxGreen = I ; save index for Green
Case bl ; unique value for Blue channel found
\idxBlue = I ; save index for Blue
Case al ; unique value for Alpha channel found
\idxAlpha = I ; save index for Alpha
EndSelect
Next
; Step 2 : Caluclate the Bits to Shift for each Channel
; This is calculation for LittleEndian! Maybe not correct for BigEndian!
\shlRed = \idxRed *8
\shlGreen = \idxGreen *8
\shlBlue = \idxBlue *8
\shlAlpha = \idxAlpha *8
; Step 3 : Calculate BitMask to filter each Channel
\maskRed = ($FF << \shlRed)
\maskGreen = ($FF << \shlGreen)
\maskBlue = ($FF << \shlBlue)
\maskAlpha = ($FF << \shlAlpha)
; Step 4 : Calculate BitMask to Reset Channel to 0
\maskRedOff = ~\maskRed & $FFFFFFFF ; limit to 32Bit
\maskGreenOff = ~\maskGreen & $FFFFFFFF
\maskBlueOff = ~\maskBlue & $FFFFFFFF
\maskAlphaOff = ~\maskAlpha & $FFFFFFFF
EndWith
EndIf
; Debug the ColorChannel Order and the Pointers to the Structure Elements
; IDENTICAL POINTERS FOR:
; @TSystemColor= @TSystemColor\col= @TSystemColor\RGB = @TSystemColor\RGB\R = @TSystemColor\ch[0]
With SysCol
Debug "------------------------------"
Debug "PB::InitSytemColorMask"
Debug "Color order in Memory Channel + ByteNo -> maybe wrong for BigEndian (PowerPC)"
Debug "Red-Channel = " + _SCM\idxRed
Debug "Green-Channel = " + _SCM\idxGreen
Debug "Blue-Channel = " + _SCM\idxBlue
Debug "Alpha-Channel = " + _SCM\idxAlpha
Debug ""
Debug "Pointers of TSystemColor Structure"
Debug "@SysCol =" + @SysCol
Debug "@SysCol\col =" +@\col
Debug "@SysCol\ch[0] =" +@\ch[0]
Debug "@SysCol\RGB =" + @\RGB
Debug "@SysCol\RGB\R =" +@\RGB\R
Debug ""
Debug "@SysCol\RGB\G =" +@\RGB\G
Debug "@SysCol\RGB\B =" +@\RGB\B
Debug "@SysCol\RGB\A =" +@\RGB\A
Debug "------------------------------"
EndWith
; Show Error Message for programmer, if the Color Order does not fit together"
With SysCol
If \RGB\R <> rd Or \RGB\G <> gn Or \RGB\B <> bl Or \RGB\A <> al
MessageRequester("Purebasic Framework: Error in Modul: " + #PB_Compiler_Module + "/" + #PB_Compiler_Procedure, "The System Color order does not fit with the programmed one in TSystemColor")
EndIf
EndWith
ProcedureReturn *SCM
EndProcedure
InitSytemColorMask(_SCM)