Scaling the TRotLayer

2019-09-13 00:10发布

问题:

I'm working on graphics32. And I'm using the given component from its examples, the TRotLayer. Basing on the example (Examples/Layers/RotLayer_Ex), the created RotLayer only scales together with the ImgView. If ImgView.Bitmap is not assigned, the RotLayer doesn't scale. So I tinkered the source code, changing it's behavior. I changed the TRotLayer.AdjustTransformation procedure. Here's what I did.

procedure TRotLayer.AdjustTransformation;
var
ScaleX, ScaleY,
ShiftX, ShiftY: Single;
begin
Transformation.Clear;
Transformation.Translate(-BitmapCenter.X, -BitmapCenter.Y);
Transformation.Rotate(0, 0, Angle);
Transformation.Translate(Position.X, Position.Y);
Transformation.Scale(Scale.X, Scale.Y);
Transformation.Translate(Shift.X, Shift.Y);
//  if Scaled and Assigned(LayerCollection) then
//    with LayerCollection do
//    begin
//      GetViewportScale(ScaleX, ScaleY);
//      GetViewportShift(ShiftX, ShiftY);
//      Transformation.Scale(ScaleX, ScaleY);
//      Transformation.Translate(ShiftX, ShiftY);
//    end;
end;

I just ommitted the restriction and simply executed the .Scale procedure. I passed values for Scale.X and Scale.Y and it worked as I expected. The image was resized but now my problem is the positioning. The image moves up or down if I scale it's height then it moves right or left if I scale it's width. I just wanted it to resize and just stay in it's original position. I noticed that the function .Translate can possibly fix my problem but I don't know what to pass in the parameters. Or I don't know how to compute the values to pass.

Anyone can help me with this problem. Thanks.

回答1:

Pseudo code:

  • Calculate the original bounds:

    Transformation.SrcRect := FloatRect(0, 0, Old.Width, Old.Height);

  • Shift the origin to the center of that bounds:

    Transformation.Translate(-0.5 * Old.Width, -0.5 * Old.Height);

  • Rotate around the new origin:

    Transformation.Rotate(0, 0, Degrees);

  • Scale

  • Calculate the new bounds:

    New.Bounds := Transformation.GetTransformedBounds;

  • Shift the origin back to (0, 0) of the new bounds:

    Transformation.Translate(0.5 * New.Width, 0.5 * New.Height);

You might also take a look at Rotate bitmap by real angle for a Graphics32 example (without scaling).