阅读提示:
《Delphi图像处理》系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。
《C++图像处理》系列以代码清晰,可读性为主,全部使用C++代码。
尽可能保持二者内容一致,可相互对照。
本文代码必须包括文章《Delphi图像处理 -- 数据类型及公用过程》中的ImageData.pas单元。
图像的最大值处理就是以当前像素为中心,取周边一定半径范围内的所有像素的RGB分量的最大值,作为当前像素的分量值。如果图像含Alpha信息,则应对Alpha分量作一个相反的处理,即最小值处理。
procedure DoMaxValue(var Dest: TImageData; const Source: TImageData; Radius: Integer); var height, iOffset, jOffset, dstOffset, srcOffset: Integer; asm push esi push edi push ebx push ecx shl ecx, 1 mov ebx, [edx].TImageData.Stride imul ebx, ecx shl ecx, 2 add ebx, ecx sub ebx, 4 neg ebx mov iOffset, ebx mov ebx, [edx].TImageData.Stride push ebx shl ebx, 1 sub ebx, ecx mov jOffset, ebx call _SetCopyRegs mov dstOffset, ebx mov srcOffset, eax mov height, edx pop ebx pop eax @@yLoop: push ecx @@xLoop: mov edx, eax pxor mm0, mm0 pxor mm1, mm1 pxor mm2, mm2 @@iLoop: push eax @@jLoop: pmaxub mm1, [esi] pmaxub mm2, [esi+ebx] add esi, 8 dec eax jnz @@jLoop movd mm3, [esi] movd mm4, [esi+ebx] pmaxub mm0, mm3 pmaxub mm0, mm4 pop eax add esi, jOffset dec edx jnz @@iLoop push eax @@jlLoop: pmaxub mm1, [esi] add esi, 8 dec eax jnz @@jlLoop movd mm3, [esi] pmaxub mm0, mm3 pop eax pmaxub mm0, mm1 pmaxub mm0, mm2 psrlq mm1, 32 psrlq mm2, 32 pmaxub mm0, mm1 pmaxub mm0, mm2 movd [edi], mm0 add esi, iOffset add edi, 4 loop @@xLoop pop ecx add esi, srcOffset add edi, dstOffset dec height jnz @@yLoop pop ebx pop edi pop esi emms end; procedure DoMinAlpha(var Dest: TImageData; const Source: TImageData; Radius: Integer); var height, iOffset, jOffset, dstOffset, srcOffset: Integer; asm push esi push edi push ebx shl ecx, 1 inc ecx push ecx mov ebx, [edx].TImageData.Stride imul ebx, ecx sub ebx, 4 neg ebx mov iOffset, ebx shl ecx, 2 mov ebx, [edx].TImageData.Stride sub ebx, ecx mov jOffset, ebx call _SetCopyRegs mov dstOffset, ebx mov srcOffset, eax mov height, edx add esi, 3 add edi, 3 pop edx @@yLoop: push ecx @@xLoop: mov ebx, edx mov eax, 255 @@iLoop: push edx @@jLoop: cmp al, [esi] jbe @@1 mov al, [esi] @@1: add esi, 4 dec edx jnz @@jLoop pop edx add esi, jOffset dec ebx jnz @@iLoop mov [edi], al add esi, iOffset add edi, 4 loop @@xLoop pop ecx add esi, srcOffset add edi, dstOffset dec height jnz @@yLoop pop ebx pop edi pop esi end; // 图像数据最大值处理。参数:图像数据,半径 procedure ImageMaxValue(var Data: TImageData; Radius: Integer); var src: TImageData; begin if Data.AlphaFlag then ArgbConvertPArgb(Data); // 如果图像数据含Alpha信息,转换为PARGB src := _GetExpandData(Data, Radius);// 获取扩展半径后的图像数据源 DoMaxValue(Data, src, Radius); // 图像数据的最大值处理 if Data.AlphaFlag then // 如果图像数据含Alpha信息 begin DoMinAlpha(Data, src, Radius); // Alpha分量作最小值处理 PArgbConvertArgb(Data); // 还原PARGB为ARGB end; FreeImageData(src); end;
调用例子及运行效果:
procedure TForm1.Button3Click(Sender: TObject); var bmp: TGpBitmap; g: TGpGraphics; data: TImageData; begin // bmp := TGpBitmap.Create('..\..\media\apple.png'); bmp := TGpBitmap.Create('..\..\media\source.bmp'); data := LockGpBitmap(bmp); ImageMaxValue(data, 3); UnlockGpBitmap(bmp, data); g := TGpGraphics.Create(Canvas.Handle); g.DrawImage(bmp, 140, 0); g.Free; bmp.Free; end;
《Delphi图像处理》系列使用GDI+单元下载地址和说明见文章《GDI+ for VCL基础 -- GDI+ 与 VCL》。
因水平有限,错误在所难免,欢迎指正和指导。邮箱地址:[email protected]
这里可访问《Delphi图像处理 -- 文章索引》。