If a>255: a=255?

Just starting out? Need help? Post your questions and find answers here.
AMpos
Enthusiast
Enthusiast
Posts: 128
Joined: Fri Jun 05, 2020 12:47 am

If a>255: a=255?

Post by AMpos »

Hi!

is there a faster/better method for this?

Code: Select all

a=a+b
if a>255
 a=255
endif
I want to add any valor to "a" (byte/ascii size), and any number greater than 255 crop to 255.
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 »

If a is of type Ascii, you will never be able to get a value above 255. It will always overflow. So you condition "a > 255" will never be true.

Code: Select all

b.a = 100
a.a = 200

a + b
Debug a ; shows 44
Well, it works like this without branching, and therefore the prefetching of your CPU can help to make it faster. But I never tested it. And I guess there will be an assembler instruction which can do all of this in one clock cycle:

Code: Select all

b.a = 100
a.u = 200

a = a + b

;1. version (assumes a and b were < 256 before the addition)
a = ((a >> 8) * $ff) | (a & $ff)

;2. version (works for every value of a and b)
;a = (Bool(a > 255) * $ff) | (a & $ff)

Debug a
If you make lots of these clampings you also may want to use some SSE instructions which can to 4 (or more?) of these comparisons at the same time. And when I remember right there should also be a simple ASM instruction which can set a value if a given condition is met which should also make this faster. But unfortunately I am not an Assember guru.
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 »

Yeah, I know.

If I define "a" as ascii, I will never get a value over 255, so I can't know if it was.

In my code (it is an "image color levels / gamma" ), I use this:

Code: Select all

Protected *red.Ascii, *green.Ascii, *blue.Ascii, x,y,r,g,b,gwhite.f,gblack.f
r=*red\a*gwhite:If r>255:r=255:EndIf:*red\a=r
(I am modifying viewtopic.php?f=12&t=67262&hilit=GammaCorrectImage to accept White and Black values, and need it to be as fast as possible)
User avatar
Jac de Lad
Enthusiast
Enthusiast
Posts: 106
Joined: Wed Jul 15, 2020 7:10 am
Contact:

Re: If a>255: a=255?

Post by Jac de Lad »

But if you use a single byte the outcome is different:
In the original 200+100 is 300 and shall be lowered to 255.
As a byte it is 44, like Nic said. That's not the same.

Am I wrong?
AMpos
Enthusiast
Enthusiast
Posts: 128
Joined: Fri Jun 05, 2020 12:47 am

Re: If a>255: a=255?

Post by AMpos »

If you have a byte/ascii variable, and add over 255, then it start again:

a.ascii=200+100=300, and a is really 300-256=44, so a=44

so

Code: Select all

a.ascii=200
a=a+100
if a>255
 a=255
endif
will never work as the "a.ascii" is a loop between 0 to 255.

Code: Select all

a.q=200
a=a+100
if a>255
 a=255
endif
does work.

I was asking for a faster method to do the second code, if it does exist.
User avatar
Jac de Lad
Enthusiast
Enthusiast
Posts: 106
Joined: Wed Jul 15, 2020 7:10 am
Contact:

Re: If a>255: a=255?

Post by Jac de Lad »

That's exactly what I said...
AMpos
Enthusiast
Enthusiast
Posts: 128
Joined: Fri Jun 05, 2020 12:47 am

Re: If a>255: a=255?

Post by AMpos »

Jac de Lad wrote:That's exactly what I said...
Problems of not speaking non-native language. :oops:
AMpos
Enthusiast
Enthusiast
Posts: 128
Joined: Fri Jun 05, 2020 12:47 am

Re: If a>255: a=255?

Post by AMpos »

NicTheQuick wrote:If a is of type Ascii, you will never be able to get a value above 255. It will always overflow. So you condition "a > 255" will never be true.

Code: Select all

b.a = 100
a.a = 200

a + b
Debug a ; shows 44
Well, it works like this without branching, and therefore the prefetching of your CPU can help to make it faster. But I never tested it. And I guess there will be an assembler instruction which can do all of this in one clock cycle:

Code: Select all

b.a = 100
a.u = 200

a = a + b

;1. version (assumes a and b were < 256 before the addition)
a = ((a >> 8) * $ff) | (a & $ff)

;2. version (works for every value of a and b)
;a = (Bool(a > 255) * $ff) | (a & $ff)

Debug a
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.
User avatar
Jac de Lad
Enthusiast
Enthusiast
Posts: 106
Joined: Wed Jul 15, 2020 7:10 am
Contact:

Re: If a>255: a=255?

Post by Jac de Lad »

Sorry for that. But I guess now it's clear to everyone.
User avatar
Jac de Lad
Enthusiast
Enthusiast
Posts: 106
Joined: Wed Jul 15, 2020 7:10 am
Contact:

Re: If a>255: a=255?

Post by Jac de Lad »

Btw, depending on how high the factor can be I think

Code: Select all

a=a*1.3
a=a-256*Mod(a,256)
would be safer
Not faster though...
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: If a>255: a=255?

Post by Olli »

not tested (from smartphone, sorry...)

Code: Select all

define.a a, b
a = 251
b = 6
! xor ax,ax ; reset registers
! xor bx,bx
! mov dx,65280 ; dh = 255
! mov ah, [v_a] ; input a and b values
! mov bh, [v_b]
! add ah,bh ; does the sum and updates carry flag if the result requires it
! cmovc ax,dx ; if carry is set, then ah = dh = 255
! mov [v_a], ah
debug a
Last edited by Olli on Fri Oct 09, 2020 1:42 pm, edited 1 time in total.
User avatar
Jac de Lad
Enthusiast
Enthusiast
Posts: 106
Joined: Wed Jul 15, 2020 7:10 am
Contact:

Re: If a>255: a=255?

Post by Jac de Lad »

I just realized that my solution is crap. Working but unnecessary...

If someone makes a function that could limit the top to 255 and bottom to 0 I would be very happy. I guess some of us could need that for graphics functions but I don't speak asm.
Olli
Addict
Addict
Posts: 1238
Joined: Wed May 27, 2020 12:26 pm

Re: If a>255: a=255?

Post by Olli »

Jac de Lad wrote:[...]and bottom to 0[...]
Please test asm code before, in the way it has already a bug you find. (just the version for over than 255 for now)
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 »

If you multiply an Ascii value with a Float there are many things happening in the background because numbers have to be converted between types. No wonder it is slow.
If you want to make it fast either use only Floats or only Integers but not both at the same time. You should use the format your original image data is stored with. I guess you are working with 24 or 32 bit image data and each color channel is a byte wide. Then you should definitely use integers. For your gamma problem I would suggest something like this:

Code: Select all

#IGammaShift = (SizeOf(Integer) - 2) * 8 - 1
#IGammaFactor = 1 << #IGammaShift

Define gamma.f = 1.3

;convert gamma value to integer BEFORE iterating over all the pixel values
Define iGamma.i

If gamma >= 256
	iGamma = #IGammaFactor << 8
Else
 	iGamma = gamma * #IGammaFactor
EndIf


; No iterate over the values and apply the gamma

Define a.i, ag.i

For a = 0 To 255
	ag = (a * iGamma) >> #IGammaShift
	ag = (ag | (Bool(ag > $ff) * $ff)) & $ff
	Debug "a = " + a + " -> " + ag
Next
So just precalculate `iGamma` beforehand and then do the thing in the loop for every channel and every pixel. Or try your `if` version again.
Last edited by NicTheQuick on Fri Oct 09, 2020 1:55 pm, edited 1 time in total.
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.
User avatar
Jac de Lad
Enthusiast
Enthusiast
Posts: 106
Joined: Wed Jul 15, 2020 7:10 am
Contact:

Re: If a>255: a=255?

Post by Jac de Lad »

Seems to work, for 255.

I though of a function or macro like:

Code: Select all

Procedure Limit(iData)
If iData>255:iData=255:EndIf
If iData<0:iData=0:EndIf
ProedureReturn iData
EndProcedure
...just in asm.
Post Reply