• Unknown picture file extension (.jpg)


    VCL下的TImage,加载一个Jpg文件时,出这个提示,无法加载:

    Image1.Picture.LoadFromFile(fn1);

    不认识这个文件格式,如果在设计期是可以调入对应的图片的。查了半天代码,原来,如果使用jpg文件,我们要引用Vcl.Imaging.jpeg

    在uses部分引用Vcl.Imaging.jpeg,问题解决。

    同样,当加载jpg的Stream时,也是同样的问题。当加载流时,要记得调整流当前的位置为0,如下代码:

        ms.Position := 0;
        Image1.Picture.LoadFromStream(ms);

    不然,无法识别流的格式。

    为什么引用Vcl.Imaging.jpeg就解决了呢?

    查看Vcl.Imaging.jpeg代码,原来,这个单元实现了对jpg的处理,然后在initialization部分实现了这样的代码:

    initialization
      TPicture.RegisterFileFormat('jpeg', sJPEGImageFile, TJPEGImage);
      TPicture.RegisterFileFormat('jpg', sJPEGImageFile, TJPEGImage);

    再查看TPicture.LoadFromFile代码,原来这个方法会根据文件的扩展名,查找TGraphicClass,如果找不到,则抛出Unknown picture file extension (.jpg)异常。

    procedure TPicture.LoadFromFile(const Filename: string);
    var
      Ext: string;
      GraphicClass: TGraphicClass;
    begin
      Ext := ExtractFileExt(Filename).Remove(0, 1);
      GraphicClass := FileFormats.FindExt(Ext);//查找处理图片格式的类
      ...
      if GraphicClass = nil then//找不到则发出异常
        raise EInvalidGraphic.CreateFmt(SUnknownExtension, [Ext]);
      ...
    end;

    上面是官方的代码,我做了简化。

    再分析FileFormats.FindExt方法,原来FileFormats在Create中,默认只处理下面的文件类型:

    constructor TFileFormatsList.Create;
    begin
      inherited Create;
    {$IF DEFINED(CLR)}
      Add('tiff', SVTIFFImages, '', TBitmap);
      Add('tif', SVTIFFImages, '', TBitmap);
      Add('wmf', SVMetafiles, '', TMetafile);
      Add('emf', SVEnhMetafiles, '', TMetafile);
      Add('ico', SVIcons, '', TIcon);
      Add('png', SVPNGImages, '', TBitmap);
      Add('gif', SVGIFImages, '', TBitmap);
      Add('jpeg', SVJPGImages, '', TBitmap);
      Add('jpg', SVJPGImages, '', TBitmap);
      Add('bmp', SVBitmaps, '', TBitmap);
    {$ELSE}
      Add('tiff', SVTIFFImages, 0, TWICImage);
      Add('tif', SVTIFFImages, 0, TWICImage);
      Add('wmf', SVMetafiles, 0, TMetafile);
      Add('emf', SVEnhMetafiles, 0, TMetafile);
      Add('ico', SVIcons, 0, TIcon);
      Add('bmp', SVBitmaps, 0, TBitmap);
    {$ENDIF}
    end;

    注意,上面代码,没有定义CLR,所以编译的是ELSE部分,标记为红色的部分。

    FileFormats本质上就是一个TList类的全局实例,用来保存文件扩展名与处理他的类,上面的

      TPicture.RegisterFileFormat('jpg', sJPEGImageFile, TJPEGImage);

    就是把jpg与TJPEGImage,保存到这个FileFormats对象中。

    如果要处理的是png格式的图片,要引用Vcl.Imaging.pngimage单元。

    好了,基本上把这块说完了,休息。

  • 相关阅读:
    Vue练习三十六:05_01_模拟select控件
    Vue练习三十五:04_09_星级评分系统
    Vue练习三十四:04_07_各种数组方法练习
    Vue练习三十三:04_06_当前输入框高亮显示
    Vue练习三十二:04_05_设置读取属性
    【CC++笔记】指针输出字符串
    【CC++笔记】数组指针越界
    【算法】递归思想
    【学习方法】堕落大学生补救方法
    【数字逻辑】补码技巧
  • 原文地址:https://www.cnblogs.com/kinglandsoft/p/16051007.html
Copyright © 2020-2023  润新知