CyberPeter 14 Posted yesterday at 09:40 AM 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
Uwe Raabe 2105 Posted yesterday at 10:10 AM Calling GraphicFileMask(TGraphic) from Vcl.Graphics will give you a list of supported extensions. Share this post Link to post
Anders Melander 1932 Posted yesterday at 10:12 AM 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
Anders Melander 1932 Posted yesterday at 10:18 AM 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
CyberPeter 14 Posted yesterday at 10:41 AM 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
Anders Melander 1932 Posted yesterday at 10:56 AM > 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
Uwe Raabe 2105 Posted yesterday at 11:25 AM 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
CyberPeter 14 Posted 12 hours ago > 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
CyberPeter 14 Posted 11 hours ago > 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: 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
Remy Lebeau 1529 Posted 10 hours ago 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
CyberPeter 14 Posted 10 hours ago 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
Remy Lebeau 1529 Posted 6 hours ago (edited) 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 5 hours ago by Remy Lebeau 1 Share this post Link to post
CyberPeter 14 Posted 5 hours ago 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
Anders Melander 1932 Posted 4 hours ago 1 hour ago, CyberPeter said: WIC does a better job on the images that I tested How so? Share this post Link to post
CyberPeter 14 Posted 3 hours ago 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
Anders Melander 1932 Posted 3 hours ago 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
CyberPeter 14 Posted 3 hours ago @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) Share this post Link to post
Anders Melander 1932 Posted 2 hours ago 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
CyberPeter 14 Posted 1 hour ago 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. 1 Share this post Link to post