Jump to content
CyberPeter

What picture formats are supported by TImage ?

Recommended Posts

c++Builder 12.2

 

I finished an implementation where I load pictures from a proprietary source into a TImage instance.

 

Image->Picture->LoadFromStream(Stream)

 

This works well and during testing I found I could render following file formats without a problem on my W11 development system
bmp, jpg, png, wmf, emf, webp, gif, ico, tif, cr2, erf, raf, 3fr, dcr, dng, mrw, nef, orf, raw, pef, srw, sr2

 

However, while testing on older OS (VM) I noticed a lot of the fancier formats above do not work.

Only the basic ones: bmp, jpg, png, wmf, emf, gif, ico and tif

 

1. I'm guessing TImage uses system installed resources to render images ?  Which ones ?  How does that work ?  What do other applications install for TImage to be able to use them

2. Is there a way to get a list out of TImage that lists the supported files on the system the exe is running on ?

Share this post


Link to post

The image formats that are missing on your "older OS" are the ones supplied by WIC (via the TWICImage class).

 

TImage, or more precise TPicture, relies on different TGraphic implementations for image format support. The image formats you get by default,  whether you like them or not, are the ones registered in the Graphics unit.

 

Image formats are registered with TPicture.RegisterFileFormat and can be unregistered with TPicture.UnregisterFileFormat.

The list of registered image formats is internal (private in the Graphics unit) and Embarcadero, in their infinite wisdom, has not provided us with any means of accessing or enumerating the list so the only info you can get about registered image formats are filename masks.

 

See the TGraphic and TPicture documentation for more info.

 

 

Share this post


Link to post

I should mention that instead of relying on WIC, which is a library external to Delphi and thus outside your control, it would be better if you explicitly included/declared the image formats you want supported.

For example, include the pngimage unit for PNG support, the jpeg unit for JPEG support, etc.

 

I would also unregister the TWICImage class (see UnregisterFileFormat) as support for all the formats it support might not be a good thing. All the formats will just confuse your users.

Share this post


Link to post

Thanks guys, I'll check it out tomorrow (signing off now, down under)

>  For example, include the pngimage unit for PNG support, the jpeg unit for JPEG support, etc.

Is this not implied if I use TImage ?  Since it supports those formats via the different graphics classes that it supports (png, bmp, jpg, wmf, ico)

Share this post


Link to post

> Is this not implied if I use TImage ?

 

TImage is just a control that displays the data of a TPicture (TImage contains a TPicure object), so forget about TImage itself.

 

None of the image formats, except maybe bmp/TBitmap, are "implied" by design. It has just gotten so that using the Graphics unit implicitly pulls in support for a lot of different image formats. But it's not because someone sat down and had deep thoughts about what image formats to support by default and how to do it. It just happened to end up that way because, I guess, there's nobody left at Embarcadero who gives a damn about these things. Not that I think there has ever been anyone there that understood graphics or cared about imaging.

Share this post


Link to post

Vcl.Graphics internally registers the following extensions: tiff, tif, wmf, emf, ico and bmp.

 

All other extensions are registered in the units the format is implemented: 

  • gif in Vcl.Imaging.GIFImg
  • jpeg and jpg in Vcl.Imaging.jpeg
  • png in Vcl.Imaging.pngimage
  • svg, webp and wbmp in Vcl.Skia

Only when these units are used in your application the corresponding file extensions will be supported.

 

While designing in the IDE, these units are usually registered because the vclimg and the Skia packages are loaded.

Share this post


Link to post

>  Only when these units are used in your application the corresponding file extensions will be supported.  

I seem to have support for all of them, but ok I will also explicitly include them:
 

#include <Vcl.Imaging.GIFImg.hpp> // *.gif
#include <Vcl.Imaging.jpeg.hpp> // *.jpg, *.jpeg
#include <Vcl.Imaging.pngimage.hpp> // *.png

 

svg, webp and wbmp in Vcl.Skia

 

I have fully disabled Skia again because I don't want to statically link an extra dll

 

#if defined BUILD_WITH_SKIA
    #include <System.Skia.hpp>
    #include <Vcl.Skia.hpp>
#endif

 

However *.webp works for me, loaded in TImage btw, so I don't see the relationship with Skia ?

Share this post


Link to post

>  I would also unregister the TWICImage class (see UnregisterFileFormat) as support for all the formats it support might not be a good thing. All the formats will just confuse your users.

It's not a picture viewing program as such.  More of an extra feature if the functionality is available for that type picture (user needs to jump through hoops to get there).
Example:
484459649_1169633201837469_4118504129773509274_n.thumb.jpg.1f3418dc066ede8f4ffba266ec08c166.jpg


So I will try to build a list of supported extensions on that system and use that list to make the functionality available for that file (or not) using this suggestion:

 

>  Calling GraphicFileMask(TGraphic) from Vcl.Graphics will give you a list of supported extensions. 

 

Though I still need to figure this out ?

Share this post


Link to post
1 hour ago, CyberPeter said:

I seem to have support for all of them

As  stated earlier, a only handful of formats are supported by default.  If you were not already including those units explicitly, maybe they were being included implicitly somewhere else.  Or maybe something else in your program is providing the necessary support.

1 hour ago, CyberPeter said:

However *.webp works for me, loaded in TImage btw, so I don't see the relationship with Skia ?

Then something else in your program is providing support for WEBP, because that is not a format that the VCL supports natively.

Share this post


Link to post

I arrived at this first iteration code:

 

{
String formats;

static const TGraphicClass graphicClasses[] =
    {
    __classid(TBitmap),      // BMP
    __classid(TJPEGImage),   // JPG
    __classid(TPngImage),    // PNG
    __classid(TMetafile),    // WMF, EMF
    __classid(TIcon),        // ICO
    __classid(TGIFImage),    // GIF
    __classid(TWICImage),    // TIF, TIFF
    };

constexpr int numClasses = sizeof(graphicClasses) / sizeof(graphicClasses[0]);

for (int i = 0; i < numClasses; i++)
    {
    String mask = GraphicFileMask(graphicClasses[i]);

    if (!mask.IsEmpty())
        {
        // Remove "*." from extensions
        mask = StringReplace(mask, L"*.", L"", TReplaceFlags() << rfReplaceAll);

        if (!formats.IsEmpty())
            formats += L";";

        formats += mask;
        }
    }

return formats;
}

 

which reliably provides me this list:
 

L"bmp;jpg;jpeg;png;emf;wmf;ico;gif;tif;tiff"

which I can use to decide on providing a picture for a file or not
Although I might as well hard code these since they are built in anyway

I am not seeing the @Anders Melander mentioned external WIC extensions.  Any idea how to get to those ?  

GraphicFileMask()  on the WIC class only adds tif and tif

@Remy Lebeau I suspect *.webp, just like cr2, erf, raf, 3fr, dcr, dng, mrw, nef, orf, raw, pef, srw, sr2 (and perhaps more)  on my system are supported via mentioned external WIC class ?
I just need to find a way to build up a list
 

 

Share this post


Link to post
5 hours ago, CyberPeter said:

I am not seeing the @Anders Melander mentioned external WIC extensions.  Any idea how to get to those ?  

GraphicFileMask()  on the WIC class only adds tif and tif

Because those are the only 2 extensions that the VCL registers for TWICImage. But the WIC library supports so much more.

Windows Imaging Component

Native WIC Codecs

Quote

I suspect *.webp, just like cr2, erf, raf, 3fr, dcr, dng, mrw, nef, orf, raw, pef, srw, sr2 (and perhaps more)  on my system are supported via mentioned external WIC class ?

Most likely, yes. WIC can be extended with custom codecs.

Quote

I just need to find a way to build up a list

The VCL does not provide a way to enumerate file extensions that WIC supports. But WIC itself does via its IWICImagingFactory interface, which you can access by the TWICImage::ImagingFactory property.  Use IWICImagingFactory::CreateComponentEnumerator() to enumerate its available codecs, query each one for IWICBitmapCodecInfo, and then use IWICBitmapCodecInfo::GetFileExtensions().

Edited by Remy Lebeau
  • Thanks 1

Share this post


Link to post

Will check the WIC API functions, thanks.

FYI I experimented with built in GIF support but I have already disabled it again

//#include <Vcl.Imaging.GIFImg.hpp>   // For TGIFImage

because WIC does a better job on the images that I tested

Share this post


Link to post
Just now, Anders Melander said:

How so?

If I include GIFImg, Image->Picture->LoadFromStream() throws an exception on the two GIFs tried (Passed via a custom Stream)
If I don't include GIFImg, all GIFs tested work fine, assuming WIC was used.
 

Share this post


Link to post

Okay but do you remember what the exception was? - or if you have one of the GIFs I can try for myself.

 

I'm just curious because AFAIK there no known bugs in the GIF reader (and I wrote the original TGIFImage code back in... 1997).

Share this post


Link to post

@Anders Melander Just signing off, Friday evening down under.

I quickly included GIF again and built in 32bit and 64bit (Modern)

LoadFromStream() seems to throw an exception after testing the first two bytes (I think - checked in haste)

removing the include fixes the issue (use of WIC instead)

 


GIF.gif.efe688c6fa443c6b7a05eefea2e434c2.gif1624365877_Daffyduck.gif.c5bd4d75f3b0d1613f4569c659bcefd4.gif

Share this post


Link to post
27 minutes ago, CyberPeter said:

LoadFromStream() seems to throw an exception after testing the first two bytes (I think - checked in haste)

Works for me; The GIFs load and display without problems.

 

It's probably a problem in your code (have you remembered to reset the stream position before load?) but you don't have to pursue it for my sake. I was just curios.

Share this post


Link to post

Thanks @Anders Melander, I will double check on Monday.  I tried to finish too many things in the last few hours of the week.  I now also build a list of WIC registered codecs.  It's possible I made a mistake.  Weird though that all the other formats work without issues.  Only (embedded) GIF has an issue at the moment.  The Offset is definitely set to 0 (not on my dev system, so can't check, but pretty sure).  I'll put some breakpoints on Monday and will check my custom stream that pulls the data from various sources.

  • Like 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×