閱讀提示: 《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 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; 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;