Page 2 of 2
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 2:14 pm
by Olli
Is this bugging ?
Code: Select all
define between0and255
macro sat0n255() ; /!\ rax,rbx,rdx
! xor rax,rax
! mov rdx, 255
! xor rbx, rbx
! add rax, [v_between0and255]
! cmovl [v_between0and255],rbx
! jmp sat0n255end
! cmp rax,rdx
! cmova [v_between0and255],rdx
!sat0n255end:
endmacro
between0and255 = 300
sat0n255()
debug between0and255
between0and255 = 10
sat0n255()
debug between0and255
between0n255 = -1
sat0n255()
debug between0and255
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 2:23 pm
by RASHAD
It may help
Code: Select all
Procedure Min(n1,n2)
!mov eax,dword[p.v_n1]
!cmp eax,dword[p.v_n2]
!cmovnl eax,dword[p.v_n2] ;for i686 (PentiumPro) and above only
ProcedureReturn
EndProcedure
Debug Min(2,255)
Debug Min(256,255)
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 2:38 pm
by Olli
yes, I give a code to test, imagining you have a x64...
X86/x64 switch can be integrated, one time there is no bug : this changes so the understanding of the code !
And CMOVcc ASM instruction compatibility can be checked too. But it is useful in the pre-compiling step...
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 3:05 pm
by Olli
Result : CMOVcc stays useless
Code: Select all
define x
goto start
limit:
! cmp [p.v_x], 0
! jg upto0
! mov [p.v_x], 0
return
!upto0:
! cmp [p.v_x], 255
! jl dnto255
! mov [p.v_x], 255
!dnto255:
return
start:
x = -1
gosub limit
debug x
x = 50
gosub limit
debug x
x = 256
gosub limit
debug x
maybe
Code: Select all
If x < 0
x = 0
elseif x > 255
x = 255
endif
[edited 4 times !]
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 4:12 pm
by Olli
AMpos wrote:My bad, the code I really need is this:
Code: Select all
define a.q, b.f
a=200: b=1.3
a=a*b
if a>255
a=255
endif
I try to modify your code, but I am unable.
I did not watch this... Follow the message of
NicTheQuick : use only floats. << X * 1.3 >> is too accurate to use an integer.
I do not think a neighbour value would be good
1/4 = 0.25
1/8 = 0.125
1/16 = 0.0625
1/4 + 1/16 = 0.3125
So
Code: Select all
Define.I N, X
Define A.D
N = 198
A = N
; this :
X = N ; multiply with 1.3125
X >> 2
N + X
X >> 2
N + X
; is slower than this :
A * 1.3
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 4:57 pm
by wilbert
The fastest way would probably to use asm SSE instructions.
the PACKUSWB instruction can convert 16 signed 16 bit values to 16 unsigned 8 bit values.
It automatically limits the 8 bit values to the range 0 - 255.
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 5:21 pm
by GPI
maybe easy to understand:
Code: Select all
Procedure Min(a,b)
ProcedureReturn (Bool(a>b)*b) | (Bool(a<b)*a)
EndProcedure
Procedure Max(a,b)
ProcedureReturn (Bool(a>b)*a) | (Bool(a<b)*b)
EndProcedure
Debug min(255,2)
Debug min(255,256)
Debug max(0,min(255, -10 ))
Debug max(0,min(255, 10 ))
Debug max(0,min(255, 2658 ))
also possible with macro
Code: Select all
Macro mMin(_a_,_b_) : (Bool((_a_)>(_b_))*(_b_)) | (Bool((_a_)<(_b_))*(_a_)) :EndMacro
Macro mMax(_a_,_b_) : (Bool((_a_)>(_b_))*(_a_)) | (Bool((_a_)<(_b_))*(_b_)) :EndMacro
Debug mMin(255,2)
Debug mMin(255,256)
Debug mMax(0,mMin(255, -10 ))
Debug mMax(0,mMin(255, 10 ))
Debug mMax(0,mMin(255, 2658 ))
but the last line would be without macro:
Code: Select all
Debug (Bool((0)>((Bool((255)>(2658))*(2658)) | (Bool((255)<(2658))*(255)) ))*(0)) | (Bool((0)<((Bool((255)>(2658))*(2658)) | (Bool((255)<(2658))*(255)) ))*((Bool((255)>(2658))*(2658)) | (Bool((255)<(2658))*(255)) ))
Edit: The Problem is, that without assembler there is no way to check a "overflow"-Cpu-Flag after the add.
but i have another solution:
Code: Select all
a.a=20
b.a=215
a=(a+b) | (Bool(a+b>255) * $FF)
Debug a
a.a=50
b.a=255
a=(a+b) | (Bool(a+b>255) * $FF)
Debug a
the big question is, what exactly you what to do, maybe there is a solution "outside the box"
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 6:38 pm
by NicTheQuick
@GPI: Did you miss the latest posts in this thread?
His main issue is multiplication with a float. And I still think that it is not a big problem clamping the value to 0..255. The thing what slows the calculation down is the convertion between integers and floats.
If you want to multiply the integer 4 with the float 1.3, the compiler first has to convert the 4 (int) to 4.0 (float). Then it does the multiplication 4.0 * 1.3 = 5.2 using its FPU. After that the value should be stored again in an integer, so it has to convert it back from 5.2 (float) to 5 (int). That all costs time.
Better use my code which first converts the 1.3 to an integer and then you can use simple calculations to get a good result using only integer arithmethics. Did you look at my example?
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 7:40 pm
by AMpos
This is the code:
-White can have any value from 0 to 255, with no decimals. It can be a float or a integer.
Code: Select all
procedure white-gamma(white)
gwhite.f=white/255
for n=0 to ALOT
If white<>255 ; ### White Point correction
r=*red\a*gwhite:If r>255:r=255:EndIf:*red\a=r
g=*green\a*gwhite:If g>255:g=255:EndIf:*green\a=g
b=*blue\a*gwhite:If b>255:b=255:EndIf:*blue\a=b
EndIf
*red+bytesperpixel: *green+bytesperpixel: *blue+bytesperpixel
next
endprocedure
As I said, the full code is here:
viewtopic.php?f=12&t=67262&hilit=GammaCorrectImage
I am adding code for White (and Black) level modify.
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 8:18 pm
by GPI
try
Code: Select all
Procedure white-gamma(white)
For n=0 To ALOT
If white<>255 ; ### White Point correction
r=*red\a * 255 / white:If r>255:*red\a =255:Else:*red\a =r:EndIf
g=*green\a * 255 / white:If g>255:*green\a=255:Else:*green\a=g:EndIf
b=*blue\a * 255 / white:If b>255:*blue\a =255:Else:*blue\a =b:EndIf
EndIf
*red+bytesperpixel: *green+bytesperpixel: *blue+bytesperpixel
Next
EndProcedure
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 8:26 pm
by Olli
Even if it not sure that this will be useful in this subject, I thank
wilbert for suggesting
packuswb which saturates exactly between two extrema : 0 and 255.
Source :
http://www.info.univ-angers.fr/~richer/ ... 253667.pdf(Google research)
(37th page)
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 9:01 pm
by Olli
We can so imagine that the image is not aligned in the memory. It is slower, but safer, to test first... After, aligning the source image will use the max of the cpu...
We can imagine too, we will work on a 128-bits range. It is slower, but reachable for few old computers... After, the owners of more recent cpu could use 256-bits range, or 512-bits range. Certainly, it will be a little bit fast...
So... AVX process suggesting...
1) copy from memory to xmm register
2) as a convert from 8 bits to 32 bits will be done, xmm internal copy *4 to 3 others xmm registers
3) AND mask to remove each digit overflow created by the 4 copyings. (near this : N000 0N00 00N0 000N, N are 8-bits range)
4) Shufflings (to get 000N 000N 000N 000N)
5) Converting from integer to single-precision float
6) Multiplying with the gamma coefficient
7) Converting from single-precision float to dword integer
8 ) Converting dword to word with saturations
9) Converting word to byte with saturations (thank you wilbert ! )
10) Shuffling (back of step #4)
11) OR mask to assembly the 4 results
12) copy from xmm register to memory
Re: If a>255: a=255?
Posted: Fri Oct 09, 2020 9:07 pm
by Olli
AVX instructions suggestings...
1: MOVUPS in the future, MOVAPS when the source image will be aligned in memory...
2 : maybe MOVD, to be confirmed
3 : ANDPS
4 : PSHUFB
5 : CVTSI2SS
6 : MULPS
7 : CVTTPS2PI
8 : PACKUSDW
9 : PACKUSWB
10 : PSHUFB
11 : ORPS
12 : MOVUPS
Now... Good luck !