2011-09-07 211 views
6

我有一个例程procedure DrawStuff(ACanvas: TCanvas; const ARect: TRect),它将某些东西绘制到TCanvas上的指定矩形。目前我用PaintBox的画布调用DrawStuff。现在我要添加一个Save as选项,其中用户可以从多种文件格式中选择(bmp,wmf,jpg,... - 优选尽可能多的TGraphic后代)以将DrawStuff的结果保存到。将图片保存为各种文件格式

绘制到TMetafile并将其保存为“bla.bmp”或Assign将其保存为TPicture无法正常工作 - 例如,它会生成扩展名为“.bmp”的文件,即不是位图。现在我无法找到一种不涉及特殊外壳的解决方案,每一种文件格式都可以使用:

  • bmp - 使用TBitmap.Canvas
  • wmf/emf:使用TMetafileCanvas
  • 等等,等等

你知道有什么想法我吗?

+2

制作保存BMP,PNG,GIF,JPG等的“统一”例程非常容易,但如果它也包含WMF或EMF,则很难做到,因为后者*矢量图像*格式,而前者是*光栅图像*格式。当然,除非您选择将图像保存为EMF/WMF中嵌入的栅格位图,但在这种情况下,完全可以使用EMF/WMF格式... –

+0

Special-casing wmf/emf会没事的。你能指点一下你提到的统一套路吗? –

+0

PS:我认为绘制到一个图元文件,然后'将它分配给一个'TPicture'可能工作,因为它似乎是像记录的GDI调用的集合。 –

回答

9

我猜“哑”的转换可能会像这样简单:

type 
    TGraphicTypeEnum = (gteBMP, gteJPG, gteTIF, gtePNG); 

procedure SaveGraphicAs(AGraphic : TGraphic; AGraphicType : TGraphicTypeEnum; AFileName : String); 
var vGraphicClass : TGraphicClass; 
    vTargetGraphic : TGraphic; 
    vBmp : TBitmap; 
begin 

    case AGraphicType of 
    gteBMP : vGraphicClass := TBitmap; 
    gtejpg : vGraphicClass := TJPEGImage; 
    gtetif : vGraphicClass := TWICImage; 
    gtepng : vGraphicClass := TPngImage; 
    else 
    // EXIT; or raise... 
    end; 
    if aGraphic is vGraphicClass then //As suggested by Rob Kennedy 
    AGraphic.SaveToFile(AFileName) 
    else 
    begin 
    vBmp := nil; 
    vTargetGraphic := vGraphicClass.Create; 
    try 
     vBmp := TBitmap.Create; 
     vBmp.Assign(AGraphic); 
     vTargetGraphic.Assign(vBmp); 
     vTargetGraphic.SaveToFile(aFileName); 
    finally 
     vTargetGraphic.Free; 
     vBmp.Free; 
    end; 
    end; 
end; 

分配到TPicture没有工作,当你分配到TPicture如,TPicture将图形转换为类您正在分配。

请注意,在我的示例中,有2层转换,原始图像在转换为最终格式之前转换为位图。在这个过程中可能会有相当多的信息丢失。大多数(全部?)图形类型知道如何转换TBitmap和从TBitmap转换,但TJPEGImage不知道如何转换为TPngImage,反之亦然。

可以开发更高效的转换方法,以保持文件格式特有的透明度和其他效果,但这是我的知识。但根据您的需求,这可能就足够了。

+0

检查'AGraphic是否为vGraphicClass'可能是值得的,如果它是真的,则跳过位图转换。否则,即使将JPEG保存为JPEG,也会失去图像质量。 –

+0

或者跳过调用SaveGraphicAs函数,只需调用AGraphic.SaveToFile。还有不少其他问题可能会出现。第三方可以注册他们自己的PNG类(DevExpress是这样做的)。所以你最终会得到'TdxPNGImage是TPNGImage'(这将是错误的)。目前可能无法获得给定分机的当前注册班级(2008年1月24日请求QC57402 ...仍然打开)。调用者可能更容易确定图形是否已经处于正确的格式。但是,是的,我想这样做并不会伤害到优化。 –