Guest:
Register
|
Login
|
Member List
|
Search
|
Statistics
|
FAQ
Language
----------
Simplifed Chinese
Traditional Chinese
English
CnPack Forum
»
CnVCL 组件包
» 旋转位图
‹‹ Last Thread
|
Next Thread ››
Poll
Trade
Reward
Activity
Printable Version
|
Email to Friend
|
Subscription
|
Favorites
Subject: 旋转位图
alblert
新警察
UID 2395
Digest Posts 0
Credits 3
Posts 3
点点分 3
Reading Access 10
Registered 2006-7-21
Status Offline
#1
Post at 2006-7-21 19:17
Profile
|
Blog
|
P.M.
旋转位图
没学过线性代数,也不知道什么是插值算法、矩阵,最近在网上看了点资料,补了补,自己写了段二次插值算法旋转位图的代码(纯粹是根据二次插值的原理写的),图象效果还行,就是速度太慢,根本没有实用价值,cnpack的图象处理单元有快速二次插值旋转位图的算法,可惜没看懂,原理网上也有--将浮点运算变为整数运算,但具体实现我做不出来,在此请教cnpack的高手,可否解释一下cnpack那段快速二次插值旋转位图的代码,不甚感激!!!
另外,使用cnBitmap.rotate旋转后,部分图象看不见,如何将整个位图显示出来?
下面是我写的,如何该为快速的旋转方法(如何将浮点运算变为整数运算)
type
PPixelArray = ^TPixelArray;
TPixelArray = array[word] of TRGBQuad;
procedure RotateBitmap(Src: TBitmap; out Dst: TBitmap;Center:point; Angle: single);
var
cosRadians: single;
sinRadians: single;
inX: Integer;
inY: Integer;
oldX: Double;
oldY: Double;
oldRow: PPixelArray;
RotatedRow: PPixelArray;
iX, iY: Integer;
dX, dY: single;
SrcWidth, SrcHeight: Integer;
Sx, Sy: single;
begin
Angle := -(Angle) * PI / 180;
SrcWidth := Src.Width;
SrcHeight := Src.Height;
sinRadians := Sin(Angle);
cosRadians := Cos(Angle);
Sx := Abs(SrcWidth * cosRadians) + Abs(SrcHeight * sinRadians);
Sy := Abs(SrcWidth * sinRadians) + Abs(SrcHeight * cosRadians);
Dst.Width := round(Sx);
Dst.Height := round(Sy);
for inY := 0 to Dst.Height - 1 do begin
RotatedRow := Dst.Scanline[inY];
for inX := 0 to Dst.Width - 1 do begin
oldX := (inX - center.x) * cosRadians + (inY - center.Y) * sinRadians + center.x;
oldY := -(inX - center.x) * sinRadians + (inY - center.Y) * cosRadians + center.Y;
if (oldX > 0) and (oldX < SrcWidth - 1) and (oldY > 0) and (oldY < SrcHeight - 1) then begin
iX := trunc(oldX); iY := trunc(oldY);
dX := frac(oldX); dY := frac(oldY);
oldRow := Src.Scanline[iY];
RotatedRow[inX].rgbBlue := round((oldRow[iX].rgbBlue * (1 - dX) + oldRow[iX + 1].rgbBlue * dX) * (1 - dY));
RotatedRow[inX].rgbGreen := round((oldRow[iX].rgbGreen * (1 - dX) + oldRow[iX + 1].rgbGreen * dX) * (1 - dY));
RotatedRow[inX].rgbRed := round((oldRow[iX].rgbRed * (1 - dX) + oldRow[iX + 1].rgbRed * dX) * (1 - dY));
RotatedRow[inX].rgbReserved := round((oldRow[iX].rgbReserved * (1 - dX) + oldRow[iX + 1].rgbReserved * dX) * (1 - dY));
oldRow := Src.Scanline[iY + 1];
RotatedRow[inX].rgbBlue := RotatedRow[inX].rgbBlue + round((oldRow[iX].rgbBlue * (1 - dX) + oldRow[iX + 1].rgbBlue * dX) * dY);
RotatedRow[inX].rgbGreen := RotatedRow[inX].rgbGreen + round((oldRow[iX].rgbGreen * (1 - dX) + oldRow[iX + 1].rgbGreen * dX) * dY);
RotatedRow[inX].rgbRed := RotatedRow[inX].rgbRed + round((oldRow[iX].rgbRed * (1 - dX) + oldRow[iX + 1].rgbRed * dX) * dY);
RotatedRow[inX].rgbReserved := RotatedRow[inX].rgbReserved + round((oldRow[iX].rgbReserved * (1 - dX) + oldRow[iX + 1].rgbReserved * dX) * dY);
end
else begin
RotatedRow[inX].rgbBlue := 0;
RotatedRow[inX].rgbGreen := 0;
RotatedRow[inX].rgbRed := 0;
RotatedRow[inX].rgbReserved := 0;
end;
end;
end;
end;
[
Last edited by alblert on 2006-7-21 at 19:26
]
alblert
新警察
UID 2395
Digest Posts 0
Credits 3
Posts 3
点点分 3
Reading Access 10
Registered 2006-7-21
Status Offline
#2
Post at 2006-7-24 14:26
Profile
|
Blog
|
P.M.
zx := SrcX and $7FFF; //取低15位,既旋转后坐标的小数部分
zy := SrcY and $7FFF; //同上
izy := zy xor $7FFF; //???
w2 := (zx * izy) shr 15; // 计算加权值
w1 := izy - w2;
w4 := (zx * zy) shr 15;
w3 := zy - w4;
Dst.b := (Col1.b * w1 + Col2.b * w2 + Col3.b * w3 + Col4.b * w4) shr 15;
Dst.g := (Col1.g * w1 + Col2.g * w2 + Col3.g * w3 + Col4.g * w4) shr 15;
Dst.r := (Col1.r * w1 + Col2.r * w2 + Col3.r * w3 + Col4.r * w4) shr 15;
下面都没看懂
izy := zy xor $7FFF; 异或运算后是什么?
...
...
zjy
管理员
UID 2
Digest Posts
6
Credits 2385
Posts 1543
点点分 2385
Reading Access 102
Registered 2002-12-16
Location China
Status Offline
#3
Post at 2006-7-24 20:03
Profile
|
Site
|
Blog
|
P.M.
这段代码使用整数模拟小数运算的方法来提高性能。旋转函数的代码没写什么注释,你可以看看缩放函数的代码:SmoothResize,这里面有原始公式及推导和演化,其实主要就是分别计算插值区域四个点的权值。
代码中用 int32 的低 15 位表示小数部分。
izy := zy xor $7FFF; 这行相当于 izy := $8000 - zy; 也就是小数的 1.0 - zy。
(似乎 xor 的速度比减法快,或者可以跟相邻的指令同步执行,原因不太记得了,也可能跟用减法效果一样吧)
这段代码是我根据缩放代码修改而来,当时忘记写详细的文档,现在自己也不太记得了
Zhou JingYu
CnPack Administrator
http://www.cnpack.org/
alblert
新警察
UID 2395
Digest Posts 0
Credits 3
Posts 3
点点分 3
Reading Access 10
Registered 2006-7-21
Status Offline
#4
Post at 2006-7-25 14:28
Profile
|
Blog
|
P.M.
总算想明白了,和斑竹说的差不多
把我的代码修改之后,速度的确快了很多
Vdst为反向计算原始点的颜色值
V11,V21,V12,V22为四个邻近点的颜色值
i水平方向比例系数
j垂直方向比例系数
Vdst=(V11*(1-i)+V21*i)*(1-j) + (V12*(1-i)+V21*i)*j
=V11*(1-i)*(1-j) + V21*i*(1-j) + (V12*(1-i)*j + V21*i*j
zx := SrcX and $7FFF; // 旋转后的低15bit,即小数部分 => i
zy := SrcY and $7FFF; //同上 => j
izy := zy xor $7FFF; // 1-j
w2 := (zx * izy) shr 15; // i*(1-j)
w1 := izy - w2; //1-j-i*(1-j) => (1-i)*(1-j)
w4 := (zx * zy) shr 15; // i*j
w3 := zy - w4; //j-i*j => j*(1-i)
[
Last edited by alblert on 2006-7-25 at 14:36
]
Poll
Trade
Reward
Activity
CnPack Forum
CnPack English Forum
> CnWizards IDE Wizards
> CVSTracNT
> Announcements & Others
All times are GMT++8, the time now is 2024-11-24 12:54
Powered by
Discuz!
5.0.0
© 2001-2006
Comsenz Inc.
Processed in 0.010005 second(s), 8 queries , Gzip enabled
TOP
Clear Cookies
-
Contact Us
-
CnPack Website
-
Archiver
-
WAP
Member's CP Home
Edit Profile
Credits Transaction
Public User Groups
Buddy List
Main
Page Views
User Agents
Posts History
Top Forums
Top Threads
Post Ranking
Credit Ranking
Online Time
Team
Moderation Stats