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

Just starting out? Need help? Post your questions and find answers here.
SMaag
Enthusiast
Enthusiast
Posts: 303
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

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

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

User avatar
NicTheQuick
Addict
Addict
Posts: 1504
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

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

Post 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.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
Bmld756
User
User
Posts: 30
Joined: Mon Sep 19, 2022 3:30 pm

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

Post 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
------------------------------
Last edited by Bmld756 on Mon Feb 03, 2025 10:09 pm, edited 1 time in total.
IMAC 21.5 2012 Core I5 - 2.70 Ghz. 16 GB NVIDIA GeForce GT 640M 512 Mo. MacOs OCPL Sequoia 15.0
MacBook Air M1 - 8Go - Sonoma 14.1
Bmld756
User
User
Posts: 30
Joined: Mon Sep 19, 2022 3:30 pm

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

Post 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
------------------------------
IMAC 21.5 2012 Core I5 - 2.70 Ghz. 16 GB NVIDIA GeForce GT 640M 512 Mo. MacOs OCPL Sequoia 15.0
MacBook Air M1 - 8Go - Sonoma 14.1
User avatar
idle
Always Here
Always Here
Posts: 5836
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

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

Post by idle »

I just thought is was difference between windows vs Linux or mac as far as we're concerned.
SMaag
Enthusiast
Enthusiast
Posts: 303
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

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

Post 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!
Post Reply