代码之家  ›  专栏  ›  技术社区  ›  Paul

用gdi+旋转的图形比原始图形大

  •  5
  • Paul  · 技术社区  · 7 年前

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

    只要我用

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

    horizonBitmap 1:1转移到 image .

    但是当我尝试用gdi+旋转传输图像时,它出现在 形象 大约大0.75倍,我必须使用

    Matrix.Scale(SCALE_FACTOR, SCALE_FACTOR);
    

    然后除以 SCALE_FACTOR 到处都是。

    我做错了什么?

    horizon.bmp 是350 x 1120像素。

    下面是人工智能单元的完整代码。

    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 回复  |  直到 7 年前
        1
  •  11
  •   MBo    7 年前

    它与旋转无关。问题是由于DPI写在图像中。

    在我的实验中,没有dpi的BMP是按需要显示的。当我设置72 dpi分辨率(使用irfanview程序)时,它将以较大的尺寸绘制。

    如果dpi设置为120(我的屏幕比通常的96 dpi具有125%的比例),则绘制比例为1:1。

    因此,gdilus在这里太聪明了——它试图用“正确”的物理尺寸(厘米/英寸)来绘制图像。

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

    GPGraphics.DrawImage(horizonGPImage, 0, 0,
                         horizonGPImage.GetWidth, horizonGPImage.GetHeight);
    
    推荐文章