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

Delphi图像处理 -- 最小值

2013-07-16 19:33 281 查看
阅读提示:

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

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

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

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

图像的最小值处理就是以当前像素为中心,取周边一定半径范围内的所有像素的RGB分量的最小值,作为当前像素的分量值。如果图像含Alpha信息,则应对Alpha分量作一个相反的处理,即最大值处理。

procedure DoMinValue(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
pcmpeqb   mm0, mm0
movq      mm1, mm0
movq      mm2, mm0
@@iLoop:
push      eax
@@jLoop:
pminub    mm1, [esi]
pminub    mm2, [esi+ebx]
add       esi, 8
dec       eax
jnz       @@jLoop
movd      mm3, [esi]
movd      mm4, [esi+ebx]
pminub    mm0, mm3
pminub    mm0, mm4
pop       eax
add       esi, jOffset
dec       edx
jnz       @@iLoop
push      eax
@@jlLoop:
pminub    mm1, [esi]
add       esi, 8
dec       eax
jnz       @@jlLoop
movd      mm3, [esi]
pminub    mm0, mm3
pop       eax
pminub    mm0, mm1
pminub    mm0, mm2
psrlq     mm1, 32
psrlq     mm2, 32
pminub    mm0, mm1
pminub    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 DoMaxAlpha(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
xor       eax, eax
@@iLoop:
push      edx
@@jLoop:
cmp       al, [esi]
jae       @@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 ImageMinValue(var Data: TImageData; Radius: Integer);
var
src: TImageData;
begin
if Data.AlphaFlag then
ArgbConvertPArgb(Data);           // 如果图像数据含Alpha信息,转换为PARGB
src := _GetExpandData(Data, Radius);// 获取扩展半径后的图像数据源
DoMinValue(Data, src, Radius);      // 图像数据的最小值处理
if Data.AlphaFlag then              // 如果图像数据含Alpha信息
begin
DoMaxAlpha(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);
ImageMinValue(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》。

因水平有限,错误在所难免,欢迎指正和指导。邮箱地址:maozefa@hotmail.com

这里可访问《Delphi图像处理 -- 文章索引》。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: