Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
724 views
in Technique[技术] by (71.8m points)

rotation - Scale a rotated image with zoom center (Delphi, fmx)

I am trying to build a seemingly simple GUI in which a Timage can be panned, zoomed, and rotated. The zooming and rotating should be done at/around a defined zoom and rotation center position.

I am first trying this on Windows. All is working fine now, except that when the image has a rotation, the zoom at a specific zoom center does not work (the zoom center moves around). It does work fine when the rotationangle=0. I can indulge again in the math to get correct image position equations, but first wanted to ask here if someone has maybe tackled this problem before.

For the code below to work do the following:

  • start a new blank fmx multidevice project
  • Add a TPanel aligned to client
  • Add a TImage, fill its MultiResBitmap property with any image
  • Set the hittest property of the image to false (panel input used for zoom)

In the minimum code sample below the image is rotated in the form's FormCreate procedure (or not to see how the zooming at a certain point is supposed to work). Zooming is done at the mouse position when scrolling the wheel on the mouse in the Panel1MouseWheel procedure.

So what would need to be adjusted are only the two lines below the comment // correction for image position when scaling

procedure TForm1.FormCreate(Sender: TObject);
begin
//  Image1.RotationAngle := 0;
  Image1.RotationAngle := 30;
end;

procedure TForm1.Panel1MouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; var Handled: Boolean);
var zoom_center: TPointF;
    new_scale,old_scale: single;
    P1,P2: TPointF;
begin
  // Scaling (mousewheel)
  if shift = [] then
  begin
    zoom_center := screen.MousePos - ClienttoScreen(Image1.LocalToAbsolute(PointF(0,0)));

    old_scale := Image1.Scale.X;
    if WheelDelta>=0 then new_scale := old_scale * (1 + (WheelDelta / 120)/5)
                     else new_scale := old_scale / (1 - (WheelDelta / 120)/5);

    Image1.Scale.X := new_scale;
    Image1.Scale.Y := new_scale;

    // correction for image position when scaling
    Image1.Position.X := Image1.Position.X + zoom_center.x * (1-new_scale/old_scale);
    Image1.Position.Y := Image1.Position.Y + zoom_center.y * (1-new_scale/old_scale);
  end;
end;
question from:https://stackoverflow.com/questions/66048612/scale-a-rotated-image-with-zoom-center-delphi-fmx

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I'm assuming that you want to zoom to the cursor such that the image pixel at the cursor doesn't move. Your code didn't do that for me even when angle was 0. There are a couple of problems with your code. Firstly how you compute the zoom_center and secondly how you correct for image position. Here's the corrected code with your code commented out. It seems to work when rotation angle is 0 or 30.

procedure TForm1.Panel1MouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; var Handled: Boolean);
var zoom_center: TPointF;
    new_scale,old_scale: single;
    P1,P2: TPointF;
begin
  // Scaling (mousewheel)
  if shift = [] then
  begin
    //zoom_center := screen.MousePos - ClienttoScreen(Image1.LocalToAbsolute(PointF(0,0)));
    zoom_center := ScreenToClient(Screen.MousePos) - Panel1.Position.Point;

    old_scale := Image1.Scale.X;
    if WheelDelta>=0 then new_scale := old_scale * (1 + (WheelDelta / 120)/5)
                     else new_scale := old_scale / (1 - (WheelDelta / 120)/5);

    Image1.Scale.X := new_scale;
    Image1.Scale.Y := new_scale;

    // correction for image position when scaling
    //Image1.Position.X := Image1.Position.X + zoom_center.x * (1-new_scale/old_scale);
    //Image1.Position.Y := Image1.Position.Y + zoom_center.y * (1-new_scale/old_scale);

    Image1.Position.Point := zoom_center - (new_scale * (zoom_center - Image1.Position.Point) / old_scale);
  end;
end;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...