- UID
- 7
- 帖子
- 2888
- 精华
- 10
- 积分
- 2836
|
找到一个原理比较简单的算法:
实现图像浮雕效果的一般原理是,将图像上每个像素点与其对角线的像素点形成差值,使相似颜色值淡化,不同颜色值突出,从而产生纵深感,达到浮雕的效果,具体的做法是用处于对角线的2个像素值相减,再加上一个背景常数,一般为128而成。这种算法的特点是简单快捷,缺点是不能调节图像浮雕效果的角度和深度。
用Photoshop实现图像浮雕效果,可以任意调节浮雕角度和深度(2个像素点的距离),还可以调整浮雕像素差值的数量。其基本算法原理和一般浮雕效果相同,但是具体做法不一样:对每个要处理的像素点,首先按照浮雕角度和深度计算处2个相应点的位置,然后计算这2个位置的颜色值,并使之形成差值,再乘上浮雕差值数量百分比,最后加上128的背景色。注意,这里计算的2个相应点是逻辑点,而不是实际的像素点,比如实现一个45度角,深度为3的图像浮雕效果,对每个像素点P(x, y),其对应的2个逻辑点的位置分别是P0(x - 3 * 0.7071 / 2, y - 3 * 0.7071 / 2)和P1(x + 3 * 0.7071 / 2, y + 3 * 0.7071 / 2),显然,对于这样的2个逻辑点,是不能直接从图像中找到其对应的像素点的,如果简单地对其四舍五入处理,将会造成大量的,由不同角度和深度而形成的相同的浮雕效果,这可不是我们想要的结果,而且使浮雕角度和深度参数失去了它原本的意义。为此,必须对原始图像按浮雕角度和深度进行缩放后,再对每个像素点进行浮雕效果处理,完毕再缩放回原图的大小,从而完成整个浮雕效果过程。下面是我经过反复试验后,写的Photoshop浮雕效果实现过程代码:
view plaincopy to clipboardprint?
01.过程定义:
02.
03. // 灰色浮雕。参数:
04. // Dest输出图,Source原图,Data自身操作图像
05. // Angle 角度, Size 长度, Num 像素数量百分比
06. // Callback回调函数,返回True终止操作,CallbackData回调函数参数地址
07. procedure ImageGraySculpture(var Data: TImageData;
08. Angle: Single; Size: LongWord; Num: LongWord = 100); overload;
09. {$IF RTLVersion >= 17.00}inline;{$IFEND}
10. procedure ImageGraySculpture(var Dest: TImageData; const Source: TImageData;
11. Angle: Single; Size: LongWord; Num: LongWord = 100); overload;
12. {$IF RTLVersion >= 17.00}inline;{$IFEND}
13. // 无效参数或者被回调函数终止操作返回False。
14. function ImageGraySculpture(var Dest: TImageData; const Source: TImageData;
15. Angle: Single; Size: LongWord; Num: LongWord;
16. Callback: TImageAbort; CallbackData: Pointer): Boolean; overload;
17.
18.代码实现:
19.
20.procedure GetSrcColor;
21.asm
22. push edx // edx = x
23. push ecx // ecx = y
24. mov esi, ecx // esi = y / 256 * Data.Stride +
25. mov eax, edx // x / 256 * 4 + Data.Scan0
26. sar esi, 8
27. sar eax, 8
28. shl eax, 2
29. imul esi, [ebx].TImageData.Stride
30. add esi, eax
31. add esi, [ebx].TImageData.Scan0
32. call GetBilinearColor
33. pop ecx // return eax = mm0 = ARGB
34. pop edx
35.end;
36.
37.procedure GraySculpture(x, y, xDelta, yDelta, Num: Integer); pascal;
38.var
39. width, height: Integer;
40. dstOffset: Integer;
41. colorBuf: TARGBQuadW;
42. data: TImageData;
43.asm
44. mov dstOffset, ebx
45. lea ebx, data
46. mov [ebx].TImageData.Scan0, esi
47. shl ecx, 2
48. add eax, ecx // Stride = srcOffset + width * 4
49. mov [ebx].TImageData.Stride, eax
50. shl ecx, 6
51. add ecx, x
52. mov width, ecx // width = width * 256 + x
53. shl edx, 8
54. add edx, y
55. mov height, edx // height = height * 256 + y
56. movd mm6, Num
57. punpcklwd mm6, mm6
58. punpcklwd mm6, mm6 // mm6 = 00 Num 00 Num 00 Num 00 Num
59. pxor mm7, mm7 // mm7 = 00 00 00 00 00 00 00 00
60. mov ecx, y // for (; y < Height; y += 256)
61.@@yLoop: // {
62. mov edx, x // for (; x < Width; x += 256
63.@@xLoop: // {
64. add ecx, yDelta // y1 = y + yDelta
65. add edx, xDelta // x1 = x + xDelta
66. call GetSrcColor // mm0 = 00 00 00 00 A1 R1 G1 B1
67. punpcklbw mm0, mm7 // mm0 = 00 A1 00 R1 00 G1 00 B1
68. movq ColorBuf, mm0 // ColorBuf = mm0
69. sub ecx, yDelta // y0 = y - yDelta
70. sub edx, xDelta // x0 = x - xDelta
71. call GetSrcColor // mm0 = 00 00 00 00 A0 R0 G0 B0
72. punpcklbw mm0, mm7 // mm0 = 00 A0 00 R0 00 G0 00 B0
73. psubsw mm0, ColorBuf // mm0 = A0-A1 R0-R1 G0-G1 B0-B1
74. psllw mm0, 7 // mm0 = mm0 * 128 * Num / 65536
75. pmulhw mm0, mm6
76. paddsw mm0, qword ptr ArgbTable[128*8]// mm0 = A+128 R+128 G+128 B+128
77. packuswb mm0, mm7 // mm0 = 00 00 00 00 A R G B
78. mov al, [edi].TARGBQuad.Alpha
79. movd [edi], mm0 // *edi = mm0
80. mov [edi].TARGBQuad.Alpha, al
81. add edi, 4 // edi += 4
82. add edx, 256
83. cmp edx, Width
84. jl @@xLoop // }
85. add ecx, 256
86. add edi, dstOffset
87. cmp ecx, Height
88. jl @@yLoop // }
89. emms
90.end;
91.
92.function ImageGraySculpture(var Dest: TImageData; const Source: TImageData;
93. Angle: Single; Size: LongWord; Num: LongWord;
94. Callback: TImageAbort; CallbackData: Pointer): Boolean;
95.var
96. x, y, Radius: Integer;
97. xDelta, yDelta: Integer;
98. dst, src: TImageData;
99.begin
100. Result := False;
101. if ImageEmpty(Dest) or ImageEmpty(Source) or (Size = 0) then
102. Exit;
103. Radius := (Size + 1) shr 1; // 图像边框扩展半径
104. Angle := PI * Angle / 180;
105. Size := Size shl 8; // Size = Size * 256
106. Num := (Num shl 9) div 100; // Num *= 5.12 转换为2的幂
107. xDelta := Round(Cos(Angle) * Size);
108. yDelta := Round(Sin(Angle) * Size);
109. x := (Radius shl 8) - (xDelta div 2);
110. y := (Radius shl 8) - (yDelta div 2);
111. if @Dest <> @Source then
112. CopyAlpha(Dest, Source);
113. GetExpandData(Dest, Source, Radius, dst, src);
114. try
115. if Assigned(Callback) then
116. Result := ExecuteAbort(dst, src, @GraySculpture,
117. [x, y, xDelta, yDelta, Num], Callback, CallbackData)
118. else
119. Result := ExecuteProc(dst, src, @GraySculpture, [x, y, xDelta, yDelta, Num]);
120. finally
121. FreeImageData(src);
122. end;
123.end;
124.
125.procedure ImageGraySculpture(var Dest: TImageData; const Source: TImageData;
126. Angle: Single; Size: LongWord; Num: LongWord);
127.begin
128. ImageGraySculpture(Dest, Source, Angle, Size, Num, nil, nil);
129.end;
130.
131.procedure ImageGraySculpture(var Data: TImageData;
132. Angle: Single; Size: LongWord; Num: LongWord);
133.begin
134. ImageGraySculpture(Data, Data, Angle, Size, Num, nil, nil);
135.end; |
|