1. Why do I use IImgCtx
to decode images?
If you want to develop a image viewer or processor in Windows, the first thing you have to face is image decoding. Now there are some free image decoders, with full source code:
If you'd like all decoders in one project, you may try CxImage, which is developed by Davide Pizzolato.
But after I tried all of above decoders, I also found some problems:
- They were difficult to use. I had to configure or tailor source code before I could compile them.
- They were difficult to debug. Most free decoders were written in C, with poor comments.
- All decoders would be embedded in EXE or DLL and make install package so big. Of cause, if the final user would like to buy a "big" package, it could be another story.
So I (just like other "lazy" programmers) wondered if there was such an image decoder: easy to use, small footprint, one decoder for all images.
According to the information I got from Internet, the first toy I tried is IPicture
interface, which was well documented in MSDN, and discussed in codeguru and CodeProject. The good news was: though MSDN said IPicture
only could decode BMP, WMF and ICO files, it really worked fine with GIF and JPG. The bad news was: it really couldn't decode PNG and TIFF.
Then when I reinstalled my Windows OS, I found that the default viewer of GIF, JPG, PNF
files was Microsoft Internet Explorer (IE). Since all kinds of these images are often used in web pages, it
is reasonable if IE supported them. So is there any interface provided by IE that can decode images, just like I use IHTMLDocument
interface to parse HTML code?
The answer is: Yes, it's IImgCtx
interface. It can decode all
images that can be shown in IE, including JPEG, PNG, GIF, BMP, WMF, ICO, and
sometime TIFF (I'll explain why I say "sometime" later).
2. How to use IImgCtx
interface to decode images?
In IE 5.5 SDK, which is the only IE SDK I have, I found the definition of IImgCtx
interface in IImgCtx.h. In VC++ 6, I also found that file. The difference between two files
is just one line: In IE 5.5 SDK, it defines one more constant value named DWN_MIRRORIMAGE
. I think this is also the difference between IE 4 and IE 5.5.
But when I searched IImgCtx
in MSDN, I got nothing. Then I tried it in Google, the result was the same. Fortunately, the interface was relatively simple and I might guess its usage:
DECLARE_INTERFACE_(IImgCtx, IUnknown)
{
#ifndef NO_BASEINTERFACE_FUNCS
STDMETHOD(QueryInterface)(THIS_ REFIID riid,
LPVOID FAR* ppvObj) PURE;
STDMETHOD_(ULONG, AddRef)(THIS) PURE;
STDMETHOD_(ULONG, Release)(THIS) PURE;
#endif
STDMETHOD(Load)(THIS_ LPCWSTR pszUrl, DWORD dwFlags) PURE;
STDMETHOD(SelectChanges)(THIS_ ULONG ulChgOn,
ULONG ulChgOff, BOOL fSignal) PURE;
STDMETHOD(SetCallback)(THIS_ PFNIMGCTXCALLBACK pfn,
void * pvPrivateData) PURE;
STDMETHOD(Disconnect)(THIS) PURE;
STDMETHOD(GetUpdateRects)(THIS_ struct tagRECT FAR* prc,
struct tagRECT FAR* prcImg, long FAR* pcrc) PURE;
STDMETHOD(GetStateInfo)(THIS_ ULONG FAR* pulState,
struct tagSIZE FAR* psize, BOOL fClearChanges) PURE;
STDMETHOD(GetPalette)(THIS_ HPALETTE FAR* phpal) PURE;
STDMETHOD(Draw)(THIS_ HDC hdc,
struct tagRECT FAR* prcBounds) PURE;
STDMETHOD(Tile)(THIS_ HDC hdc, struct tagPOINT FAR* pptBackOrg,
struct tagRECT FAR* prcClip, struct tagSIZE FAR* psize) PURE;
STDMETHOD(StretchBlt)(THIS_ HDC hdc, int dstX, int dstY, int dstXE,
int dstYE, int srcX, int srcY, int srcXE, int srcYE,
DWORD dwROP) PURE;
};
According to the definition of
IImgCtx
, I can use
Load
method to read image file after I create
IImgCtx
object. And I can use
Draw
method to show decoded image. But
- The parameter of
Load
method is a URL (for IE?) in Unicode. So I have to convert local path name into file://local path.
- Just like other interfaces in IE,
IImgCtx
also works asynchronously. This is the reason why it defines SetCallback
method to set call back function, and SelectChanges
method to monitor status.
Since there is no any document about IImgCtx
, I don't know how to use them. I only know that I have to build a message pump to drive asynchronous process.
Draw
method uses a HDC
as target DC. If this is a memory DC, it can decode image without show it. Decoded image is a DDB (Device Dependent Bitmap). If you want to process it, you'd better convert it into DIB (Device Independent Bitmap).
The full process of using IImgCtx interface to decode image is shown in WndImgCtx.cpp, in sample project.
3. How to use IImgCtx
in your project?
The sample code of this document is ImgViewer.zip. Download and unzip it, you'll get a VC++ 6 project of a simple (really quite simple) image viewer. Besides image decoder, it also shows how to search and sort files in a folder so you can view images one by one.
If you just want a image decoder, you can include WndImgCtx.h and WndImgCtx.cpp into your project, and add this line at the beginning of you CPP file:
#include "WndImgCtx.h"
Then you can call
HBITMAP GetBitmapFromFile(LPCTSTR pszFilename);
to decode image. It will return a DDB identified by a HBITMAP
.
4. Why is TIFF an exception?
IE supports most image files, including JPEG, PNG and GIF. But in the
"File Open" dialog of IE, I can't find TIFF files. I tested ImgViewer
with the sample files provided by libtiff
organization. The result was: In Windows 98/Me/XP, none of them could be shown.
In Windows 2000, about half of them could, others couldn't.
In Windows 2000, I compiled and run ImgViewer in Debug mode in VC++ 6, opened
a TIFF file, then exited it. I found these lines in the Output window of VC++:
Loaded 'C:\WINNT\system32\imgutil.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\tifflt.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\oieng400.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\mscms.dll', no matching symbolic information found.
Loaded 'C:\WINNT\system32\winspool.drv', no matching symbolic information found.
I did the same thing in Windows XP but I only could see the first line.
In Windows 2000, I searched key word "tifflt.dll" in regedit and
found it belonged to "TIFFilter Class", whose CLSID was {EBD0F6B6-4AED-11D1-9CDB-00805F0C62F5}
.
Then I searched this CLSID again, and found it was the value of "Image
Filter CLSID" key, in "HKEY_CLASSES_ROOT\MIME\Database\Content Type\image/tiff"
item. Before this item, I also saw "image/png" and
"image/jpeg" items. Both of them had "Image
Filter CLSID" key. Documented in MSDN, "HKEY_CLASSES_ROOT\MIME\Database\Content
Type" items record all MIME types that can be recognized by IE.
By the name of "Image
Filter CLSID", I guess this is the CLSID of image filter. In Windows
98/Me/XP, I can't find it under "image/tiff" item. But I can found it
under "image/png" and "image/jpeg" items. Maybe this is the
reason why IE can't show TIFF in Windows 98/Me/XP: there is no image filter for
it.
I tried to move tifflt.dll and oieng400.dll into XP but failed because of DLL
conflict. Maybe the only hope is: Microsoft provides an image filter for
TIFF.