您的位置:首页 > 编程语言 > Delphi

Delphi图像处理 -- RGB与HSL转换

2013-12-05 09:53 609 查看
阅读提示:

Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。

C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。

尽可能保持二者内容一致,可相互对照。

本文代码必须包括文章《Delphi图像处理 -- 数据类型及公用过程》中的ImageData.pas单元。

const
_fc0: Single    = 0.0;
_fcd5: Single   = 0.5;
_fc1: Single    = 1.0;
_fc2: Single    = 2.0;
_fc6: Single    = 6.0;
_fc60: Single   = 60.0;
_fc255: Single  = 255.0;
_fc360: Single  = 360.0;
_fc510: Single  = 510.0;

procedure ColorToHSL(var H, S, L: Single; Color: TARGB);
var
rgbMax: LongWord;
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
mov       rgbMax, ecx
mov       eax, ecx
add       ecx, edx        // ecx = rgbMax + rgbMin
sub       eax, edx        // delta = rgbMax - rgbmin
cvtsi2ss  xmm0, ecx
divss     xmm0, _fc510
pop       edx
movss     [edx], xmm0     // *L = (rgbMax + rgbMin) / 255 / 2
jnz       @@3
pop       ecx             // if (delta == 0)
pop       edx             // {
mov       [ecx], eax      //   *H = *S = 0
mov       [edx], eax      //   return
jmp       @@Exit          // }
@@3:
comiss    xmm0, _fcd5
jb        @@4
neg       ecx
add       ecx, 510        // if (L < 128) ecx = 510 - ecx
@@4:
pop       edx
cvtsi2ss  xmm0, eax
cvtsi2ss  xmm1, ecx
movaps    xmm2, xmm0
divss     xmm0, xmm1
movss     [edx], xmm0     // *S = delta / ecx
mov       eax, 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 HSLToColor(H, S, L: Single): TARGB;
asm
movss     xmm0, H
comiss    xmm0, _fc0
jae       @@1
addss     xmm0, _fc360
jmp       @@2
@@1:
comiss    xmm0, _fc360
jb        @@2
subss     xmm0, _fc360
@@2:
movss     xmm3, _fc1
divss     xmm0, _fc60
cvtss2si  edx, xmm0       // index = Round(H)
cvtsi2ss  xmm1, edx
subss     xmm0, xmm1      // extra = H - index
comiss    xmm0, _fc0      // if (extra < 0) // 如果index发生五入
jae       @@3             // {
dec       edx             //   index --
addss     xmm0, xmm3      //   extra ++
@@3:                          // }
test      edx, 1
jz        @@4
movaps    xmm1, xmm0
movaps    xmm0, xmm3
subss     xmm0, xmm1      // if (index & 1) extra = 1 - extra
@@4:
movss     xmm2, S
movss     xmm4, L
minss     xmm2, xmm3
minss     xmm4, xmm3
maxss     xmm2, _fc0
maxss     xmm4, _fc0
pslldq    xmm0, 4         //            max  mid  min
movlhps   xmm0, xmm3      // xmm0 = 0.0 1.0 extra 0.0
movaps    xmm1, xmm0
subss     xmm3, xmm2
movss     xmm2, _fcd5
pshufd    xmm2, xmm2, 0
pshufd    xmm3, xmm3, 0
subps     xmm1, xmm2
mulps     xmm1, xmm3
subps     xmm0, xmm1      // xmm0 = xmm0 - (xmm0 - 0.5) * (1.0 - S);
movaps    xmm1, xmm0
subss     xmm4, xmm2
mulss     xmm4, _fc2      // xmm4 = (L - 0.5) * 2
comiss    xmm4, _fc0
jb        @@5
movss     xmm0, _fc1
pshufd    xmm0, xmm0, 0
subps     xmm0, xmm1      // if (xmm4 >= 0) xmm0 = 1 - xmm0
@@5:
movss     xmm3, _fc255
pshufd    xmm4, xmm4, 0
pshufd    xmm3, xmm3, 0
mulps     xmm0, xmm4
addps     xmm0, xmm1
mulps     xmm0, xmm3      // xmm0 = (xmm0 + xmm0 * xmm4) * 255
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
pshufd    xmm0, xmm0, 11100001b
jmp       @@H60
@@H300:                       // 240 - 299
pshufd    xmm0, xmm0, 11010010b
jmp       @@H60
@@H240:                       // 180 - 239
pshufd    xmm0, xmm0, 11000110b
jmp       @@H60
@@H180:                       // 120 - 179
pshufd    xmm0, xmm0, 11001001b
jmp       @@H60
@@H120:                       // 60 - 119
pshufd    xmm0, xmm0, 11011000b
@@H60:                        // 0 - 59
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图像处理 -- 文章索引》。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: