红鱼儿

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单元。

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

 

posted on 2022-03-24 17:55  红鱼儿  阅读(632)  评论(0编辑  收藏  举报