Delphi 将TBitmap存储在TMetaFile中,以便在RTF中平滑缩放,可使图像大小加倍
RTF图像支持非常有限(Windows支持,不仅仅在Delphi中),位图和图元文件以外的其他格式也可以工作,但不能通过RichEdit控件正确显示 我注意到的一件事是,当MicrosoftWord图像被复制并粘贴到RTF中时,它会缩放 平滑,而不是手动粘贴图像(作为位图)。 原因是Word在内部以图元文件格式(以及原始图像)保留图像的缩放预览,此缩放版本被复制并粘贴到RTF,显然RTF在RichText editor中缩放时平滑地渲染图元文件图像 这似乎是一个很好的解决方法,在WPF函数中嵌入BMP后,我注意到了一个无法回避的问题:生成的WMF是位图大小的两倍。看起来WMF存储了绘画缓冲区或图像的第二个副本 守则:Delphi 将TBitmap存储在TMetaFile中,以便在RTF中平滑缩放,可使图像大小加倍,delphi,bitmap,metafile,wmf,Delphi,Bitmap,Metafile,Wmf,RTF图像支持非常有限(Windows支持,不仅仅在Delphi中),位图和图元文件以外的其他格式也可以工作,但不能通过RichEdit控件正确显示 我注意到的一件事是,当MicrosoftWord图像被复制并粘贴到RTF中时,它会缩放 平滑,而不是手动粘贴图像(作为位图)。 原因是Word在内部以图元文件格式(以及原始图像)保留图像的缩放预览,此缩放版本被复制并粘贴到RTF,显然RTF在RichText editor中缩放时平滑地渲染图元文件图像 这似乎是一个很好的解决方法,在WPF函数中嵌入
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);