閱讀提示:
《Delphi影像處理》系列以效率為側重點,一般代碼為PASCAL,核心代碼採用BASM。
《C++影像處理》系列以代碼清晰,可讀性為主,全部使用C++代碼。
儘可能保持二者內容一致,可相互對照。
本文代碼必須包括文章《Delphi影像處理 -- 資料類型及公用過程》中的ImageData.pas單元和《Delphi影像處理 -- 平面幾何變換類》TransformMatrix.pas單元。
利用模版矩陣進行卷積操作,可以實現圖片的彩色浮雕效果,下面的代碼使用《Delphi影像處理 -- 映像卷積》中介紹的通用卷積過程,來實現圖片的彩色浮雕效果:
var Data: TImageData;begin Data := GetImageData(TGpBitmap.Create('d:/56-3.jpg'), True); ImageConvolutionI(Data, [1, 1, 0, 0, 0, 0, 1, 0, -2]); DrawImage(Canvas, 0, 0, Data); FreeImageData(Data);end;
但是,同一般灰色浮雕的實現一樣,沒法實現任意角度的浮雕,為此,採用《Delphi影像處理 -- 灰階浮雕》同樣的方法,可靈活的完成任意角度和大小的圖片彩色浮雕效果,下面是整個代碼:
procedure ImageColorSculpture(var Data: TImageData; Angle: Single; Size: LongWord);var x, y, Radius: Integer; xDelta, yDelta: Integer; xDelta2, yDelta2: Integer; width, height: Integer; dstOffset: Integer; src: TImageData;begin Radius := (Size + 1) shr 1; // 映像邊框擴充半徑 Angle := PI * Angle / 180; Size := Size shl 11; // Size = Size * 2048 xDelta := Round(Cos(Angle) * Size); yDelta := Round(Sin(Angle) * Size); xDelta2 := xDelta shl 1; yDelta2 := yDelta shl 1; x := (Radius shl 12) - xDelta; y := (Radius shl 12) - yDelta; width := x + (Data.Width shl 12); height := y + (Data.Height shl 12); if Data.AlphaFlag then ArgbConvertPArgb(Data); src := _GetExpandData(Data, Radius); asm push esi push edi push ebx mov eax, Data lea edx, src call _SetCopyRegs mov dstOffset, ebx pxor mm7, mm7 // mm7 = 00 00 00 00 00 00 00 00 pxor xmm7, xmm7 mov esi, src.Scan0 mov ebx, src.Stride mov ecx, y // for (; y < Height; y += 1096)@@yLoop: // { mov edx, x // for (; x < Width; x += 4096@@xLoop: // { push edx push ecx // x1 = x, y1 = y call GetSrcColor // mm0 = 00 A1 00 R1 00 G1 00 B1 movq mm1, mm0 // mm1 = mm0(ARGB1) add edx, xDelta // x2 = x, y2 = y - yDelta call GetSrcColor // mm0 = 00 A2 00 R2 00 G2 00 B2 paddw mm1, mm0 // mm1 += mm0(ARGB2) add ecx, yDelta2 sub edx, xDelta // x3 = x - xDelta, y3 = y + yDelta call GetSrcColor // mm0 = 00 A3 00 R3 00 G3 00 B3 paddw mm1, mm0 // mm1 += mm0(ARGB3) add edx, xDelta2 // x0 = x + xDelta, y0 = y + yDelta call GetSrcColor // mm0 = 00 A0 00 R0 00 G0 00 B0 psllw mm0, 1 // mm0 = A0*2 R0*2 G0*2 B0*2 psubsw mm1, mm0 // mm6 = (ARGB1+ARGB2+ARGB3) - ARGB0*2 packuswb mm1, mm7 // mm6 = 00 00 00 00 A R G B mov al, [edi].TARGBQuad.Alpha movd [edi], mm1 // *edi = mm0 mov [edi].TARGBQuad.Alpha, al pop ecx pop edx add edi, 4 // edi += 4 add edx, 1000h cmp edx, width jl @@xLoop // } add ecx, 1000h add edi, dstOffset cmp ecx, height jl @@yLoop // } emms pop ebx pop edi pop esi end; FreeImageData(src); if Data.AlphaFlag then PArgbConvertArgb(Data);end;
代碼還是採用二次線性插值法為每個象素點尋找鄰近的4個邏輯點進行差值運算,差值運算的原理同前面所舉的利用卷積矩陣實現彩色浮雕效果的例子。
下面是一個簡單的測試代碼:
procedure TForm1.Button3Click(Sender: TObject);var bmp: TGpBitmap; g: TGpGraphics; data: TImageData;begin bmp := TGpBitmap.Create('..\media\20041001.jpg'); g := TGpGraphics.Create(Canvas.Handle); g.DrawImage(bmp, 0, 0); data := LockGpBitmap(bmp); ImageColorSculpture(data, 45, 3); UnlockGpBitmap(bmp, data); g.DrawImage(bmp, 0, data.Height); g.Free; bmp.Free;end;
原始圖:
彩色浮雕:
《Delphi影像處理》系列使用GDI+單元和說明見文章《GDI+ for VCL基礎 -- GDI+ 與 VCL》。
因水平有限,錯誤在所難免,歡迎指正和指導。郵箱地址:maozefa@hotmail.com
這裡可訪問《Delphi影像處理 -- 文章索引》。