Page 1 of 1

I'm little bit confused about Color Byte Order on different Systems

Posted: Mon Feb 03, 2025 11:10 am
by SMaag
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?

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)


Re: I'm little bit confused about Color Byte Order on different Systems

Posted: Mon Feb 03, 2025 11:42 am
by NicTheQuick
This is the output on an Ubuntu 24.04 LTS Xorg, AMD Ryzen 7 5800X:

Code: Select all

------------------------------
PB::InitSytemColorMask
Color order in Memory Channel + ByteNo -> maybe wrong for BigEndian (PowerPC)
Red-Channel = 0
Green-Channel = 1
Blue-Channel = 2
Alpha-Channel = 3

Pointers of TSystemColor Structure
@SysCol =140734660400360
@SysCol\col =140734660400360
@SysCol\ch[0] =140734660400360
@SysCol\RGB =140734660400360
@SysCol\RGB\R =140734660400360

@SysCol\RGB\G =140734660400361
@SysCol\RGB\B =140734660400362
@SysCol\RGB\A =140734660400363
------------------------------
I hope that helps.

Re: I'm little bit confused about Color Byte Order on different Systems

Posted: Mon Feb 03, 2025 10:05 pm
by Bmld756
Hello, that is the result on IMAC / Sequoia intel

Code: Select all

------------------------------
PB::InitSytemColorMask
Color order in Memory Channel + ByteNo -> maybe wrong for BigEndian (PowerPC)
Red-Channel = 0
Green-Channel = 1
Blue-Channel = 2
Alpha-Channel = 3

Pointers of TSystemColor Structure
@SysCol =140701965170828
@SysCol\col =140701965170828
@SysCol\ch[0] =140701965170828
@SysCol\RGB =140701965170828
@SysCol\RGB\R =140701965170828

@SysCol\RGB\G =140701965170829
@SysCol\RGB\B =140701965170830
@SysCol\RGB\A =140701965170831
------------------------------

Re: I'm little bit confused about Color Byte Order on different Systems

Posted: Mon Feb 03, 2025 10:07 pm
by Bmld756
and on an Apple silicon M1

Code: Select all

------------------------------
PB::InitSytemColorMask
Color order in Memory Channel + ByteNo -> maybe wrong for BigEndian (PowerPC)
Red-Channel = 0
Green-Channel = 1
Blue-Channel = 2
Alpha-Channel = 3

Pointers of TSystemColor Structure
@SysCol =6099859324
@SysCol\col =6099859324
@SysCol\ch[0] =6099859324
@SysCol\RGB =6099859324
@SysCol\RGB\R =6099859324

@SysCol\RGB\G =6099859325
@SysCol\RGB\B =6099859326
@SysCol\RGB\A =6099859327
------------------------------

Re: I'm little bit confused about Color Byte Order on different Systems

Posted: Tue Feb 04, 2025 7:14 am
by idle
I just thought is was difference between windows vs Linux or mac as far as we're concerned.

Re: I'm little bit confused about Color Byte Order on different Systems

Posted: Tue Feb 04, 2025 10:48 am
by SMaag
Ok! That's what I expected.
On AMD/Intel and ARM its little Endian RGBA.

I guess only on PowerPC (old Mac) it is differnt!