阅读提示:
《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图像处理 -- 文章索引》。