【问题标题】:How do I make a PNG resource?如何制作 PNG 资源?
【发布时间】:2010-11-12 07:25:17
【问题描述】:

我有一个表格,上面有一个大的TImage 作为背景。问题是,它作为位图直接存储在 DFM 中,占用大约 3 MB。原始 PNG 文件约为 250K。我想尝试通过将 PNG 嵌入资源中来减少臃肿,然后让表单在OnCreate 期间加载它。现在我可以做到这一点,因为 Delphi 2009 包含 PNG 支持,但我不太清楚如何构建包含 PNG 的资源文件。有人知道这是怎么做到的吗?

【问题讨论】:

    标签: delphi png delphi-2009 resources


    【解决方案1】:

    示例文本文件(名为 myres.rc):

    MYPNG RCDATA mypng.png
    

    添加到项目中:

    {$R 'myres.res' 'myres.rc'}
    

    运行时加载示例:

    uses
      PngImage;
    
    var
      Png: TPngImage;
    begin
      Png := TPngImage.Create;
      try
        Png.LoadFromResourceName(HInstance, 'MYPNG');
        Image1.Picture.Graphic := Png; // Image1: TImage on the form
      finally
        Png.Free;
      end;
    end;
    

    【讨论】:

    • RCDATA 真的是该图形类型可用的最具体的资源类型吗?例如,没有RT_PNG
    • 问得好,罗布。我当前安装的 Platform SDK 适用于 Windows Server 2003 R2,我在 WinUser.h 中找不到特定于 PNG 的常量。不过,我不确定。它可能在其他地方声明,可能在更高版本的 Platform SDK 中。
    • LoadFromResourceName 专门寻找 RCDATA 类型的资源。
    • 您还可以在您的 MSBuild 进程中包含该资源:tondrej.blogspot.com/2016/08/…
    • 好像.DLL项目自动.rc文件编译不起作用?
    【解决方案2】:

    对于那些使用 C++ Builder 的人来说,这段代码对我有用:

    在 ResourceTest.rc 文件中

    IMG_BMP BITMAP "Ressources\\myimage.bmp";
    IMG_PNG RCDATA "Ressources\\myimage.png";
    

    在 ResourceTest.rh 文件中

    #ifndef ResourceTestRH
    #define ResourceTestRH
    
    #define IMG_BMP "IMG_BMP"
    #define IMG_PNG "IMG_PNG"
    
    #endif
    

    在 ResourceTest.cpp 文件中

    #include "pngimage.hpp"
    
    // Loading bmp image from resource
    Graphics::TBitmap *bmpImage = new Graphics::TBitmap();
    bmpImage->LoadFromResourceName((int)HInstance, IMG_BMP);
    
    // Loading png image from resource
    TPngImage *pngImage = new TPngImage();
    pngImage->LoadFromResourceName((int)HInstance, IMG_PNG);
    

    【讨论】:

      【解决方案3】:

      如果您使用的是 Delphi 2009,TImage 应该将您的 PNG 文件作为 PNG 存储到 DFM 文件中。 DFM 会更大,因为 TImage 对象的 Picture.Data 属性的二进制内容在 DFM 中编码为十六进制文本。但是当 DFM 被编译到你的 EXE 中时,它会被编译成二进制资源。然后,您的图像应在表单的 RCDATA 资源中占用与将 PNG 存储在其自己的 RCDATA 资源中相同的空间。

      我刚刚通过在文本编辑器中打开我自己的一个 Delphi 2009 DFM 文件来测试这一点编辑。十六进制编辑器向我显示 Picture.Data 属性存储了一个以 10 个字节为前缀的实际 PNG 文件。第一个字节是 $09,接下来的 9 个字节拼写为 TPngImage。如果我删除这 10 个字节并将文件保存在十六进制编辑器中,我会得到一个正确的 PNG 文件。

      因此,如果您使用的是 Delphi 2009,只需在设计时将 PNG 图像加载到 TImage 组件中即可。

      【讨论】:

      • 很有趣,但是图像在多个表单上重复使用的情况呢? Delphi 是否足够智能以仅存储一份副本,或者它是否将图像存储 n 次,其中 n 是加载该图像的 TImage 组件的数量? :)
      • 每个 TImage 组件都独立于任何其他 TImage 实例存储其图像。因此,如果您将相同的图像加载到 TImage 的 n 个实例中,则相同的图像将被存储 n 次。解决这个问题的一种方法是使用表单继承。使用 TImage 创建一个基本表单并将图像加载到其中。然后从该表单派生所有需要具有相同 TImage 的表单。后代表单中未更改的任何属性仅存储在祖先表单的 DFM 中。其中包括 TImage 的图片数据。
      【解决方案4】:
      【解决方案5】:

      当使用Resource Hacker 时,PNG 图像添加了 'PNG' ResType 而不是普通的RT_RCDATA

      TPngImage Class Helper 为这个问题提供了一个简单的解决方案:

      Type
        TPngImageHelper = Class Helper For Vcl.Imaging.pngimage.TPngImage
          Procedure LoadFromRHResourceName(Instance: HInst; Const Name: String);
        End;
      

      ...

      Procedure TPngImageHelper.LoadFromRHResourceName(Instance: HInst; Const Name: String);
      Var
        rs: TResourceStream;
      Begin
        rs := TResourceStream.Create(Instance, PChar(Name), 'PNG');
        Try
          LoadFromStream(rs);
        Finally
          rs.Free;
        End;
      End;
      

      使用简单:

      var
        pngInfo: TPngImage;
      begin
        pngInfo := TPngImage.Create;
        try
          pngInfo.LoadFromRHResourceName(HInstance, 'MY_IMAGE.PNG');
          Image1.Picture.Graphic:= pngInfo;
        finally
          pngInfo.Free;
        end;
      end;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-05
        • 2017-07-04
        • 2011-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多