ennixo
asked on
Radial Blur Zoom
Hi, i programmed a function to radial blur (zoom) pictures in Vb6 (with a force from zero to 100% and a point of blur), it works well (better quality than photoshop) but it's a little slower.
my function is easy and i would like to know how to accelerate the process to get the same quality faster
i need a vb6 or C++ function.
here's my function :
'cx, cy = Center X and Center Y
'k = Force (0 to 100%)
'Quality = Quality : 1 = Best | 2 = Good | 4 = Medium | 16 = Bad
Public Sub RadialBlurZoom(ByVal cx As Long, ByVal cy As Long, ByVal k As Single, ByVal Quality as Long)
Dim j As Long
Dim i As Long
Dim l As Long
Dim nX As Long
Dim nY As Long
Dim dX As Long
Dim dY As Long
Dim Alpha As Single
Dim Hypotenuse As Long
Dim vMax As Long
Dim TotalR As Long
Dim TotalG As Long
Dim TotalB As Long
Dim Dividor As Long
Dim NewBits() As Byte
'in the form, PicBits is a private array which contains bitmapbits (from GetBitmapBits)
ReDim NewBits(LBound(PicBits) To UBound(PicBits))
If K = 0 Then K = 1
If K > 100 Then K = 100
K = K / 400
'shpSelection is a Shape which contains the rectangle area to be processed
For j = shpSelection.Top + 1 To shpSelection.Top + shpSelection.Height
dY = Abs(j - cY)
For i = shpSelection.Left + 1 To shpSelection.Left + shpSelection.Width
dX = Abs(i - cX)
If dX = 0 Then dX = 1
Alpha = Atn(dY / dX)
Hypotenuse = Sqr(dX * dX + dY * dY)
TotalR = 0
TotalG = 0
TotalB = 0
Dividor = 0
vMax = Hypotenuse * K
For l = -vMax To vMax Step Quality
If i < cX Then
nX = i + (Cos(Alpha) * l)
ElseIf i >= cX Then
nX = i - (Cos(Alpha) * l)
Else
nX = 0
End If
If j < cY Then
nY = j + (Sin(Alpha) * l)
ElseIf j >= cY Then
nY = j - (Sin(Alpha) * l)
Else
nY = 0
End If
'in this form, Matrix is a private array which contains indexes of
'bits in PicBits to retrieve a point with X and Y values.
If nX > 0 And nY > 0 And nX <= UBound(Matrix) And nY <= UBound(Matrix, 2) Then
TotalR = TotalR + PicBits(Matrix(nX, nY))
TotalG = TotalG + PicBits(Matrix(nX, nY) + 1)
TotalB = TotalB + PicBits(Matrix(nX, nY) + 2)
Dividor = Dividor + 1
End If
Next l
If Dividor > 0 Then
NewBits(Matrix(i, j)) = TotalR \ Dividor
NewBits(Matrix(i, j) + 1) = TotalG \ Dividor
NewBits(Matrix(i, j) + 2) = TotalB \ Dividor
Else
NewBits(Matrix(i, j)) = PicBits(Matrix(i, j))
NewBits(Matrix(i, j) + 1) = PicBits(Matrix(i, j) + 1)
NewBits(Matrix(i, j) + 2) = PicBits(Matrix(i, j) + 2)
End If
Next i
Next j
'P is the name of a pictureBox where the picture was loaded
'sets the new bits to P.Image
SetBitmapBits P.Image, UBound(NewBits), NewBits(1)
End Function
my function is easy and i would like to know how to accelerate the process to get the same quality faster
i need a vb6 or C++ function.
here's my function :
'cx, cy = Center X and Center Y
'k = Force (0 to 100%)
'Quality = Quality : 1 = Best | 2 = Good | 4 = Medium | 16 = Bad
Public Sub RadialBlurZoom(ByVal cx As Long, ByVal cy As Long, ByVal k As Single, ByVal Quality as Long)
Dim j As Long
Dim i As Long
Dim l As Long
Dim nX As Long
Dim nY As Long
Dim dX As Long
Dim dY As Long
Dim Alpha As Single
Dim Hypotenuse As Long
Dim vMax As Long
Dim TotalR As Long
Dim TotalG As Long
Dim TotalB As Long
Dim Dividor As Long
Dim NewBits() As Byte
'in the form, PicBits is a private array which contains bitmapbits (from GetBitmapBits)
ReDim NewBits(LBound(PicBits) To UBound(PicBits))
If K = 0 Then K = 1
If K > 100 Then K = 100
K = K / 400
'shpSelection is a Shape which contains the rectangle area to be processed
For j = shpSelection.Top + 1 To shpSelection.Top + shpSelection.Height
dY = Abs(j - cY)
For i = shpSelection.Left + 1 To shpSelection.Left + shpSelection.Width
dX = Abs(i - cX)
If dX = 0 Then dX = 1
Alpha = Atn(dY / dX)
Hypotenuse = Sqr(dX * dX + dY * dY)
TotalR = 0
TotalG = 0
TotalB = 0
Dividor = 0
vMax = Hypotenuse * K
For l = -vMax To vMax Step Quality
If i < cX Then
nX = i + (Cos(Alpha) * l)
ElseIf i >= cX Then
nX = i - (Cos(Alpha) * l)
Else
nX = 0
End If
If j < cY Then
nY = j + (Sin(Alpha) * l)
ElseIf j >= cY Then
nY = j - (Sin(Alpha) * l)
Else
nY = 0
End If
'in this form, Matrix is a private array which contains indexes of
'bits in PicBits to retrieve a point with X and Y values.
If nX > 0 And nY > 0 And nX <= UBound(Matrix) And nY <= UBound(Matrix, 2) Then
TotalR = TotalR + PicBits(Matrix(nX, nY))
TotalG = TotalG + PicBits(Matrix(nX, nY) + 1)
TotalB = TotalB + PicBits(Matrix(nX, nY) + 2)
Dividor = Dividor + 1
End If
Next l
If Dividor > 0 Then
NewBits(Matrix(i, j)) = TotalR \ Dividor
NewBits(Matrix(i, j) + 1) = TotalG \ Dividor
NewBits(Matrix(i, j) + 2) = TotalB \ Dividor
Else
NewBits(Matrix(i, j)) = PicBits(Matrix(i, j))
NewBits(Matrix(i, j) + 1) = PicBits(Matrix(i, j) + 1)
NewBits(Matrix(i, j) + 2) = PicBits(Matrix(i, j) + 2)
End If
Next i
Next j
'P is the name of a pictureBox where the picture was loaded
'sets the new bits to P.Image
SetBitmapBits P.Image, UBound(NewBits), NewBits(1)
End Function
Maybe I can try. In case You would explain better in words what it should do.
ASKER
ok, for each pixel i compute the resulting color (function of its position, the center position and the force).
everything is calculated for one pixel, everything is calculated again for another pixel, etc...
what i would like is a function which won't recompute everything for each pixel but which will use what was already computed (when possible). this way, there will be less computes and it will be a lot faster (i think) !
but i don't really know how to implement this...
everything is calculated for one pixel, everything is calculated again for another pixel, etc...
what i would like is a function which won't recompute everything for each pixel but which will use what was already computed (when possible). this way, there will be less computes and it will be a lot faster (i think) !
but i don't really know how to implement this...
Hi.
Depending on in what range the arguments (Alpha) for your sine and cosine functions vary, you can try to make your own sine and cosine functions, based on the Taylor series. As far as I know, VB (and other programming languages) actually does the same, but it usually uses very long series. You can choose to truncate the series earlier. For example write your own functions mCos and mSin which use the following truncated Taylor series:
mCos = 1 - (1/2)*x*x + (1/24)*x*x*x*x - (1/720)*x*x*x*x*x*x
mSin = x - (1/6)*x*x*x + (1/120)* x*x*x*x*x - (1/5040) *x*x*x*x*x*x*x
These two series give pretty good values for -pi<Alpha<pi. Try to make the series even shorter and compare the results. I am also interested to know if or how much this solution improves the speed of your code. So please keep me updated if you choose to give it a try.
There are other things you can do, for example bit-shifting instead of multiplication/division by 2, and so on. I know how it works in C but I am not sure how you can do it in VB, probably the same. Ask me later if you.
Depending on in what range the arguments (Alpha) for your sine and cosine functions vary, you can try to make your own sine and cosine functions, based on the Taylor series. As far as I know, VB (and other programming languages) actually does the same, but it usually uses very long series. You can choose to truncate the series earlier. For example write your own functions mCos and mSin which use the following truncated Taylor series:
mCos = 1 - (1/2)*x*x + (1/24)*x*x*x*x - (1/720)*x*x*x*x*x*x
mSin = x - (1/6)*x*x*x + (1/120)* x*x*x*x*x - (1/5040) *x*x*x*x*x*x*x
These two series give pretty good values for -pi<Alpha<pi. Try to make the series even shorter and compare the results. I am also interested to know if or how much this solution improves the speed of your code. So please keep me updated if you choose to give it a try.
There are other things you can do, for example bit-shifting instead of multiplication/division by 2, and so on. I know how it works in C but I am not sure how you can do it in VB, probably the same. Ask me later if you.
ASKER
jamchad:
you won't believe me because i really thought mCos and mSin would accelerate the radial blur... but for the same image in the same conditions with compiled code :
Cos & Sin : 27.189 sec
mCos & mSin : 30.564 sec
i did not compare the resulting images but mSin and mCos seems to give the same result effect.
perhaps it would be faster with simpler mCos & mSin but i don't really know how to "truncate the series" more.
for bitshifting i didn't found where i could do this (no multiplication or division by 2) and i don't know how to do this in vb.
you won't believe me because i really thought mCos and mSin would accelerate the radial blur... but for the same image in the same conditions with compiled code :
Cos & Sin : 27.189 sec
mCos & mSin : 30.564 sec
i did not compare the resulting images but mSin and mCos seems to give the same result effect.
perhaps it would be faster with simpler mCos & mSin but i don't really know how to "truncate the series" more.
for bitshifting i didn't found where i could do this (no multiplication or division by 2) and i don't know how to do this in vb.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
mokule:
1.
original image :http://auchtre.free.fr/xpws/_flr_cmp_original.jpg
a radial blur (zoom) with photoshop : http://auchtre.free.fr/xpws/_flr_cmp_photoshop.jpg
a radial blur (zoom) with my algorithm : http://auchtre.free.fr/xpws/_flr_cmp_xpws.jpg
that's why i want to be faster, mine is better quality but slower.
2. GREAAAAAAT !!!!!!!
9.935 sec, same image, same conditions !!!
now it's better and faster than photoshop !!!
1.
original image :http://auchtre.free.fr/xpws/_flr_cmp_original.jpg
a radial blur (zoom) with photoshop : http://auchtre.free.fr/xpws/_flr_cmp_photoshop.jpg
a radial blur (zoom) with my algorithm : http://auchtre.free.fr/xpws/_flr_cmp_xpws.jpg
that's why i want to be faster, mine is better quality but slower.
2. GREAAAAAAT !!!!!!!
9.935 sec, same image, same conditions !!!
now it's better and faster than photoshop !!!
ASKER
even if you didn't do what i asked, i was so glad that i accepted your answer...
but if you want, you can still research to be faster & faster !
but if you want, you can still research to be faster & faster !
Well, take it into account.:)
hi!
did the quality of the image deteriorate?
these are the more truncated versions (you simply remove the last term in the polynomials)
mCos = 1 - (1/2)*x*x + (1/24)*x*x*x*x
mSin = x - (1/6)*x*x*x + (1/120)* x*x*x*x*x
may be you won't need these now any more, but who knows? may be another time! cheers.
did the quality of the image deteriorate?
these are the more truncated versions (you simply remove the last term in the polynomials)
mCos = 1 - (1/2)*x*x + (1/24)*x*x*x*x
mSin = x - (1/6)*x*x*x + (1/120)* x*x*x*x*x
may be you won't need these now any more, but who knows? may be another time! cheers.
ASKER
jamschad:
with
mCos = 1 - (1/2)*x*x + (1/24)*x*x*x*x
mSin = x - (1/6)*x*x*x + (1/120)* x*x*x*x*x
image is a little deteriorated but it is still slower (!!!?)
with
mCos = 1 - (1/2)*x*x
mSin = x - (1/6)*x*x*x
image is deteriarated a lot more but it is faster
but the deterioration can not be a "quality" because the deformation is not the same so the constraint of the effect are not respected...
but thanx ;)
with
mCos = 1 - (1/2)*x*x + (1/24)*x*x*x*x
mSin = x - (1/6)*x*x*x + (1/120)* x*x*x*x*x
image is a little deteriorated but it is still slower (!!!?)
with
mCos = 1 - (1/2)*x*x
mSin = x - (1/6)*x*x*x
image is deteriarated a lot more but it is faster
but the deterioration can not be a "quality" because the deformation is not the same so the constraint of the effect are not respected...
but thanx ;)
mCos = 1 - (1/2)*x*x + (1/24)*x*x*x*x // 6 multiplications
mSin = x - (1/6)*x*x*x + (1/120)* x*x*x*x*x // 8 multiplications
It can be optimized as follows. But I don't expect too mauch with it
y = x*x // 1 multiplication
mCos = 1 - (1/2)*y + (1/24)*y*y
mSin = x - (1/6)*x*y + (1/120)* x*y*y
further
mCos = 1 - (1/2)*y* (1 + (1/12)*y) // 3 multiplications
mSin = x - (1/6)*x*y*(1 + (1/20)*y) // 4 multiplications
mSin = x - (1/6)*x*x*x + (1/120)* x*x*x*x*x // 8 multiplications
It can be optimized as follows. But I don't expect too mauch with it
y = x*x // 1 multiplication
mCos = 1 - (1/2)*y + (1/24)*y*y
mSin = x - (1/6)*x*y + (1/120)* x*y*y
further
mCos = 1 - (1/2)*y* (1 + (1/12)*y) // 3 multiplications
mSin = x - (1/6)*x*y*(1 + (1/20)*y) // 4 multiplications
ASKER
i tried this kind of optimizations but the change is smaller than the loss.
Cos & Sin are definitively faster (i think it's because there are Cos & Sin instruction in asm so it is very fast because the processor can compute this, computing mCos & mSin needs a lot more instructions so it is slower)
Cos & Sin are definitively faster (i think it's because there are Cos & Sin instruction in asm so it is very fast because the processor can compute this, computing mCos & mSin needs a lot more instructions so it is slower)