If a>255: a=255?

Just starting out? Need help? Post your questions and find answers here.
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: If a>255: a=255?

Post 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
Last edited by Olli on Fri Oct 09, 2020 2:26 pm, edited 1 time in total.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4953
Joined: Sun Apr 12, 2009 6:27 am

Re: If a>255: a=255?

Post 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)
Egypt my love
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: If a>255: a=255?

Post 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...
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: If a>255: a=255?

Post 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 !]
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: If a>255: a=255?

Post 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
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: If a>255: a=255?

Post 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.
Windows (x64)
Raspberry Pi OS (Arm64)
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Re: If a>255: a=255?

Post 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"
User avatar
NicTheQuick
Addict
Addict
Posts: 1514
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: If a>255: a=255?

Post by NicTheQuick »

@GPI: Did you miss the latest posts in this thread? :D

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?
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.
AMpos
Enthusiast
Enthusiast
Posts: 128
Joined: Fri Jun 05, 2020 12:47 am

Re: If a>255: a=255?

Post 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.
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Re: If a>255: a=255?

Post 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
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: If a>255: a=255?

Post 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)
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: If a>255: a=255?

Post 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
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: If a>255: a=255?

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