使用GDI +旋转的图形看起来比原始图形大

时间:2019-01-25 09:33:19

标签: delphi rotation gdi+ scaling

这是我使用GDI +绘制姿态指示器的实验。

只要我用

image.Canvas.Draw(-25, -410-slider1.Position * 4, horizonBitmap);

horizonBitmap 1:1传输到image

但是当我尝试通过GDI +旋转来传输图像时,它出现在image上大约大0.75倍,我必须使用

Matrix.Scale(SCALE_FACTOR, SCALE_FACTOR);

然后在各处除以SCALE_FACTOR

我做错了什么?

horizon.bmp是350 x 1120像素。

下面是AI单元的完整代码。

unit AIMainform;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls, Vcl.ComCtrls, Vcl.ExtCtrls, Winapi.GDIPOBJ, Winapi.GDIPAPI;

type
  TForm1 = class(TForm)
    procedure FormPaint(Sender: TObject);
  private
    image: TImage;
    slider1: TTrackBar;
    slider2: TTrackBar;
    slider3: TTrackBar;
    horizonGPImage: TGPImage;
    horizonBitmap: TBitmap;
    bezelBitmap: TBitmap;
    headingBitmap: TBitmap;
    wingsBitmap: TBitmap;
    PitchAngle: Double;
    RollAngle: Double;
    YawAngle: Double;
    procedure slider1_Scroll(Sender: TObject);
    procedure slider2_Scroll(Sender: TObject);
    procedure slider3_Scroll(Sender: TObject);
    procedure drawRotated(rotAngle: Integer);
  protected
    procedure DoCreate(); override;
  public
    destructor Destroy(); override;
  end;

var
  Form1: TForm1;

implementation

uses
  System.Math;

{$R *.dfm}

procedure TForm1.DoCreate();
var
  s: string;
begin
  inherited;
  image := TImage.Create(Self);
  image.Parent := Self;
  image.SetBounds(0, 0, 300, 300);
  image.Canvas.Brush.Color := clBlack;
  image.Canvas.Pen.Color := clBlack;
  image.Canvas.FillRect(Rect(0,0,image.Width, image.Height));

  slider1 := TTrackBar.Create(Self);
  slider1.Parent := Self;
  slider1.Name := 'slider1';
  slider1.Orientation := trVertical;
  slider1.SetBounds(328, 21, 45, 190);
  slider1.Max := 90;
  slider1.Min := -90;
  slider1.TabOrder := 1;
  slider1.OnChange := slider1_Scroll;

  slider2 := TTrackBar.Create(Self);
  slider2.Parent := Self;
  slider2.Name := 'slider2';
  slider2.SetBounds(26, 329, 190, 45);
  slider2.Max := 180;
  slider2.Min := -180;
  slider2.TabOrder := 2;
  slider2.OnChange := slider2_Scroll;

  slider3 := TTrackBar.Create(Self);
  slider3.Parent := Self;
  slider3.Name := 'slider3';
  slider3.SetBounds(226, 329, 147, 45);
  slider3.Max := 180;
  slider3.Min := -180;
  slider3.TabOrder := 3;
  slider3.OnChange := slider3_Scroll;

  Cursor := crHandPoint;

  horizonBitmap := TBitmap.Create();
  horizonBitmap.LoadFromFile('horizon.bmp');

  bezelBitmap := TBitmap.Create();
  bezelBitmap.LoadFromFile('bezel.bmp');
  bezelBitmap.Transparent := True;
  bezelBitmap.TransparentColor := clYellow;

  headingBitmap := TBitmap.Create();
  headingBitmap.LoadFromFile('heading.bmp');
  headingBitmap.Transparent := True;
  headingBitmap.TransparentColor := clBlack;

  wingsBitmap := TBitmap.Create();
  wingsBitmap.LoadFromFile('wings.bmp');
  wingsBitmap.Transparent := True;
  wingsBitmap.TransparentColor := clYellow;

  horizonGPImage := TGPImage.Create('horizon.bmp');

  PitchAngle := 0;
  RollAngle := 0;
  YawAngle := 0;

  //ptBoule := Point(-25, -410); //Ground-Sky initial location
  //ptHeading := Point(-592, 150); // Heading ticks
  //ptRotation := Point(150, 150); // Point of rotation

  DoubleBuffered := True;
end;

destructor TForm1.Destroy();
begin
  horizonGPImage.Free();
  inherited;
end;

procedure TForm1.slider1_Scroll(Sender: TObject);
begin
  PitchAngle := slider1.Position;
  RollAngle := DegToRad(slider2.Position);
  YawAngle := DegToRad(slider3.Position);
  Invalidate();
end;

procedure TForm1.slider2_Scroll(Sender: TObject);
begin
  PitchAngle := slider1.Position;
  RollAngle := DegToRad(slider2.Position);
  YawAngle := DegToRad(slider3.Position);
  Invalidate();
end;

procedure TForm1.slider3_Scroll(Sender: TObject);
begin
  PitchAngle := slider1.Position;
  RollAngle := DegToRad(slider2.Position);
  YawAngle := DegToRad(slider3.Position);
  Invalidate();
end;

procedure TForm1.drawRotated(rotAngle: Integer);
const
  SCALE_FACTOR = 0.75;
var
  GPGraphics: TGPGraphics;
  Matrix: TGPMatrix;
  cx, cy: Single;
begin
  GPGraphics :=  TGPGraphics.Create(image.Canvas.Handle);
  Matrix := TGPMatrix.Create;
  try
    //Matrix.Translate(0, 0);
    Matrix.Scale(SCALE_FACTOR, SCALE_FACTOR);
    cx := image.Width div 2;
    cy := image.Height div 2;
    Matrix.RotateAt(rotAngle, MakePoint(cx / SCALE_FACTOR, cy / SCALE_FACTOR));
    GPGraphics.SetTransform(Matrix);
    GPGraphics.DrawImage(horizonGPImage, -35, (-410-slider1.Position * 4) / SCALE_FACTOR);
  finally
    Matrix.Free();
    GPGraphics.Free();
  end;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  inherited;
  //image.Canvas.Draw(-25, -410-slider1.Position * 4, horizonBitmap);
  drawRotated(slider2.Position);
  //0..1260
  image.Canvas.Draw(-592-slider3.Position * 4, 150, headingBitmap);
  image.Canvas.Draw(0, 0, bezelBitmap);
  image.Canvas.Draw(75, 125, wingsBitmap);
end;

end.

1 个答案:

答案 0 :(得分:11)

它与旋转无关。问题是由于DPI写入图像内部。

在我的实验中,根据需要显示了没有DPI的bmp。当我设置72 DPI分辨率(使用IrfanView程序)时,它将以更大的尺寸绘制。

在DPI设置为120(我的屏幕具有通常96 dpi的125%缩放比例)的情况下,它以1:1绘制。

所以GDIPLus在这里太聪明了-它试图以“正确”的物理尺寸(厘米/英寸)绘制图像。

解决方案可能非常简单-在输出过程中使用带有源图像像素大小的目标矩形参数:

GPGraphics.DrawImage(horizonGPImage, 0, 0,
                     horizonGPImage.GetWidth, horizonGPImage.GetHeight);