【问题标题】:Zoom image using delphi使用delphi缩放图像
【发布时间】:2010-06-12 09:36:47
【问题描述】:

我正在使用德尔福。我有 TImage,我为其分配了一个位图。

imgmain.Picture.Bitmap := bmpMain;
imgmain.Picture.Bitmap.PixelFormat := pf24bit;

imgmain 是 TImage 的对象,bmpMain 是 TBitmap 的对象

我想放大我的图像。我的表单上有一个轨迹栏,当我点击轨迹栏时,图像应该会放大。我该怎么办?
谢谢你。

编辑:
我在here 找到了一些解决方案,它可以工作,但它会破坏我的形象。

【问题讨论】:

    标签: delphi timage


    【解决方案1】:

    您引用的代码设置了从一个坐标空间到另一个坐标空间的转换,我没有注意到任何会在那里剪切/裁剪您的图像的东西。但是,我宁愿拥有易于理解的线性缩放,而不是具有反比缩放因子。另外,我认为没有理由根据比例因子切换地图模式,我会像这样修改SetCanvasZoomFactor

    procedure SetCanvasZoomPercent(Canvas: TCanvas; AZoomPercent: Integer);
    begin
      SetMapMode(Canvas.Handle, MM_ISOTROPIC);
      SetWindowExtEx(Canvas.Handle, 100, 100, nil);
      SetViewportExtEx(Canvas.Handle, AZoomPercent, AZoomPercent, nil);
    end;
    

    通过 TrackBar 缩放的位图加载到 TImage 的简化(无错误检查)工作示例可能如下所示。请注意,上述函数是内联在 TrackBar 的 OnChange 事件中的。

    type
      TForm1 = class(TForm)
        imgmain: TImage;
        TrackBar1: TTrackBar;
        Label1: TLabel;
        procedure FormCreate(Sender: TObject);
        procedure TrackBar1Change(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        bmpmain: TBitmap;
      [..]
    
    [...]
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      bmpmain := TBitmap.Create;
      bmpmain.LoadFromFile(ExtractFilePath('samplebitmap.bmp');
      bmpmain.PixelFormat := pf32bit; // No significance, just seems faster here than pf24bit
    
      TrackBar1.Min := 10;
      TrackBar1.Max := 200;
      TrackBar1.Frequency := 10;
      TrackBar1.PageSize := 10;
      TrackBar1.Position := 100; // Fires OnChange
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
     bmpmain.Free;
    end;
    
    procedure TForm1.TrackBar1Change(Sender: TObject);
    var
      Zoom, x, y: Integer;
    begin
      Zoom := TrackBar1.Position;
      if not (Visible or (Zoom = 100)) or (Zoom = 0) then
        Exit;
    
      SetMapMode(imgmain.Canvas.Handle, MM_ISOTROPIC);
      SetWindowExtEx(imgmain.Canvas.Handle, 100, 100, nil);
      SetViewportExtEx(imgmain.Canvas.Handle, Zoom, Zoom, nil);
      x := imgmain.Width * 50 div Zoom - bmpmain.Width div 2;
      y := imgmain.Height * 50 div Zoom - bmpmain.Height div 2;
      imgmain.Canvas.Draw(x, y, bmpmain);
      if (x > 0) or (y > 0) then begin
        imgmain.Canvas.Brush.Color := clWhite;
        ExcludeClipRect(imgmain.Canvas.Handle, x, y, x + bmpmain.Width, y + bmpmain.Height);
        imgmain.Canvas.FillRect(imgmain.Canvas.ClipRect);
      end;
    
      Label1.Caption := 'Zoom: ' + IntToStr(TrackBar1.Position) + '%';
    end;
    


    edit:与滚动框中的 TImage 相同的代码;

    type
      TForm1 = class(TForm)
        TrackBar1: TTrackBar;
        Label1: TLabel;
        ScrollBox1: TScrollBox;
        imgmain: TImage;
        procedure FormCreate(Sender: TObject);
        procedure TrackBar1Change(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        bmpmain: TBitmap;
      [...]
    [...]
    
    const
      FULLSCALE = 100;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      imgmain.Left := 0;
      imgmain.Top := 0;
    
      bmpmain := TBitmap.Create;
      bmpmain.LoadFromFile(ExtractFilePath(Application.ExeName) + '610x.bmp');
      bmpmain.PixelFormat := pf32bit;
    
      TrackBar1.Min := FULLSCALE div 10;   // %10
      TrackBar1.Max := FULLSCALE * 2;      // %200
      TrackBar1.PageSize := (TrackBar1.Max - TrackBar1.Min) div 19;
      TrackBar1.Frequency := TrackBar1.PageSize;
      TrackBar1.Position := FULLSCALE;
    end;
    
    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      bmpmain.Free;
    end;
    
    procedure TForm1.TrackBar1Change(Sender: TObject);
    var
      Zoom: Integer;
    begin
      Zoom := TrackBar1.Position;
      if not (Visible or (Zoom = FULLSCALE)) or (Zoom = 0) then
        Exit;
    
      SetMapMode(imgmain.Canvas.Handle, MM_ISOTROPIC);
      SetWindowExtEx(imgmain.Canvas.Handle, FULLSCALE, FULLSCALE, nil);
      SetViewportExtEx(imgmain.Canvas.Handle, Zoom, Zoom, nil);
    
      imgmain.Width := Round(bmpmain.Width * Zoom / FULLSCALE);
      imgmain.Height := Round(bmpmain.Height * Zoom / FULLSCALE);
      if Assigned(imgmain.Picture.Graphic) then begin
        imgmain.Picture.Graphic.Width := imgmain.Width;
        imgmain.Picture.Graphic.Height := imgmain.Height;
      end;
      imgmain.Canvas.Draw(0, 0, bmpmain);
    
      Label1.Caption := 'Zoom: ' +
          IntToStr(Round(TrackBar1.Position / FULLSCALE * 100)) + '%';
    end;
    

    【讨论】:

    • @Sertac Thanx,它比我使用的代码要好。但是你能告诉我 line 的意义是什么:imgmain.Canvas.Draw(x,y,bmpmain);因为,在这条线之前我们没有改变 bmpmain 那么为什么我们将它绘制到 imgmain 呢?通过切割图像的文字,我的意思是缩放后它并没有增加图像的实际长度,但我想要我也没有从这段代码中得到的完整图像。还有一件事,我已经把图片放到了TScrollBar,这是造成问题了吗?
    • @Himadri - 我们从不改变 bmpmain,我们只是改变 TImage 画布上的逻辑单元和设备单元之间的关系。让我举个例子;假设您有一个宽度为 96px 的位图,如果您的 Screen.PixelsPerInch 也是 96px imgmain.Canvas.Draw(x,y,bmpmain) 将在 TImage 上绘制一个 1" 宽度的位图。在各向同性地图模式下,如果您将水平窗口范围设置为 100,将水平视口范围设置为200,您是说 x 轴上的 100 个逻辑单元将用 200px 表示。因此,相同的调用将绘制位图 192px 或 2" 或两倍宽度。
    • @Himadri- 当然,您可以将 TImage 放在滚动框中。每当您更改缩放比例时,在绘制图像之前,您应该计算并设置图像的新宽度/高度。对于上面的示例,它将是 f.i. imgmain.Width := bmpmain.Width * Zoom div 100;
    • @Sertac 我写了这一行,但它没有改变 imgmain 的宽度。我错过了设置一些属性吗?我的切图问题还没解决。
    • @Himadri - 我想我明白你的意思了。似乎如果已经为图像的图片分配了图形,则设置图像的大小不会影响图形的大小。我已经更新了答案,请尝试使用新代码。
    猜你喜欢
    • 2021-05-08
    • 2010-12-30
    • 2021-07-25
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2011-05-12
    相关资源
    最近更新 更多