Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 将TBitmap存储在TMetaFile中,以便在RTF中平滑缩放,可使图像大小加倍_Delphi_Bitmap_Metafile_Wmf - Fatal编程技术网

Delphi 将TBitmap存储在TMetaFile中,以便在RTF中平滑缩放,可使图像大小加倍

Delphi 将TBitmap存储在TMetaFile中,以便在RTF中平滑缩放,可使图像大小加倍,delphi,bitmap,metafile,wmf,Delphi,Bitmap,Metafile,Wmf,RTF图像支持非常有限(Windows支持,不仅仅在Delphi中),位图和图元文件以外的其他格式也可以工作,但不能通过RichEdit控件正确显示 我注意到的一件事是,当MicrosoftWord图像被复制并粘贴到RTF中时,它会缩放 平滑,而不是手动粘贴图像(作为位图)。 原因是Word在内部以图元文件格式(以及原始图像)保留图像的缩放预览,此缩放版本被复制并粘贴到RTF,显然RTF在RichText editor中缩放时平滑地渲染图元文件图像 这似乎是一个很好的解决方法,在WPF函数中嵌入

RTF图像支持非常有限(Windows支持,不仅仅在Delphi中),位图和图元文件以外的其他格式也可以工作,但不能通过RichEdit控件正确显示

我注意到的一件事是,当MicrosoftWord图像被复制并粘贴到RTF中时,它会缩放 平滑,而不是手动粘贴图像(作为位图)。 原因是Word在内部以图元文件格式(以及原始图像)保留图像的缩放预览,此缩放版本被复制并粘贴到RTF,显然RTF在RichText editor中缩放时平滑地渲染图元文件图像

这似乎是一个很好的解决方法,在WPF函数中嵌入BMP后,我注意到了一个无法回避的问题:生成的WMF是位图大小的两倍。看起来WMF存储了绘画缓冲区或图像的第二个副本

守则:

  procedure DoCopyImage(AGraphic: TGraphic; AWidth, AHeight: Integer);
  var
    mf: TMetafile;
    mfc: TMetafileCanvas;
    r: Cardinal;
  begin
    mf := TMetafile.Create;
    try
      mf.Enhanced := True;
      mf.SetSize(AWidth, AHeight);
      mfc := TMetafileCanvas.Create(mf, 0);
      try
        // set clipping region to a whole image
        r := CreateRectRgn(0, 0, AWidth, AHeight);
        try
          SelectClipRgn(mfc.Handle, r)
        finally
          DeleteObject(r);
        end;

        if (AGraphic.Width = AWidth) and (AGraphic.Height = AHeight) then
          mfc.Draw(0, 0, AGraphic)
        else
          mfc.StretchDraw(Rect(0, 0, AWidth, AHeight), AGraphic);
      finally
        mfc.Free;
      end;
      // Clipboard.Assign(mf);
      mf.SaveToFile('C:\4MB_MetaFile_Why.wmf');
    finally
      mf.Free;
    end;
  end;
我使用TBitmap将其称为TGraphic:

  pic := TPicture.Create;
  pic.LoadFromFile('C:\2MB_24bpp_Bitmap.bmp');
  bmp := Graphics.TBitmap.Create;
  bmp.Assign(pic.Graphic);
  bmp.Dormant; // experimentation
  bmp.FreeImage; // experimentation
  DoCopyImage(bmp, bmp.Width, bmp.Height);

有人能为这种行为找到解释吗?WMF是否与位图一起存储绘制缓冲区?如何防止它?

mf.SaveToFile('C:\4MB\u MetaFile\u Why.wmf')之前添加此代码


mf.SaveToFile('C:\4MB_图元文件_Why.wmf')之前添加此代码


至于为什么您的大小可能不同-一旦绘制到图元文件,您就将保存数据的责任移交给图元文件。输出中的位深度可能不同。我不确定,但我也想知道StretchDraw调用是否最终保存了原始输入,或者是否保存了具有新像素数的位图。如果图像小于拉伸绘制的大小,则调用该调用可以解释差异。元文件中也会有一些开销,这些开销不会出现在保存的位图中,尽管这应该是最小的

你可能想看看这个。该工具将向您显示嵌入图元文件中的不同绘制命令。我尝试了您的代码,并在MetaFileExplorer中查看了生成的图像。嵌入图像的大小在我看来还行。查看EMR_STRETCHBLT.cbbitsrc大小。但是,我确实看到了您报告的尺寸差异,因此有些东西占用了空间

你说:

原因是Word在内部以图元文件格式(以及原始图像)保留图像的缩放预览,此缩放版本被复制并粘贴到RTF,显然RTF在RichText editor中缩放时平滑地渲染图元文件图像

我对这个假设有点怀疑。位图(任何光栅图像)将根据缩放的执行方式显示不同的缩放瑕疵。这本书有一些很好的例子来说明这些差异

将位图写入图元文件时,当图像绘制到屏幕上时,将允许图元文件执行缩放。图元文件图形代码与RTF图形代码使用的不同算法将导致输出看起来不同。但是,图元文件没有什么特殊之处,它不能用普通位图来完成。在这两种情况下,都需要调整原始像素的大小/重新采样

图元文件的用途与嵌入单个位图图像不同。下面是一个很好的例子,解释了其中的一些差异。基本上,如果您定义线条、形状和文本,您可以获得真正平滑的缩放,因为您是在描述图形,而不是存储单个像素


获得一个好看的缩放图像的关键部分是选择正确的缩放例程。我已经在我的应用程序中使用了。标准StretchDraw例程的设计是快速的,而不是高质量的。当我准备在屏幕上画图时,我选择了一个图形32重采样器,它能给我想要的结果。这可能会根据大小而变化。例如,最终输出是否大于或小于输入图像。我将图像大小调整为最终输出大小,然后只绘制而不是StretchDraw。

至于尺寸可能不同的原因-一旦绘制到图元文件,则将保存数据的责任移交给图元文件。输出中的位深度可能不同。我不确定,但我也想知道StretchDraw调用是否最终保存了原始输入,或者是否保存了具有新像素数的位图。如果图像小于拉伸绘制的大小,则调用该调用可以解释差异。元文件中也会有一些开销,这些开销不会出现在保存的位图中,尽管这应该是最小的

你可能想看看这个。该工具将向您显示嵌入图元文件中的不同绘制命令。我尝试了您的代码,并在MetaFileExplorer中查看了生成的图像。嵌入图像的大小在我看来还行。查看EMR_STRETCHBLT.cbbitsrc大小。但是,我确实看到了您报告的尺寸差异,因此有些东西占用了空间

你说:

原因是Word在内部以图元文件格式(以及原始图像)保留图像的缩放预览,此缩放版本被复制并粘贴到RTF,显然RTF在RichText editor中缩放时平滑地渲染图元文件图像

我对这个假设有点怀疑。位图(任何光栅图像)将根据缩放的执行方式显示不同的缩放瑕疵。这本书有一些很好的例子来说明这些差异

将位图写入图元文件时,当图像绘制到屏幕上时,将允许图元文件执行缩放。图元文件图形代码与RTF图形代码使用的不同算法将导致输出看起来不同。但是,图元文件没有什么特殊之处,它不能用普通位图来完成。在这两种情况下,都需要调整原始像素的大小/重新采样

元文件的真正目的不是仅仅嵌入一个位
  mf.MMHeight := Round(mf.Height / Screen.PixelsPerInch * 2540);
  mf.MMWidth := Round(mf.Width / Screen.PixelsPerInch * 2540);