I am experiencing that Delphi's TImage
component is very poor. I am working with various Delphi versions starting from Delphi 6 (2000 edition, we still have some projects on it) and ending with Tokyo, Alexandria. TImage
has poor support for files beyond ico/bmp/jpg, it has no EXIF auto-rotation feature, and it has no resampling/interpolation.
I tried to find open source replacement using Graphics32's TImage32
and I have installed it. But I am experiencing multiple problems:
Delphi 6 compiled program with TImage32
can load png files on Windows 10, but the same exe reports 'Unknown file extension (.png)' on Windows XP (yes, we still use them).
There are some jpg files that can be opened in image editors without problems, but loading them in TImage32 reports 'JPEG error #52'.
I observed even more strange things: after installing Graphics32 components in my Delphi 6, the following builds can not load jpg files into VCL's TImage
! And reports 'Unknown file extension (.jpg)'.
OK, so - lot of problems, possibly too many for one question. But my question is about the core issue that underlies all these problems: I see this VCL code:
procedure TPicture.LoadFromFile(const Filename: string);
var
Ext: string;
NewGraphic: TGraphic;
GraphicClass: TGraphicClass;
begin
Ext := ExtractFileExt(Filename);
Delete(Ext, 1, 1);
GraphicClass := FileFormats.FindExt(Ext);
if GraphicClass = nil then
raise EInvalidGraphic.CreateFmt(SUnknownExtension, [Ext]);
NewGraphic := GraphicClass.Create;
try
NewGraphic.OnProgress := Progress;
NewGraphic.LoadFromFile(Filename);
except
NewGraphic.Free;
raise;
end;
FGraphic.Free;
FGraphic := NewGraphic;
FGraphic.OnChange := Changed;
Changed(Self);
end;
Which is being executed upon loading an image, both into TImage
(from VCL) and TImage32
(from Graphics32), and the core thing is:
GraphicClass := FileFormats.FindExt(Ext);
if GraphicClass = nil then
raise EInvalidGraphic.CreateFmt(SUnknownExtension, [Ext]);
I guess - there can be 2 problems:
the graphic class simply can not be found and loaded. Maybe Windows 10 has some libraries for png files, and the png graphics class is loaded into FileFormats
, but maybe Windows XP has no such library, and that is why my exe can not load this graphics class when the exe is being run on Windows XP.
there can be multiple implementations for one format, e.g. for jpg. That is why my programs could load a jpg file into TImage
before installing Graphics32, and Graphics32 may have added another implementation (or may have corrupted or removed it?), and that is why my TImage
cannot load a jpg into TImage
after installation of Graphics32.
So - all is boiling down to the method, how is the Graphics.FileFormats
list being populated?
I see VCL Graphics.pas
code:
constructor TFileFormatsList.Create;
begin
inherited Create;
Add('wmf', SVMetafiles, 0, TMetafile);
Add('emf', SVEnhMetafiles, 0, TMetafile);
Add('ico', SVIcons, 0, TIcon);
Add('bmp', SVBitmaps, 0, TBitmap);
end;
And it has no jpg file. So - I guess, that FileFormats
is created with the default 4 formats, and then some other libraries somehow can add entries to this list?
I don't know how this is happening, and this is the core of my question - how does the FileFormats
list get additional entries so that these entries can be used by TImage
and TImage32
(Graphics32)? Are these additional entries dependent on the existence of some DLLs, libraries, possibly registered Windows COM libraries for the additional formats?
My understanding is that something has gone wrong with the population of FileFormats
on my development machine.
Progress update added:
I should add jpeg
to the uses
clause, and then TImage
can load jpg files as well. So - uses
entries determine that graphic formats are loaded. So - this is one mechanism that determines the available graphic formats.
It appeared that my 'JPEG error #52' 'jpg files' were png files generically, and so the error message was correct.
But I am still seeking solution why my Delphi 6 program with TImage32
can load png files on Window 10, but reports 'Unknown file format (.png)' on Windows XP.
After finding the entire spectrum of populating Graphics.FileFormats
, I hope to write an answer, if there will not be one at that time.
So, it appeared, that adding units to the uses
clause solve the problem. I have added:
jpeg
to support jpg and jpeg files.
cxGraphics
to support png files (fortunately, I had DevExpress Suite installed, and migrated to Delphi 6, and cxGraphics was intended for its TcxImageView
component, which, while supporting many different file formats, did have support for resampling/interpolation and EXIF auto-rotation. I am reading that as of 2023/2024, DevExpress has added support for EXIF auto-rotation, and maybe there is support for resampling in the latest versions as well).
Has Graphics32 some units which can be added to uses
clause instead of commercial cxGraphics
? To answer that, I did a WinGrep search over 'graphics32 master' for RegisterFileFormat()
and it returned nothing.
So - one should look at other third party units for supporting the more exotic file formats (png, tiff, webp; in fact my version of cxGraphics
supports png only from this trio), but Graphics32
is good for resampling and for fast EXIF rotation (if EXIF orientation is determined by some other methods, e.g. by reading EXIF information using GDI+ libraries).
So - this explains support for file formats, and solve all my issues.