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单元。
好了,基本上把这块说完了,休息。