You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在多次拉伸绘制到EMF时复用Bitmap?

在EMF中复用拉伸后的TBitmap32以减小文件体积

我需要将同一张大尺寸的TBitmap32多次绘制到EMF文件中,每次绘制的偏移位置和目标尺寸都不同。

采用常规方式绘制(案例1)时,显示效果正常,但EMF文件体积异常庞大——原因是每次StretchBlt操作都会在EMF中存储一份新的位图副本。

我尝试过先将位图放入兼容DC再复用(案例2),但结果和案例1一样,文件体积还是39MB,并没有实现位图复用。

用图案画刷的方式(案例3)能大幅缩小文件体积(仅3.9MB),但绘制效果异常,而且图案画刷无法实现独立的缩放控制。

示例代码

procedure CreateStretchedBitmapEMF(aMode: Integer; const aMetafilePath: string);
var
  Metafile: TMetafile;
  MetafileCanvas: TMetafileCanvas;
  Bitmap32: TBitmap32;
begin
  Metafile := TMetafile.Create;
  Metafile.Width := 800;
  Metafile.Height := 600;
  MetafileCanvas := TMetafileCanvas.Create(Metafile, 0);

  Bitmap32 := TBitmap32.Create;
  Bitmap32.LoadFromFile('sample.bmp'); // 1000x1000px

  case aMode of
    1:  // 效果正常,但文件体积39MB
        for var i := 0 to 9 do
          StretchBlt(MetafileCanvas.Handle, i * 60, i * 40, 100, 100, Bitmap32.Handle, 0, 0, Bitmap32.Width, Bitmap32.Height, SRCCOPY);
    2:  // 效果正常,但文件体积39MB
        begin
          var TempBitmap := TBitmap.Create;
          TempBitmap.PixelFormat := pf32bit;
          TempBitmap.Width := Bitmap32.Width;
          TempBitmap.Height := Bitmap32.Height;
          Bitmap32.DrawTo(TempBitmap.Canvas.Handle, 0, 0);

          var CompatibleDC: HDC := CreateCompatibleDC(MetafileCanvas.Handle);
          var OldBitmap: HGDIOBJ := SelectObject(CompatibleDC, TempBitmap.Handle);
          for var i := 0 to 9 do
            StretchBlt(MetafileCanvas.Handle, i * 60, i * 40, 100, 100, CompatibleDC, 0, 0, TempBitmap.Width, TempBitmap.Height, SRCCOPY);
          SelectObject(CompatibleDC, OldBitmap);
          DeleteDC(CompatibleDC);
        end;
    3:  // 文件体积3.9MB,但绘制效果异常
        begin
          var TempBitmap := TBitmap.Create;
          TempBitmap.PixelFormat := pf32bit;
          TempBitmap.Width := Bitmap32.Width;
          TempBitmap.Height := Bitmap32.Height;
          Bitmap32.DrawTo(TempBitmap.Canvas.Handle, 0, 0);

          var PatternBrush := CreatePatternBrush(TempBitmap.Handle);
          var OldBrush := SelectObject(MetafileCanvas.Handle, PatternBrush);

          for var i := 0 to 9 do
          begin
            SetRectRgn(PatternBrush,  0,  0, 100, 100);
            FillRect(MetafileCanvas.Handle, Rect(i * 60, i * 40, i * 60 + 100, i * 40 + 100), PatternBrush);
          end;

          SelectObject(MetafileCanvas.Handle, OldBrush);
          DeleteObject(PatternBrush);
        end;
  end;

  Bitmap32.Free;
  MetafileCanvas.Free;
  Metafile.SaveToFile(aMetafilePath);
  Metafile.Free;
end;

各案例效果

  • 案例1/2:绘制效果正常,但文件体积随绘制次数增长(即使源位图相同)
    案例1/2正常绘制效果
  • 案例3:文件体积极小,但绘制效果异常
    案例3异常绘制效果

请问是否存在某种方法可以在EMF中复用拉伸后的位图?


内容的提问来源于stack exchange,提问作者Kromster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 20:42:16