我正在尝试将RotationLayer与常规TBitmapLayer结合使用,以便能够使用ImgView32层。
所以我的想法是:
所以基本上:将图像从实际图层移动到临时旋转图层,在那里旋转,然后,完成后,将旋转后的图像移回BitmapLayer ......
所以最后,我的逻辑似乎有效,除了我需要使用另一个SO问题(链接波纹)中提供的函数手动对BitmapLayer进行实际旋转。因为看起来rotateLayer实际上并没有在它的Bitmap中旋转图像。它似乎只是显示它旋转...
现在我的问题是:
请协助我解决这3个问题。
目前的工作代码是:
procedure TMainForm.myrotMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
l,r,t,b:single;
flrect:TFloatRect;
begin
ro:=TRotlayer.Create(imgView.Layers);
ro.Bitmap:=TBitmap32.Create;
with ro.Bitmap do
begin
BeginUpdate;
ro.Bitmap.Assign((Selection as TBitmapLayer).Bitmap);
TLinearResampler.Create(ro.Bitmap);
//ensure good looking edge, dynamic alternative to SetBorderTransparent
TCustomResampler(ro.Bitmap.Resampler).PixelAccessMode := pamTransparentEdge;
ro.BitmapCenter := FloatPoint(-(Selection as TBitmapLayer).Location.Left, -(Selection as TBitmapLayer).Location.Top);
// MasterAlpha := 200;
FrameRectS(BoundsRect, $FFFFFFFF);
DrawMode := dmBlend;
EndUpdate;
Changed;
end;
ro.Scaled := True;
(Selection as TBitmapLayer).Bitmap.Assign(ro.Bitmap);
end;
procedure TMainForm.myrotChange(Sender: TObject);
begin
ro.Angle := myRot.Position;
(Selection as TBitmapLayer).Bitmap.Assign(ro.Bitmap);
end;
procedure TMainForm.myrotMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
bmx:=TBitmap32.Create;
bmx.Assign((Selection as TBitmapLayer).Bitmap);
RotateBitmap(bmx, -(Round(ro.Angle)), false, clWhite32, true);
(Selection as TBitmapLayer).Bitmap.Assign(bmx);
bmx.Free;
ro.Free;
end;
中选取RotateBitmap函数
旋转透明图像时也会出现问题...使用上面的代码自行测试并加载一些透明的PNG,您就会明白问题。
答案 0 :(得分:0)
答案(这些问题应该是单独的问题,但由于它们密切相关,我会处理它们。希望我不会被钉死。)
调整TBitmapLayer的大小以适应旋转的图像。
您可以通过设置TBitmapLayer.Location在MyRotMouseUp过程中执行此操作。旋转的位图具有正确的Width
和Height
属性。有关示例,请参阅下面的代码。如图所示设置位置也会将其保持在ImgView
如何将TRotationLayer
准确定位在TBitmapLayer
的顶部,并将旋转中心放在图像的中心。
TRotationLayer
定位Position
属性。位图旋转中心使用BitmapCenter
属性单独设置
定位TRotLayer
与定位其他图层(f.ex。TBitmapLayer
)的不同之处在于,它使用Position: TFloatPoint
字符与Location: TFloatRect
用于其他图层。 Position
定义图层的中心点
与其他图层一样,参考坐标系取决于Scaled
属性。如果Scaled=False
(默认值),则引用TImgView32
边界。如果您在TimgView32.Bitmap
中加载了较大的图像,并使用滚动条滚动图像,则TRotLayer
不随图像移动。另一方面,如果Scaled=True
TImgView32.Bitmap
引用TRotLayer
,则Scaled
会在滚动时跟随图像。
要将旋转图层绑定到位图播放器以便它们一起滚动,请将两个图层True
属性设置为Location
,然后更改设置Position
和myRotMouseDown()
的方式。我已经对代码添加了必要的修改。
在旋转图层和原始位图之间来回分配位图时,图像颜色会发生变化。
是的,我清楚地看到您对原始代码的意思。这就是为什么我在评论中建议保持原始图像清洁(未旋转)并跟踪角度,以便原始图像可以用于仅显示一个变换。仍然有一些可见的退化,但它并没有堆积到无法使用。
在bmo: TBitmap32
:原始图片(代码中的rol: TRotationLayer
)被分配给旋转图层(bml: TBitmapLayer
)位图。 Visible := False
被隐藏(myRotChange()
)。这里没有分配任何其他位图。
在myRotMouseUp()
处:更改旋转图层角度,并使用相同的角度数据更新表格全局变量。这里没有分配任何其他位图。
在bml: TBitmapLayer.Bitmap
处:原始图像被分配给位图图层(RotateBitmap()
),并使用bml.Location
过程使用表单中存储的角度旋转该位图。更新bmx: TBitmap32
以适应旋转的图像。此处未分配任何其他位图(不需要bml
)。 RotateBitmap()
再次可见。
我还建议不要保存旋转的图像,而只是保存角度。这样,原始图像可以保持不变,并且可以在需要时以保存的角度显示。
代码
(没有必要更改 private
bmo: TBitmap32; // original bitmap
bml: TBitmapLayer;
// bmx: TBitmap32;
rol: TRotLayer;
roa: single; // rotation angle
所以我不在此处包括)
表格字段
procedure TForm9.FormCreate(Sender: TObject);
var
dstr, srcr: TRect;
png: TPortableNetworkGraphic32;
begin
png := TPortableNetworkGraphic32.Create;
png.LoadFromFile('c:\tmp\imgs\arr-2.png');
bmo:= TBitmap32.Create;
bmo.Assign(png);
// bmo.LoadFromFile('c:\tmp\imgs\arr.bmp');
png.Free;
bml := TBitmapLayer.Create(ImgView.Layers);
bml.Bitmap.SetSize(bmo.Width, bmo.Height);
bml.Scaled := True; // !!! Changed to True for synching with rol !!!
//bml.Location := FloatRect(
// (ImgView.Width - bml.Bitmap.Width) * 0.5,
// (ImgView.Height - bml.Bitmap.Height)* 0.5,
// (ImgView.Width + bml.Bitmap.Width) * 0.5,
// (ImgView.Height + bml.Bitmap.Height)* 0.5);
// !!! Change follows to synch scrolling of bml and rol
bml.Location := FloatRect(
(ImgView.Bitmap.Width - bml.Bitmap.Width) * 0.5,
(ImgView.Bitmap.Height - bml.Bitmap.Height)* 0.5,
(ImgView.Bitmap.Width + bml.Bitmap.Width) * 0.5,
(ImgView.Bitmap.Height + bml.Bitmap.Height)* 0.5);
dstr := Rect(0, 0, bmo.Width, bmo.Height);
srcr := Rect(0, 0, bmo.Width, bmo.Height);
bml.Bitmap.DrawMode := dmBlend;
bml.Bitmap.Draw(dstr, srcr, bmo.Handle);
end;
procedure TForm9.FormDestroy(Sender: TObject);
begin
bmo.Free;
end;
procedure TForm9.myRotChange(Sender: TObject);
begin
rol.Angle := myRot.Position * 3.6;
roa := rol.Angle;
// (Selection as TBitmapLayer).Bitmap.Assign(ro.Bitmap);
end;
procedure TForm9.myRotMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
l, r, t, b: single;
flrect: TFloatRect;
begin
rol := TRotLayer.Create(ImgView.Layers);
rol.Scaled := True; // !!! Added for synching with bml
with rol.Bitmap do
begin
BeginUpdate;
Assign(bmo);
// rol.Position := FloatPoint(ImgView.Width * 0.5, ImgView.Height* 0.5);
// !!! Change follows to synch scrolling of bml and rol
rol.Position := FloatPoint(
(bml.Location.Right + bml.Location.Left)*0.5,
(bml.Location.Bottom + bml.Location.Top)*0.5);
// rol.Bitmap.Assign((Selection as TBitmapLayer).Bitmap);
TLinearResampler.Create(rol.Bitmap);
// ensure good looking edge, dynamic alternative to SetBorderTransparent
TCustomResampler(rol.Bitmap.Resampler).PixelAccessMode := pamTransparentEdge;
// ro.BitmapCenter := FloatPoint(-(Selection as TBitmapLayer).Location.Left,
// -(Selection as TBitmapLayer).Location.Top);
rol.BitmapCenter := FloatPoint(Width * 0.5, Height * 0.5);
// MasterAlpha := 200;
FrameRectS(BoundsRect, $FFFFFFFF);
DrawMode := dmBlend;
rol.Angle := roa;
EndUpdate;
Changed;
end;
bml.Visible := False;
// (Selection as TBitmapLayer).Bitmap.Assign(ro.Bitmap);
end;
procedure TForm9.myRotMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
bml.Bitmap.Assign(bmo);
RotateBitmap(bml.Bitmap, -(Round(roa)), True, clWhite32, True);
//bml.Location := FloatRect(
// (ImgView.Width - bml.Bitmap.Width) * 0.5,
// (ImgView.Height - bml.Bitmap.Height)* 0.5,
// (ImgView.Width + bml.Bitmap.Width) * 0.5,
// (ImgView.Height + bml.Bitmap.Height)* 0.5);
// !!! Change follows to synch scrolling of bml and rol
bml.Location := FloatRect(
(ImgView.Bitmap.Width - bml.Bitmap.Width) * 0.5,
(ImgView.Bitmap.Height - bml.Bitmap.Height)* 0.5,
(ImgView.Bitmap.Width + bml.Bitmap.Width) * 0.5,
(ImgView.Bitmap.Height + bml.Bitmap.Height)* 0.5);
bml.Bitmap.DrawMode := dmBlend;
rol.Free;
bml.Visible := True;
end;
方法
{{1}}
最后一些截图:首先,没有旋转图像就好了。第二次旋转,边缘不是像素完美,但合理。