HSL/HSV to RGB
HSL/HSV to RGB
Forgive me, if I missed decent solutions on Forum... (I saw some but they weren't "perfect"...)
Can some Guru suggest me a SUPERFAST method? (I mostly need changing hue... but anyway...)
Thanks!
Can some Guru suggest me a SUPERFAST method? (I mostly need changing hue... but anyway...)
Thanks!
Re: HSL/HSV to RGB
What was the exact problem with the solutions you found on the forum?Piero wrote: Tue Sep 05, 2023 3:56 pm Forgive me, if I missed decent solutions on Forum... (I saw some but they weren't "perfect"...)
Do you need to convert a single value at a time or an array of pixels/rgb values.
On this page https://beesbuzz.biz/code/16-hsv-color-transforms there's also a TransformHSV function that can change the hue of a color.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: HSL/HSV to RGB
Thanks for your replies!
I'm (between other things) trying to make psychedelic graphs in "real time" (see my avatar)
I will take a look to your "methods" as soon as possible...
Thanks Again!
PS: AZJIO, are you Brasileiro, cara?
https://images2.imgbox.com/06/07/nAyqNxRF_o.jpeg
I'm (between other things) trying to make psychedelic graphs in "real time" (see my avatar)
I will take a look to your "methods" as soon as possible...
Thanks Again!
PS: AZJIO, are you Brasileiro, cara?
https://images2.imgbox.com/06/07/nAyqNxRF_o.jpeg
Re: HSL/HSV to RGB
It looks like your are only changing the hue of the hsl/hsv and are keeping the other two components the same.Piero wrote: Tue Sep 05, 2023 10:07 pm I'm (between other things) trying to make psychedelic graphs in "real time" (see my avatar)
If this is always the case, you could speed optimize the code for that.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: HSL/HSV to RGB
I'm working on that stuff! But until now it is not ready!
I have standard functions to convert from HSV/HSL to RGB and back. But this is done with standard CPU commands.
As you can see here: https://beesbuzz.biz/code/16-hsv-color-transforms
The caclculation is always a Matrix Vector Product of a 3x3Matrix with a Vector3 (x,y,z). To speed up this directly isn't possible.
But it is possible as 4x4 Matrix with a Vector4 (x,y,z,w). This is exactly the 4D Transformation for 3D Grafics.
This can be done with the MMX-SSE Extention.
Extending the Matrix to a 4D calculation:
1. The Vector: set w = 1
2.Tthe Matrix 4'th line: set all values to 0 (then you get a 0 back as result of w, which you do not need
now you can use 4D Matrix Vector Product with SSE
here is my Vectorf Module which can do this with SSE.
https://github.com/Maagic7/PureBasicFra ... VECTORf.pb
It is possible to speed up this agian, if you write functions wich converts a complete Image in a Loop. This will save time by eliminating
a function call for each pixel.
As I said, I'm working on that stuff and it will be become part of the 2 Modules VectorColor and Image.
If you are able to make a ready solution from this, please let me know, than I will integrate it in the PureBasicFrameWork project!
I have standard functions to convert from HSV/HSL to RGB and back. But this is done with standard CPU commands.
As you can see here: https://beesbuzz.biz/code/16-hsv-color-transforms
The caclculation is always a Matrix Vector Product of a 3x3Matrix with a Vector3 (x,y,z). To speed up this directly isn't possible.
But it is possible as 4x4 Matrix with a Vector4 (x,y,z,w). This is exactly the 4D Transformation for 3D Grafics.
This can be done with the MMX-SSE Extention.
Extending the Matrix to a 4D calculation:
1. The Vector: set w = 1
2.Tthe Matrix 4'th line: set all values to 0 (then you get a 0 back as result of w, which you do not need
now you can use 4D Matrix Vector Product with SSE
here is my Vectorf Module which can do this with SSE.
https://github.com/Maagic7/PureBasicFra ... VECTORf.pb
It is possible to speed up this agian, if you write functions wich converts a complete Image in a Loop. This will save time by eliminating
a function call for each pixel.
As I said, I'm working on that stuff and it will be become part of the 2 Modules VectorColor and Image.
If you are able to make a ready solution from this, please let me know, than I will integrate it in the PureBasicFrameWork project!
Re: HSL/HSV to RGB
because this direct transformation was new to me, i converted it to Purebasic.
But untested. Maybe anyone will write a test code!
For testing the principal function this will be o.k.
But for on the fly caclulations of complete images we can eliminate a lot of multiplications, if we
precalculate the transformation Matrix.
Updated 2023/09/07, it should have a limit check at 255
But untested. Maybe anyone will write a test code!
For testing the principal function this will be o.k.
But for on the fly caclulations of complete images we can eliminate a lot of multiplications, if we
precalculate the transformation Matrix.
Updated 2023/09/07, it should have a limit check at 255
Code: Select all
Procedure.l HSVadjustRBG(RGB.l, h.f, s.f, v.f)
; ======================================================================
; NAME : HSVadjustRBG
; DESC : Do a HSV-Color Space adjust at a RGB color of 24/32 Bit
; DESC : it will keep the original Alpha
; VAR(RGB.l) : 24/32 Bit RGB Color
; VAR(h.f) : Hue shift (in degrees) [0..360]
; VAR(s.f) : saturation multiplier (scalar)
; VAR(v.f) : value multiplier (scalar)
; RET.l : The HSV adjusted color as RGB-Color-Value
; ======================================================================
Protected.f vsu, vsw
Protected.f r, g, b
Protected.a A ; Alpha value
r = Red(RGB)
g = Green(RGB)
b = Blue(RGB)
A = Alpha(RGB)
vsu = v * s * Cos(Radian(h))
vsw = v * s * Sin(Radian(h))
r = (0.299*v + 0.701*vsu + 0.168*vsw) * r + (0.587*v - 0.587*vsu + 0.330*vsw) * g + (0.114*v - 0.114*vsu - 0.497*vsw) * b
g = (0.299*v - 0.299*vsu - 0.328*vsw) * r + (0.587*v + 0.413*vsu + 0.035*vsw) * g + (0.114*v - 0.114*vsu + 0.292*vsw) * b
b = (0.299*v - 0.300*vsu + 1.250*vsw) * r + (0.587*v - 0.588*vsu - 1.050*vsw) * g + (0.114*v + 0.886*vsu - 0.203*vsw) * b
If r > 255
r = 255
ElseIf r < 0
r = 0
EndIf
If g > 255
g = 255
ElseIf g < 0
g = 0
EndIf
If b > 255
b = 255
ElseIf b < 0
b = 0
EndIf
ProcedureReturn RGBA(Int(r), Int(g), Int(b), A)
EndProcedure
Re: HSL/HSV to RGB
On this page
https://stackoverflow.com/questions/131 ... conversion
there's a fast procedure for hsl to rgb.
The only issue is that the input values for hue, saturation and lightness are all in range [0, 255] which is not very common.
Usually hue is in range [0, 360] and saturation and lightness in range [0, 100].
https://stackoverflow.com/questions/131 ... conversion
there's a fast procedure for hsl to rgb.
The only issue is that the input values for hue, saturation and lightness are all in range [0, 255] which is not very common.
Usually hue is in range [0, 360] and saturation and lightness in range [0, 100].
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: HSL/HSV to RGB
Using Integer calculation might be a good way to speed up some %!
here a short calculation how many operations has a full HD 1920x180 = 2.073.600 = 2.1 e+06 Pixel
with the direct transformation HSVadjustRBG
we have 36 multiplications + 24 add/sub + a few compare for each pixel
36*2.1 = 75.6 e06 multiplications
24*2.1 = 50.4 e06 add/sub)
3*2.1 = 6.3 e06 limit checks
-----------------------------------------
132.3 e06 caluclations total per full HD picture if calling HSVadjustRBG for each pixel
With a precalcualted Matrix we can reduce the multiplications to 9 each Pixel + 27mul for the matirx (only once per picture)
9 *2.1 = 18.9 e06 Multiplications compared with 75.6 -> only 25% of multiplications! The sub/add will be the same
75.6 e06 claculations total compared with 132 e06 -> only 57% of calculations
With use of SSE typical we can speed up 4D Vector operations with a factor of 4. At 2D Pixel were we use only 3D Vectors
this will be arraund factor 3. So with SSE I estimate a total amount of calculations from 75.6 e06 /3 = 25.2 e06
now we compare SSE Version when calcualting all pixels in a loop wit the basic version of calling the function HSVadjustRBG for every pixel.
132 e06 -> 25.2 e06 -> 19% of Speed what means a factor of 5 faster.
If we estimate 4 CPU ticks for each calculation, incl. load and save intstructions (modern CPU can do 2 operations per tick).
We need 100 e06 CPU ticks for 1 full HD Picture. So per each GHz = 4 Pictures in a second. -> 3.5GhZ = 14fps for Full HD
So I guess for 'on the fly caclculation' of complete Screens it is obligatory to use SSE Vector commands! Otherwise it will be to slow!
If using 256Bit YMM registers instead of 128Bit XMM Registers it will be possible to caclculate 2 Pixels at same time what will double speed it
again. What means ~28fps. (with a singel thread)
here a short calculation how many operations has a full HD 1920x180 = 2.073.600 = 2.1 e+06 Pixel
with the direct transformation HSVadjustRBG
we have 36 multiplications + 24 add/sub + a few compare for each pixel
36*2.1 = 75.6 e06 multiplications
24*2.1 = 50.4 e06 add/sub)
3*2.1 = 6.3 e06 limit checks
-----------------------------------------
132.3 e06 caluclations total per full HD picture if calling HSVadjustRBG for each pixel
With a precalcualted Matrix we can reduce the multiplications to 9 each Pixel + 27mul for the matirx (only once per picture)
9 *2.1 = 18.9 e06 Multiplications compared with 75.6 -> only 25% of multiplications! The sub/add will be the same
75.6 e06 claculations total compared with 132 e06 -> only 57% of calculations
With use of SSE typical we can speed up 4D Vector operations with a factor of 4. At 2D Pixel were we use only 3D Vectors
this will be arraund factor 3. So with SSE I estimate a total amount of calculations from 75.6 e06 /3 = 25.2 e06
now we compare SSE Version when calcualting all pixels in a loop wit the basic version of calling the function HSVadjustRBG for every pixel.
132 e06 -> 25.2 e06 -> 19% of Speed what means a factor of 5 faster.
If we estimate 4 CPU ticks for each calculation, incl. load and save intstructions (modern CPU can do 2 operations per tick).
We need 100 e06 CPU ticks for 1 full HD Picture. So per each GHz = 4 Pictures in a second. -> 3.5GhZ = 14fps for Full HD
So I guess for 'on the fly caclculation' of complete Screens it is obligatory to use SSE Vector commands! Otherwise it will be to slow!
If using 256Bit YMM registers instead of 128Bit XMM Registers it will be possible to caclculate 2 Pixels at same time what will double speed it
again. What means ~28fps. (with a singel thread)
Re: HSL/HSV to RGB
Just had an idea to make a quick speed test.
My Ryzen 5700 need for 1 Full HD Picture ~ 540Mil ticks when calling HSVadjustRBG() for each pixel.
That means ~7fps with the slowest version. With 128Bit SSE Vector commands I estimate ~21fps and with 256Bit SSE 42fps.
That's ~50% faster as my calculation bevor!
But a very strange behavior.
Float/ Int
240 / 160 Mio , 126 / 80ms: new Intel I7 8565U (Laptop Win10)
540 / 300 Mio , 142 / 80ms : Ryzen 5800X (Dektop Win 10))
780 / 370 Mio, 202 / 110 ms : old Intel I7 Laptop (2016, Win7) :
970 / 650 Mio : old AMD Laptop (2011, Win7)
Seems to be new Intel I7 has much faster floting point unit (or a bug in RuntimeCounter)
From this test I guess with fixed point integer it is possible to speed up a lot at AMD and Intel
UDATE: when adding time measuring and frequency calculation, it is clear!
The new Intel I7 isn't faster. It use 1.9MHz and internal double it for the CPU kernel.
UPDATE 2023/09/09 with SSE Version
Download additional Modules form Github
GitHub. https://github.com/Maagic7/PureBasicFra ... in/Modules
"PbFw_Module_PbFw.pb"
"PbFw_Module_Debug.pb"
"PbFw_Module_VECTORf.pb"
My Ryzen 5700 need for 1 Full HD Picture ~ 540Mil ticks when calling HSVadjustRBG() for each pixel.
That means ~7fps with the slowest version. With 128Bit SSE Vector commands I estimate ~21fps and with 256Bit SSE 42fps.
That's ~50% faster as my calculation bevor!
But a very strange behavior.
Float/ Int
240 / 160 Mio , 126 / 80ms: new Intel I7 8565U (Laptop Win10)
540 / 300 Mio , 142 / 80ms : Ryzen 5800X (Dektop Win 10))
780 / 370 Mio, 202 / 110 ms : old Intel I7 Laptop (2016, Win7) :
970 / 650 Mio : old AMD Laptop (2011, Win7)
Seems to be new Intel I7 has much faster floting point unit (or a bug in RuntimeCounter)
From this test I guess with fixed point integer it is possible to speed up a lot at AMD and Intel
UDATE: when adding time measuring and frequency calculation, it is clear!
The new Intel I7 isn't faster. It use 1.9MHz and internal double it for the CPU kernel.
UPDATE 2023/09/09 with SSE Version
Download additional Modules form Github
GitHub. https://github.com/Maagic7/PureBasicFra ... in/Modules
"PbFw_Module_PbFw.pb"
"PbFw_Module_Debug.pb"
"PbFw_Module_VECTORf.pb"
Code: Select all
EnableExplicit
XIncludeFile "..\..\Modules\PbFw_Module_VECTORf.pb" ; VECf:: single precision Vector Modul
Procedure.q ReadRuntimeCounter() ; RDTSC
; ======================================================================
; NAME: ReadRuntimeCounter
; DESC: Reads the CPU Runtime Counter
; DESC: A counter incremented +1 at each CPU cycle
; RET.q : CPU ticks counted with the CPU's operating frequency
; ======================================================================
CompilerIf #PB_Compiler_Backend=#PB_Backend_C
; ----------------------------------------------------------------------
; C-Backend
; ----------------------------------------------------------------------
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64 Or #PB_Compiler_Processor = #PB_Processor_x86
Protected t.q
!unsigned hi, lo;
!__asm__ __volatile__ ("lfence\n rdtsc\n lfence" : "=a"(lo), "=d"(hi));
!v_t =((unsigned long long)lo)|(((unsigned long long)hi)<<32 );
ProcedureReturn t
CompilerElseIf #PB_Compiler_Processor = #PB_Processor_Arm64 Or #PB_Compiler_Processor = #PB_Processor_Arm32
; ARM x32/x64
Protected pmuseren.l,pmcntenset.l,pmccntr.l;
!asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r"(v_pmuseren));
If pmuseren & 1
!asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(v_pmcntenset));
If pmcntenset & $80000000
!asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(v_pmccntr));
t = pmccntr
ProcedureReturn t << 6
EndIf
EndIf
CompilerEndIf
CompilerElse
; ----------------------------------------------------------------------
; ASM-Backend x64 / x32
; ----------------------------------------------------------------------
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
DisableDebugger
; RDTSC transfers TimeStampCounter to EDX, EAX (on x32 and x 64)
!RDTSC
; on x64 a Quad is returned as RAX, so we have to combine hi and lo in RAX
!SHL RDX, 32 ; EDX to RDX_Hi
!OR RAX, RDX
ProcedureReturn
EnableDebugger
CompilerElse ; x32
DisableDebugger
; RDTSC transfers TimeStampCounter to EDX, EAX (on x32 and x 64)
!RDTSC
; on x32 a Quad is returned as EDX, EAX
ProcedureReturn ; return the TimeStampCounter [EDX, EAX} on x32 [RAX] on x64
EnableDebugger
CompilerEndIf
CompilerEndIf
EndProcedure
Procedure.q ElapsedMicroSeconds()
Protected v.Quad, f.Quad
QueryPerformanceFrequency_(f)
QueryPerformanceCounter_(v)
ProcedureReturn (v\q / (f\q /1e6) ) ; normalize value to MicroSeconds : 1e6 = 1.000.000 = 1Mhz
EndProcedure
Procedure.l HSVadjustRBG(RGB.l, h.f, s.f, v.f)
; ======================================================================
; NAME : HSVadjustRBG
; DESC : Do a HSV-Color Space adjust at a RGB color of 24/32 Bit
; DESC : it will keep the original Alpha
; VAR(RGB.l) : 24/32 Bit RGB Color
; VAR(h.f) : Hue shift (in degrees) [0..360]
; VAR(s.f) : saturation multiplier (scalar)
; VAR(v.f) : value multiplier (scalar)
; RET.l : The HSV adjusted color as RGB-Color-Value
; ======================================================================
Protected.f vsu, vsw
Protected.f r, g, b
Protected.a A ; Alpha value
r = Red(RGB)
g = Green(RGB)
b = Blue(RGB)
A = Alpha(RGB)
vsu = v * s * Cos(Radian(h))
vsw = v * s * Sin(Radian(h))
r = (0.299*v + 0.701*vsu + 0.168*vsw) * r + (0.587*v - 0.587*vsu + 0.330*vsw) * g + (0.114*v - 0.114*vsu - 0.497*vsw) * b
g = (0.299*v - 0.299*vsu - 0.328*vsw) * r + (0.587*v + 0.413*vsu + 0.035*vsw) * g + (0.114*v - 0.114*vsu + 0.292*vsw) * b
b = (0.299*v - 0.300*vsu + 1.250*vsw) * r + (0.587*v - 0.588*vsu - 1.050*vsw) * g + (0.114*v + 0.886*vsu - 0.203*vsw) * b
If r > 255
r = 255
ElseIf r < 0
r = 0
EndIf
If g > 255
g = 255
ElseIf g < 0
g = 0
EndIf
If b > 255
b = 255
ElseIf b < 0
b = 0
EndIf
ProcedureReturn RGBA(Int(r), Int(g), Int(b), A)
EndProcedure
Structure M3
m11.f : m12.f : m13.f
m21.f : m22.f : m23.f
m31.f : m32.f : m33.f
EndStructure
Procedure.i Get_HSVadjustRGB_Matrix (*m.M3, h.f, s.f, v.f)
Protected.f vsu, vsw
vsu = v * s * Cos(Radian(h))
vsw = v * s * Sin(Radian(h))
With *m
\m11 = 0.299*v + 0.701*vsu + 0.168*vsw
\m12 = 0.587*v - 0.587*vsu + 0.330*vsw
\m13 = 0.114*v - 0.114*vsu - 0.497*vsw
\m21 = 0.299*v - 0.299*vsu - 0.328*vsw
\m22 = 0.587*v + 0.413*vsu + 0.035*vsw
\m23 = 0.114*v - 0.114*vsu + 0.292*vsw
\m31 = 0.299*v - 0.300*vsu + 1.250*vsw
\m32 = 0.587*v - 0.588*vsu - 1.050*vsw
\m33 = 0.114*v + 0.886*vsu - 0.203*vsw
EndWith
ProcedureReturn *m
EndProcedure
Procedure.i Get_HSVadjustRBG_VecMatrix (*m.VECf::TMatrix, h.f, s.f, v.f)
Protected.f vsu, vsw
vsu = v * s * Cos(Radian(h))
vsw = v * s * Sin(Radian(h))
With *m
\m11 = 0.299*v + 0.701*vsu + 0.168*vsw
\m12 = 0.587*v - 0.587*vsu + 0.330*vsw
\m13 = 0.114*v - 0.114*vsu - 0.497*vsw
;\m14 = 0
\m21 = 0.299*v - 0.299*vsu - 0.328*vsw
\m22 = 0.587*v + 0.413*vsu + 0.035*vsw
\m23 = 0.114*v - 0.114*vsu + 0.292*vsw
;\m24 = 0
\m31 = 0.299*v - 0.300*vsu + 1.250*vsw
\m32 = 0.587*v - 0.588*vsu - 1.050*vsw
\m33 = 0.114*v + 0.886*vsu - 0.203*vsw
\m34 = 0
;\m41 = 0
;\m42 = 0
;\m43 = 0
;\m44 = 0
EndWith
ProcedureReturn *m
EndProcedure
Procedure.l HSVadjustRBG_MX(RGB.l, *Matrix.M3)
; ======================================================================
; NAME : HSVadjustRBG_MX
; DESC : Do a HSV-Color Space adjust at a RGB color of 24/32 Bit
; DESC : with Matrix caclulation.
; VAR(RGB.l) : 24/32 Bit RGB Color
; VAR(m.M3) : Matrix
; RET.l : The HSV adjusted color as RGB-Color-Value
; ======================================================================
Protected.f vsu, vsw
Protected.f r, g, b
r = Red(RGB)
g = Green(RGB)
b = Blue(RGB)
;( V 0 0 )
;( 0 VSU -VSW )
;( 0 VSW -VSU )
; m11 = 0.299*v + 0.701*vsu + 0.168*vsw
; m12 = 0.587*v - 0.587*vsu + 0.330*vsw
; m13 = 0.114*v - 0.114*vsu - 0.497*vsw
; m21 = 0.299*v - 0.299*vsu - 0.328*vsw
; m22 = 0.587*v + 0.413*vsu + 0.035*vsw
; m23 = 0.114*v - 0.114*vsu + 0.292*vsw
; m31 = 0.299*v - 0.300*vsu + 1.250*vsw
; m32 = 0.587*v - 0.588*vsu - 1.050*vsw
; m33 = 0.114*v + 0.886*vsu - 0.203*vsw
If *Matrix
With *Matrix
r = m11 * r + m12 * g + m13 * b
g = m21 * r + m22 * g + m23 * b
b = m31 * r + m32 * g + m33 * b
EndWith
If r > 255
r = 255
ElseIf r < 0
r = 0
EndIf
If g > 255
g = 255
ElseIf g < 0
g = 0
EndIf
If b > 255
b = 255
ElseIf b < 0
b = 0
EndIf
EndIf
ProcedureReturn RGBA(Int(r), Int(g), Int(b), Alpha(RGB))
EndProcedure
Procedure.l HSVadjustRBG_SSE(RGB.l, *Matrix.VECf::TMatrix)
; ======================================================================
; NAME : HSVadjustRBG_SSE
; DESC : Do a HSV-Color Space adjust at a RGB color of 24/32 Bit
; DESC : with Matrix caclulation.
; VAR(RGB.l) : 24/32 Bit RGB Color
; VAR(m.M3) : Matrix
; RET.l : The HSV adjusted color as RGB-Color-Value
; ======================================================================
Protected.f vsu, vsw
Protected IN.VECf::TVector
Protected OUT.VECf::TVector
; Protected *OUT.VECf::TVector = @OUT
; Protected *IN.VECf::TVector = @IN
With IN
\x = Red(RGB)
\y = Green(RGB)
\z = Blue(RGB)
EndWith
VECf::Vector_X_Matrix(Out, IN, *Matrix)
; ASM_Vector_X_Matrix(RAX, RDX, RCX)
With OUT
If \x > 255
\x = 255
ElseIf \x < 0
\x = 0
EndIf
If \y > 255
\y = 255
ElseIf \y < 0
\y = 0
EndIf
If \z > 255
\z = 255
ElseIf \z < 0
\z = 0
EndIf
EndWith
ProcedureReturn RGBA(Int(OUT\x), Int(OUT\y), Int(OUT\z), Alpha(RGB))
EndProcedure
EnableExplicit
Define.q ticks1, ticks2, ticks3, ticks4
Define.q time1, time2, time3, time4
Define.i I
Define.l col, newcol
Define.s msg
col = RGB(120, 200, 99)
#Pixels = 1920*1080
; --------------------------------------------------------
; Classic Version for ajustting 1 Pixel (Matrix caclulation included)
time1 = ElapsedMicroSeconds()
ticks1 = ReadRuntimeCounter()
For I = 1 To #Pixels
newCol = HSVadjustRBG(col, 33, 1.1, 0.7)
Next
ticks1 = ReadRuntimeCounter() - ticks1
time1 = ElapsedMicroSeconds() - time1
; --------------------------------------------------------
; Classic Version with precaculated Matrix
; this is much faster if adjusting more Pixels with same Parameters
Define hsvMatrix.M3
time2 = ElapsedMicroSeconds()
ticks2 = ReadRuntimeCounter()
Get_HSVadjustRGB_Matrix(hsvMatrix, 33, 1.1, 0.7)
For I = 1 To #Pixels
newCol = HSVadjustRBG_MX(col, hsvMatrix)
Next
ticks2 = ReadRuntimeCounter() - ticks2
time2 = ElapsedMicroSeconds() - time2
; --------------------------------------------------------
Define VecMatrix.VECf::TMatrix
time3 = ElapsedMicroSeconds()
ticks3 = ReadRuntimeCounter()
Get_HSVadjustRBG_VecMatrix(VecMatrix, 33, 1.1, 0.7)
For I = 1 To #Pixels
newCol = HSVadjustRBG_SSE(col, VecMatrix)
Next
ticks3 = ReadRuntimeCounter() - ticks3
time3 = ElapsedMicroSeconds() - time3
msg = "Classic Float version: ticks = " + Str(ticks1 / 1e6) + " Mio ; " + StrF(time1/1000,1) + "ms ; " + Str(ticks1/time1) + " MHz" + #CRLF$
msg + "Classic Matrix version: ticks = " + Str(ticks2 / 1e6) + " Mio ; " + StrF(time2/1000,1) + "ms ; " + Str(ticks2/time2) + " MHz" + #CRLF$
msg + "SSE-VEC-Matrix version: ticks = " + Str(ticks3 / 1e6) + " Mio ; " + StrF(time3/1000,1) + "ms ; " + Str(ticks3/time3) + " MHz"
SetClipboardText(msg)
MessageRequester("CPU Ticks of HSVadjustRBG of a FullHD Picture = ", msg , #PB_MessageRequester_Info)
; Float/ Int
; 240/160 Mio , 126/ 80ms: new Intel I7 8565U (Laptop Win10)
; 540/300 Mio , 142/ 80ms: Ryzen 5800X (Dektop Win 10))
; 780/370 Mio , 202/110ms: old Intel I7 Laptop (2016, Win7)
; 970/650 Mio : old AMD Laptop (2011, Win7)
Last edited by SMaag on Sat Sep 09, 2023 2:52 pm, edited 4 times in total.
Re: HSL/HSV to RGB
Again, thanks to all.
I think It also would be interesting how to implement "superfast color tables" to apply e.g. to the Z dimension of 3D graphs...
PS: for example, there's a system app called "Grapher" on Mac that does stuff... in theory you can even make animations... but it works very %$#@& (Monterey)...............................
I think It also would be interesting how to implement "superfast color tables" to apply e.g. to the Z dimension of 3D graphs...
PS: for example, there's a system app called "Grapher" on Mac that does stuff... in theory you can even make animations... but it works very %$#@& (Monterey)...............................
Re: HSL/HSV to RGB
Hi, there,
I've arrived a little after the battle
But, below, if needed, the procedures used by PB that can be found in the Purebasic IDE source code:
HSV to RGB :
HSL to RGB :
Hue to RGB :
I've arrived a little after the battle
But, below, if needed, the procedures used by PB that can be found in the Purebasic IDE source code:
HSV to RGB :
Code: Select all
Procedure HSVToRGB(h.f,s.f,v.f)
Protected.f i,f,p,q,t
Protected.f r,g,b
; make sure it is always less than 360, else we get black
h=Mod(h,360.0)
If s=0
r=v
g=v
b=v
Else
h/60.0
i=Round(h,0)
f=h-i
p=v*(1.0-s)
q=v*(1.0-s*f)
t=v*(1.0-s*(1.0-f))
Select i
Case 0:r=v:g=t:b=p
Case 1:r=q:g=v:b=p
Case 2:r=p:g=v:b=t
Case 3:r=p:g=q:b=v
Case 4:r=t:g=p:b=v
Case 5:r=v:g=p:b=q
EndSelect
EndIf
ProcedureReturn RGB(Int(r*255),Int(g*255),Int(b*255))
EndProcedure
HSL to RGB :
Code: Select all
Procedure.f HSLToRGBComponent(q1.f,q2.f,h.f)
If h>=360.0
h-360.0
ElseIf h<0.0
h+360.0
EndIf
If h<60.0
ProcedureReturn q1+(q2-q1)*h/60.0
ElseIf h<180.0
ProcedureReturn q2
ElseIf h<240.0
ProcedureReturn q1+(q2-q1)*(240.0-h)/60.0
Else
ProcedureReturn q1
EndIf
EndProcedure
;
Procedure HSLToRGB(h.f,s.f,l.f)
Protected.f p1,p2
Protected.f r,g,b
; make sure it is always less than 360, else we get black
h=Mod(h,360.0)
If l<=0.5
p2=l*(1.0+s)
Else
p2=l+s-l*s
EndIf
p1=2.0*l-p2
r=HSLToRGBComponent(p1,p2,h+120)
g=HSLToRGBComponent(p1,p2,h)
b=HSLToRGBComponent(p1,p2,h-120)
ProcedureReturn RGB(Int(r*255),Int(g*255),Int(b*255))
EndProcedure
Hue to RGB :
Code: Select all
Procedure HueToRGB(h.f)
Protected.f r, g, b
; make sure it is always less than 360, else we get black
h = Mod(h, 360.0)
If h < 60
r = 1
g = h / 60
b = 0
ElseIf h < 120
r = 1 - (h - 60) / 60
g = 1
b = 0
ElseIf h < 180
r = 0
g = 1
b = (h - 120) / 60
ElseIf h < 240
r = 0
g = 1 - (h - 180) / 60
b = 1
ElseIf h < 300
r = (h - 240) / 60
g = 0
b = 1
Else
r = 1
g = 0
b = 1 - (h - 300) / 60
EndIf
ProcedureReturn RGB(Int(r * 255), Int(g * 255), Int(b * 255))
EndProcedure
If my English syntax and lexicon are incorrect, please bear with Google translate and DeepL. They rarely agree with each other!
Except on this sentence...
Except on this sentence...
Re: HSL/HSV to RGB
Result of new Test with SSE Vector Matrix version for full HD.
Classic Float version: ticks = 556 Mio ; 146.4ms ; 3799 MHz
Classic Matrix version: ticks = 388 Mio ; 102.2ms ; 3799 MHz
SSE-VEC-Matrix version: ticks = 258 Mio ; 68.0ms ; 3799 MHz
My SSE version is not 100% optimized for the ColorSpace use.! There are some possiblities to optimize and speed up again!
I can't not post the complete Code for the SSE! It's to much!
It use a few external modules form PureBasic Framework. If you want to test it, download the additional modules!
I update my Testcode from the previous post! See there how to get the Code
My test ist just a timing test. I did't test it with real images to see the correct function!
Did anyone of you wrote a test code with a real Image, to see the correct function?
Classic Float version: ticks = 556 Mio ; 146.4ms ; 3799 MHz
Classic Matrix version: ticks = 388 Mio ; 102.2ms ; 3799 MHz
SSE-VEC-Matrix version: ticks = 258 Mio ; 68.0ms ; 3799 MHz
My SSE version is not 100% optimized for the ColorSpace use.! There are some possiblities to optimize and speed up again!
I can't not post the complete Code for the SSE! It's to much!
It use a few external modules form PureBasic Framework. If you want to test it, download the additional modules!
I update my Testcode from the previous post! See there how to get the Code
My test ist just a timing test. I did't test it with real images to see the correct function!
Did anyone of you wrote a test code with a real Image, to see the correct function?
Re: HSL/HSV to RGB
The transform matrix seems to work fine with a real image but I tried it with my own code.SMaag wrote: Sat Sep 09, 2023 2:32 pmDid anyone of you wrote a test code with a real Image, to see the correct function?
I precalculate the transform matrix and am using SSE2 integer math for the matrix multiplication.
I also am doing all pixels in one loop so no function calls for each pixel.
With this approach a HSV transform on a 1920x1080 pixel image on my computer takes about 4 ms.
Windows (x64)
Raspberry Pi OS (Arm64)
Raspberry Pi OS (Arm64)
Re: HSL/HSV to RGB
only 4ms for Full HD what is about 2Mio Pixels. How are you doing that???With this approach a HSV transform on a 1920x1080 pixel image on my computer takes about 4 ms.
I tested my SSE Code again and optimized it. But the effect is only 2ms. The SSE calculation itself needs aprox. 60ms, the complete rest 6ms.
can you post your code,?
here is my SSE Code for Vectror * Matrix
it needs about 60ms for 2Mio calls on a Ryzen 5800X at 3.8Ghz
Code: Select all
Procedure.i Vector_X_Matrix(*OUT.TVector, *IN.TVector, *Matrix.TMatrix)
; translated from the FreePascal Wiki at https://wiki.freepascal.org/SSE/de
!MOV REGD, [p.p_IN] ; load Adress of IN.VEctor
!MOV REGA, [p.p_Matrix] ; load Adress of Matrix
;!MOVUPS XMM2, [REGD]
!MOVLPS XMM2, [REGD] ; split 128Bit MOVUPS to 2x 64 Bit MOVLPS, MOVHPS. It's faster because of unaligned Memory
!MOVHPS XMM2, [REGD+8] ; a modern CPU do 2 64Bit load/save parallel
; we use Shuffle command and vertical Add instead of horizontal Add, because Shuffle it's faster
; Line 0
!PSHUFD XMM0, XMM2, 00000000b
;!MOVUPS XMM3, [REGA + $00]
!MOVLPS XMM3, [REGA + $00]
!MOVHPS XMM3, [REGA + $08]
!MULPS XMM0, XMM3
; Line 1
!PSHUFD XMM1, XMM2, 01010101b
;!MOVUPS XMM3, [REGA + $10]
!MOVLPS XMM3, [REGA + $10]
!MOVHPS XMM3, [REGA + $18]
!MULPS XMM1, XMM3
!ADDPS XMM0, XMM1
; Line 2
!PSHUFD XMM1, XMM2, 10101010b
;!MOVUPS XMM3, [REGA + $20]
!MOVLPS XMM3, [REGA + $20]
!MOVHPS XMM3, [REGA + $28]
!MULPS XMM1, XMM3
!ADDPS XMM0, XMM1
; Line 3
!PSHUFD XMM1, XMM2, 11111111b
;!MOVUPS XMM3, [REGA + $30]
!MOVLPS XMM3, [REGA + $30]
!MOVHPS XMM3, [REGA + $38]
!MULPS XMM1, XMM3
!ADDPS XMM0, XMM1
; Return Result
!MOV REGA, [p.p_OUT]
!MOVUPS [REGA], XMM0
EndProcedure


