### Author Topic: RGBRotate  (Read 3596 times)

#### guga

• Moderator
• Member
• Posts: 1451
• Assembly is a state of art.
##### RGBRotate
« on: June 01, 2014, 01:51:09 PM »
This is an excellent example of rotating the hue using only matrices. It is way better transformation.

Code: [Select]

;;

http://stackoverflow.com/questions/8507885/shift-hue-of-an-rgb-color

The RGB color space describes a cube. It is possible to rotate this cube around the diagonal axis from (0,0,0) to (255,255,255)
to effect a change of hue.

Note that some of the results will lie outside of the 0 to 255 range and will need to be clipped.
I finally got a chance to code this algorithm.
It's in Python but it should be easy to translate to the language of your choice.
The formula for 3D rotation came from http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
Edit: If you saw the code I posted previously, please ignore it.
I was so anxious to find a formula for the rotation that I converted a matrix-based solution into a formula, not realizing
that the matrix was the best form all along.
I've still simplified the calculation of the matrix using the constant sqrt(1/3) for axis unit vector values,
but this is much closer in spirit to the reference and simpler in the per-pixel calculation apply as well.

def clamp(v):
if v < 0:
return 0
if v > 255:
return 255
return int(v + 0.5)

class RGBRotate(object):
def __init__(self):
self.matrix = [[1,0,0],[0,1,0],[0,0,1]]

def set_hue_rotation(self, degrees):
self.matrix[0][0] = cosA + (1.0 - cosA) / 3.0
self.matrix[0][1] = 1./3. * (1.0 - cosA) - sqrt(1./3.) * sinA
self.matrix[0][2] = 1./3. * (1.0 - cosA) + sqrt(1./3.) * sinA
self.matrix[1][0] = 1./3. * (1.0 - cosA) + sqrt(1./3.) * sinA
self.matrix[1][1] = cosA + 1./3.*(1.0 - cosA)
self.matrix[1][2] = 1./3. * (1.0 - cosA) - sqrt(1./3.) * sinA
self.matrix[2][0] = 1./3. * (1.0 - cosA) - sqrt(1./3.) * sinA
self.matrix[2][1] = 1./3. * (1.0 - cosA) + sqrt(1./3.) * sinA
self.matrix[2][2] = cosA + 1./3. * (1.0 - cosA)

def apply(self, r, g, b):
rx = r * self.matrix[0][0] + g * self.matrix[0][1] + b * self.matrix[0][2]
gx = r * self.matrix[1][0] + g * self.matrix[1][1] + b * self.matrix[1][2]
bx = r * self.matrix[2][0] + g * self.matrix[2][1] + b * self.matrix[2][2]
return clamp(rx), clamp(gx), clamp(bx)

;;

[RotationMatrix:
RotationMatrix.Data0_0: R\$ 0
RotationMatrix.Data0_1: R\$ 0
RotationMatrix.Data0_2: R\$ 0
RotationMatrix.Data1_0: R\$ 0
RotationMatrix.Data1_1: R\$ 0
RotationMatrix.Data1_2: R\$ 0
RotationMatrix.Data2_0: R\$ 0
RotationMatrix.Data2_1: R\$ 0
RotationMatrix.Data2_2: R\$ 0]

[Float_SquareRoot_OneThird: R\$ 0.577350269189625764509148780501957455647601751270126876018602] ; sqrt(1/3)

[TmpRotate.Red: R\$ 0]
[TmpRotate.Green: R\$ 0]
[TmpRotate.Blue: R\$ 0]
[TmpAngle: R\$ 0]

[TmpRotateRatio: R\$ 0]

Proc RGBRotate:
Arguments @pColorData, @Angle
Local @TmpStorage, @TmpAngle, @TmpColorRed, @TmpColorGreen, @TmpColorBlue
Uses ebx, esi

mov esi D@pColorData
lea ebx D@TmpColorRed | move D\$ebx D\$esi
lea ebx D@TmpColorGreen | move D\$ebx D\$esi
lea ebx D@TmpColorBlue | move D\$ebx D\$esi
lea ebx D@TmpStorage
movzx eax B\$esi+RGBTRIPLE.rgbtRedDis | mov D\$ebx eax | fild F\$ebx | fstp R\$TmpRotate.Red
movzx eax B\$esi+RGBTRIPLE.rgbtGreenDis | mov D\$ebx eax | fild F\$ebx | fstp R\$TmpRotate.Green
movzx eax B\$esi+RGBTRIPLE.rgbtBlueDis | mov D\$ebx eax | fild F\$ebx | fstp R\$TmpRotate.Blue

lea ebx D@TmpAngle | move D\$ebx D@Angle | fild F\$ebx | fmul R\$Degree_Radian | fstp R\$TmpAngle

R\$TmpRotateRatio = (1 - cos(R\$TmpAngle)) * R\$Float_OneThird
R\$RotationMatrix.Data0_0 = (cos(R\$TmpAngle) + R\$TmpRotateRatio); * R\$GrayRedFactor_Rec709 ; seting the gray factor keep luma while not touching saturtion
R\$RotationMatrix.Data0_1 = (R\$TmpRotateRatio - (R\$Float_SquareRoot_OneThird*sin(R\$TmpAngle))); * R\$GrayGreenFactor_Rec709
R\$RotationMatrix.Data0_2 = (R\$TmpRotateRatio + (R\$Float_SquareRoot_OneThird*sin(R\$TmpAngle))); * R\$GrayBlueFactor_Rec709

R\$RotationMatrix.Data1_0 = R\$RotationMatrix.Data0_2
R\$RotationMatrix.Data1_1 = R\$RotationMatrix.Data0_0
R\$RotationMatrix.Data1_2 = R\$RotationMatrix.Data0_1

R\$RotationMatrix.Data2_0 = R\$RotationMatrix.Data0_1
R\$RotationMatrix.Data2_1 = R\$RotationMatrix.Data0_2
R\$RotationMatrix.Data2_2 = R\$RotationMatrix.Data0_0

lea ebx D@TmpStorage
fld R\$TmpRotate.Red | fmul R\$RotationMatrix.Data0_0 | fld R\$TmpRotate.Green | fmul R\$RotationMatrix.Data0_1 | faddp ST1 ST0
fld R\$TmpRotate.Blue | fmul R\$RotationMatrix.Data0_2 | faddp ST1 ST0 | fistp F\$ebx | On D\$ebx <s 0, mov D\$ebx 0 | On D\$ebx > 255, mov D\$ebx 255 | mov eax D\$ebx | mov B\$esi+RGBTRIPLE.rgbtRedDis al

fld R\$TmpRotate.Red | fmul R\$RotationMatrix.Data1_0 | fld R\$TmpRotate.Green | fmul R\$RotationMatrix.Data1_1 | faddp ST1 ST0
fld R\$TmpRotate.Blue | fmul R\$RotationMatrix.Data1_2 | faddp ST1 ST0 | fistp F\$ebx | On D\$ebx <s 0, mov D\$ebx 0 | On D\$ebx > 255, mov D\$ebx 255 | mov eax D\$ebx | mov B\$esi+RGBTRIPLE.rgbtGreenDis al

fld R\$TmpRotate.Red | fmul R\$RotationMatrix.Data2_0 | fld R\$TmpRotate.Green | fmul R\$RotationMatrix.Data2_1 | faddp ST1 ST0
fld R\$TmpRotate.Blue | fmul R\$RotationMatrix.Data2_2 | faddp ST1 ST0 | fistp F\$ebx | On D\$ebx <s 0, mov D\$ebx 0 | On D\$ebx > 255, mov D\$ebx 255 | mov eax D\$ebx | mov B\$esi+RGBTRIPLE.rgbtBlueDis al

EndP

Example of usage:
Code: [Select]

[hBitsInMemory: D\$ 0]  ; a variable to store the pixel in an ARGB form

mov esi D\$hBitsInMemory
call RGBRotate esi, 260 ;<--- Angle always in degrees

Btw: SOmeone knows how to achieve the hue angle using this sort of matrix ? For the reverted operation
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

#### dedndave

• Member
• Posts: 8828
• Still using Abacus 2.0
##### Re: RGBRotate
« Reply #1 on: June 01, 2014, 02:25:46 PM »
Christian Graus wrote several articles
whether or not you find exactly what you're looking for, you'll enjoy his articles   :t

http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=6556

another one, i haven't had time to look at it closely

http://www.codeproject.com/Articles/426172/My-Photo-Editor