阅读提示:
《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》。