Delphi图像处理 -- 设置图像关键颜色

设置图像关键颜色,使图像的某种或某个范围的颜色成为透明色,是图片合成、动画显示中经常用的图像处理手段。下面是实现代码:

过程定义: // 设置色键(透明范围)。colorLow 低色键值; colorHigh 高色键值 // 当像素A、R、G、B值同时大于等于colorLow和小于等于colorHigh时为透明色 procedure ImageSetColorKey(var Data: TImageData; ColorLow, ColorHigh: LongWord); // 按坐标颜色设置色键。x,y 图像坐标点, Precision 色键容差 procedure ImageSetColorKeyPoint(var Data: TImageData; x, y: Integer; Precision: LongWord); 实现代码: procedure ColorKeyEQ; asm punpckldq mm2, mm2 // mm2 = ColorKey ColorKey mov eax, ecx shr ecx, 1 // 每次比较2个像素 @@yLoop: push ecx @@xLoop: dec ecx js @@1 movq mm0, [edi] // mm0 = A1 R1 G1 B1 A0 R0 G0 B0 pcmpeqd mm0, mm2 // 按32位数对2个像素进行比较 pandn mm0, [edi] // 比较结果取非后同原象素值作与运算 movq [edi], mm0 // 存入结果 add edi, 8 jmp @@xLoop @@1: test eax, 1 // 比较可能存在的最后一个像素 jz @@2 movd mm0, [edi] pcmpeqd mm0, mm2 movd ecx, mm0 not ecx and [edi], ecx add edi, 4 @@2: pop ecx add edi, ebx dec edx jnz @@yLoop end; procedure ColorKeyArea; asm pxor mm7, mm7 // 比较命令是按有符号数进行的,因此 punpcklbw mm2, mm7 // ColorLow按字节扩展为字 punpcklbw mm3, mm7 // ColorHigh按字节扩展为字 @@yLoop: push ecx @@xLoop: movd mm0, [edi] // mm0 = 00 00 00 00 A R G B punpcklbw mm0, mm7 // mm0 = 00 A 00 R 00 G 00 B movq mm1, mm2 pcmpgtw mm1, mm0 // 比较 ColorLow 是否大于 mm0 packsswb mm1, mm1 // 比较结果按字压缩为字节 movd eax, mm1 test eax, eax jnz @@Next // 如果 ColorLow 小于等于 mm0 pcmpgtw mm0, mm3 // 比较 mm0 是否大于 ColorHigh packsswb mm0, mm0 // 比较结果按字压缩为字节 movd eax, mm0 test eax, eax jnz @@Next // if (argb < ColorLow || argb > ColorLor) and [edi], eax // *(int* )edi = 0 @@Next: add edi, 4 loop @@xLoop pop ecx add edi, ebx dec edx jnz @@yLoop end; procedure ImageSetColorKey(var Data: TImageData; ColorLow, ColorHigh: LongWord); asm push edi push ebx call IsValid32 jc @@Exit movd mm2, edx movd mm3, ecx xor edx, ecx push edx call SetDataRegs32 pop eax test eax, eax jz @@1 call ColorKeyArea jmp @@end @@1: call ColorKeyEQ @@end: emms @@Exit: pop ebx pop edi end; procedure ImageSetColorKeyPoint(var Data: TImageData; x, y: Integer; Precision: LongWord); asm push edi push ebx call IsValid32 jc @@Exit test edx, edx js @@Exit cmp edx, [eax].TImageData.Width jae @@Exit test ecx, ecx js @@Exit cmp ecx, [eax].TImageData.Height jae @@Exit cmp [eax].TImageData.InvertLine, TRUE jne @@1 neg ecx add ecx, [eax].TImageData.Height dec ecx @@1: imul ecx, [eax].TImageData.Stride shl edx, 2 // edx = data->Scan0 + add edx, ecx // y * data->Stride + x * 4 add edx, [eax].TImageData.Scan0 pxor mm7, mm7 movd mm0, precision // mm0 = precision (4 word) punpcklwd mm0, mm0 punpcklwd mm0, mm0 movd mm2, [edx] // mm2 = mm3 = argb (byte --> word) punpcklbw mm2, mm7 movq mm3, mm2 paddsw mm3, mm0 // mm3 += mm0 (colorHigh) psubsw mm2, mm0 // mm2 -= mm0 (colorLow) packuswb mm3, mm3 packuswb mm2, mm2 call SetDataRegs32 movq mm0, mm2 pxor mm0, mm3 movd eax, mm0 test eax, eax jz @@2 call ColorKeyArea jmp @@end @@2: call ColorKeyEQ @@end: emms @@Exit: pop ebx pop edi end;

上面的代码中,提供了2种设置图像关键颜色过程:

ImageSetColorKey过程,设置图像的关键颜色范围,ColorLow和ColorHigh分别为图像关键颜色的低色键值和高色键值,只要是处于高低色键范围内的颜色都会成为透明色,如果ColorLow与ColorHigh相等,只有一种颜色成为透明色。

ImageSetColorKeyPoint过程,是通过图像的位置和颜色容差来设置关键颜色的。因为很多图像的背景色都不是单纯的某种颜色,靠ImageSetColorKey过程也不好确定关键颜色的高低色键,这时可以给定一个图像坐标,以这个坐标位置的像素颜色为基准,凡是在基准颜色上下容差范围内的颜色都会成为透明色。

下面是个简单的调用例子:

var Data: TImageData; begin Data := GetImageData(TGpBitmap.Create('d:\56-3.jpg'), True); DrawImage(Canvas, 0, 0, Data); ImageSetColorKeyPoint(Data, 175, 5, 39); DrawImage(Canvas, Data.Width, 0, Data); FreeImageData(Data); end;

代码中的DrawImage过程见《Delphi图像处理 -- 图像显示》。

下面是运行效果截图:

效果图

文章中使用GDI+版本下载地址和说明见《GDI+ for VCL基础 -- GDI+ 与 VCL》。

文章中所用数据类型及一些过程见《Delphi图像处理 -- 数据类型及内部过程》和《Delphi图像处理 -- 图像像素结构与图像数据转换》。

尽管我十分努力,但水平有限,错误在所难免,欢迎指正和指导。邮箱地址:

maozefa@hotmail.com

说明:本文代码于2010.5.20重新修订过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值