Delphi图像处理 -- RGB与HSV转换
阅读提示:
《Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。
《C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。
尽可能保持二者内容一致,可相互对照。
本文代码必须包括文章《Delphi图像处理 -- 数据类型及公用过程》中的ImageData.pas单元。
const _fc0: Single = 0.0; _fc1: Single = 1.0; _fc6: Single = 6.0; _fc60: Single = 60.0; _fc255: Single = 255.0; _fc360: Single = 360.0; procedure ColorToHSV(var H, S, V: Single; Color: TARGB); asm push eax push edx push ecx movzx ecx, Color.TARGBQuad.Blue movzx edx, Color.TARGBQuad.Green movzx eax, Color.TARGBQuad.Red cmp ecx, edx // ecx = rgbMax jge @@1 // edx = rgbMin xchg ecx, edx @@1: cmp ecx, eax jge @@2 xchg ecx, eax @@2: cmp edx, eax cmova edx, eax cvtsi2ss xmm0, ecx movaps xmm1, xmm0 divss xmm0, _fc255 pop eax movss [eax], xmm0 // *V = rgbMax / 255 mov eax, ecx sub ecx, edx // delta = rgbMax - rgbmin jnz @@3 pop edx // if (delta == 0) pop eax // { mov [eax], ecx // *H = *S = 0 mov [edx], ecx // return jmp @@Exit // } @@3: cvtsi2ss xmm0, ecx movaps xmm2, xmm0 divss xmm0, xmm1 pop edx movss [edx], xmm0 // *S = delta / rgbMax cmp al, Color.TARGBQuad.Red jne @@5 movzx eax, Color.TARGBQuad.Green movzx edx, Color.TARGBQuad.Blue xor ecx, ecx // if (R == rgbMax) eax = G - B; add = 0 jmp @@7 @@5: cmp al, Color.TARGBQuad.Green jne @@6 movzx eax, Color.TARGBQuad.Blue movzx edx, Color.TARGBQuad.Red mov ecx, 120 // if (G == rgbMax) eax = B - R; add = 120 jmp @@7 @@6: movzx eax, Color.TARGBQuad.Red movzx edx, Color.TARGBQuad.Green mov ecx, 240 // if (B == rgbMax) eax = R - G; add = 240 @@7: sub eax, edx cvtsi2ss xmm0, eax cvtsi2ss xmm1, ecx mulss xmm0, _fc60 divss xmm0, xmm2 addss xmm0, xmm1 // H = eax * 60 / delta + add comiss xmm0, _fc0 jae @@8 addss xmm0, _fc360 @@8: pop eax movss [eax], xmm0 @@Exit: end; function HSVToColor(H, S, V: Single): TARGB; asm movss xmm1, H comiss xmm1, _fc0 jae @@1 addss xmm1, _fc360 jmp @@2 @@1: comiss xmm1, _fc360 jb @@2 subss xmm1, _fc360 @@2: divss xmm1, _fc60 cvtss2si edx, xmm1 // index = Round(H) cvtsi2ss xmm2, edx subss xmm1, xmm2 // extra = H - index comiss xmm1, _fc0 // if (extra < 0) // 如果index发生五入 jae @@3 // { dec edx // index -- addss xmm1, _fc1 // extra ++ @@3: // } test edx, 1 jnz @@4 movaps xmm2, xmm1 movss xmm1, _fc1 subss xmm1, xmm2 // if (index & 1 == 0) extra = 1 - extra @@4: movss xmm0, V movss xmm2, S minss xmm0, _fc1 minss xmm2, _fc1 maxss xmm0, _fc0 maxss xmm2, _fc0 mulss xmm0, _fc255 mulss xmm2, xmm0 // V * S mulss xmm1, xmm2 // V * S * extra pslldq xmm1, 4 movss xmm1, xmm2 // xmm1 = 0 0 V*S*E V*S pshufd xmm0, xmm0, 0 // xmm0 = V V V V subps xmm0, xmm1 // xmm0 -= mm1 = V V T P jmp @@jmpTable[edx*4].Pointer @@jmpTable: dd offset @@H60 dd offset @@H120 dd offset @@H180 dd offset @@H240 dd offset @@H300 dd offset @@H360 @@H360: // 300 - 359 (V, P, T) pshufd xmm0, xmm0, 11100001b jmp @@H60 @@H300: // 240 - 299 (T, P, V) pshufd xmm0, xmm0, 11010010b jmp @@H60 @@H240: // 180 - 239 (P, T, V) pshufd xmm0, xmm0, 11000110b jmp @@H60 @@H180: // 120 - 179 (P, V, T) pshufd xmm0, xmm0, 11001001b jmp @@H60 @@H120: // 60 - 119 (T, V, P) pshufd xmm0, xmm0, 11011000b @@H60: // 0 - 59 (V, T, P) cvtps2dq xmm0, xmm0 packssdw xmm0, xmm0 packuswb xmm0, xmm0 movd eax, xmm0 or eax, 0ff000000h end;
《Delphi图像处理》系列使用GDI+单元下载地址和说明见文章《GDI+ for VCL基础 -- GDI+ 与 VCL》。
因水平有限,错误在所难免,欢迎指正和指导。邮箱地址:maozefa@hotmail.com
这里可访问《Delphi图像处理 -- 文章索引》。