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

阅读提示:

    《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》。

    因水平有限,错误在所难免,欢迎指正和指导。邮箱地址:[email protected]

    这里可访问《Delphi图像处理 -- 文章索引》。

 

 

你可能感兴趣的:(Delphi)