delphi – Windows图元文件的维度是否有限制?
我正在创建一些.wmf文件,但其中一些似乎已损坏,无法显示在任何图元文件查看器中.经过一番试错,我发现问题是由他们的尺寸造成的.如果我通过一个因素缩放相同的图形来减小尺寸,那么它将被显示出来.
现在,我想知道绘图的大小是否有限制,或者问题是其他的.我知道这些文件有一个16位的数据结构,所以我猜测每个维度的限制将是2 ^ 16个单位(如果签名则为2 ^ 15).但是在我的测试中,它是25,000左右.所以我不能依赖这个值,因为限制可以在任何东西(宽度*高度可能,或者也许绘图的分辨率可能会影响它).我找不到有关描述这个的.wmf文件的可靠资源. 以下是显示问题的示例代码: procedure DrawWMF(const Rect: TRect; const Scale: Double; FileName: string); var Metafile: TMetafile; Canvas: TMetafileCanvas; W,H: Integer; begin W := Round(Rect.Width * Scale); H := Round(Rect.Height * Scale); Metafile := TMetafile.Create; Metafile.SetSize(W,H); Canvas := TMetafileCanvas.Create(Metafile,0); Canvas.LineTo(W,H); Canvas.Free; Metafile.SaveToFile(FileName); Metafile.Free; end; procedure TForm1.Button1Click(Sender: TObject); const Dim = 40000; begin DrawWMF(Rect(0,Dim,Dim),1.0,'Original.wmf'); DrawWMF(Rect(0,0.5,'Scaled.wmf'); try Image1.Picture.LoadFromFile('Original.wmf'); except Image1.Picture.Assign(nil); end; try Image2.Picture.LoadFromFile('Scaled.wmf'); except Image2.Picture.Assign(nil); end; end; PS:我知道设置Metafile.Enhanced为True并将其保存为.emf文件将解决问题,但生成文件的目标应用程序不支持增强型图元文件. 编辑: 主要问题是关于文件本身,它对每个维度都有一个2 ^ 15的限制.如果绘图的宽度或高度超过此值,则delphi会写入损坏的文件.您可以在Sertac’s answer找到更多的细节. 第二个问题是将文件加载到TImage中.当您想在delphi VCL应用程序中显示图像时,还有另一个限制.这一个是系统依赖的,并且与图形将被绘制的DC的dpi相关. Tom’s answer详细描述.传递0.7作为缩放DrawWMF(上面的代码示例)在我的电脑上再现这种情况.生成的文件可以使用其他图元文件查看器(我使用MS Office Picture Manager)查看,但VCL无法显示,但在加载文件时不会出现异常. 解决方法
你的上限是32767.
跟踪VCL代码,输出文件在TMetafile.WriteWMFStream中被破坏. VCL写入一个 即使尺寸小于32767,“可放置的标题”可能有错误的值(从Tom’s answer读取详细的原因和含义,并给出了答案),但更多的是在以后… 我使用下面的代码找到限制.请注意,GetWinMetaFileBits不会使用增强型图元文件在VCL代码中调用. function IsDimOverLimit(W,H: Integer): Boolean; var Metafile: TMetafile; RefDC: HDC; begin Metafile := TMetafile.Create; Metafile.SetSize(W,H); RefDC := GetDC(0); TMetafileCanvas.Create(Metafile,RefDC).Free; Result := GetWinMetaFileBits(MetaFile.Handle,nil,MM_ANISOTROPIC,RefDC) > 0; ReleaseDC(0,RefDC); Metafile.Free; end; procedure TForm1.Button1Click(Sender: TObject); var i: Integer; begin for i := 20000 to 40000 do if not IsDimOverLimit(100,i) then begin ShowMessage(SysErrorMessage(GetLastError)); // ReleaseDc and freeing meta file does not set any last error Break; end; end; 错误是534(“算术结果超过32位”).显然有一些有符号的整数溢出.一些“mf3216.dll”(“32位到16位元文件转换DLL”)将GetWinMetaFileBits调用期间的错误设置为其导出的ConvertEmfToWmf函数,但不会导致任何有关溢出的文档.关于wmf限制的唯一官方文档是this(其主要内容是“仅在16位可执行文件中使用wmf”)). 如前所述,伪造的“可置换标题”结构可能具有“伪造”值,这可能会阻止VCL正确播放图元文件.具体来说,像VCL知道它们的元文件的维度可能会溢出.您可以在加载图像以便正确显示之后执行简单的理智检查: var Header: TEnhMetaHeader; begin DrawWMF(Rect(0,'Scaled.wmf'); try Image1.Picture.LoadFromFile('Original.wmf'); if (TMetafile(Image1.Picture.Graphic).Width < 0) or (TMetafile(Image1.Picture.Graphic).Height < 0) then begin GetEnhMetaFileHeader(TMetafile(Image1.Picture.Graphic).Handle,SizeOf(Header),@Header); TMetafile(Image1.Picture.Graphic).Width := MulDiv(Header.rclFrame.Right,Header.szlDevice.cx,Header.szlMillimeters.cx * 100); TMetafile(Image1.Picture.Graphic).Height := MulDiv(Header.rclFrame.Bottom,Header.szlDevice.cy,Header.szlMillimeters.cy * 100); end; ... (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |