Click here to Skip to main content
Click here to Skip to main content

An Image Decoder Based on IImgCtx

By , 25 May 2004
 

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

    /* IUnknown methods */
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, 
      LPVOID FAR* ppvObj) PURE;
    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
    STDMETHOD_(ULONG, Release)(THIS) PURE;
#endif

    /* IImgCtx methods */

    /* Initialization/Download methods */
    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;

    /* Query methods */
    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;

    /* Rendering methods */
    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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

strnghrs
Web Developer
China China
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
NewsForget IImgCtx from now onmemberAlex Reser12 Oct '10 - 20:03 
Apparently IE9 beta brings this component down, so all coders out there forget this stuff as soon as you can. And sorry for those who already used it in their projects, you're in big trouble. Remember, microsoft will always outplay you!
 
And yes, this is officially confirmed by microsoft, look here:
https://connect.microsoft.com/IE/feedback/details/611317/iimgctx-fails-to-draw-after-installing-ie9-beta[^]
 
They are "surprised that it does not crash", very funny guys indeed.
Sincerely,
Alex.

GeneralRe: Forget IImgCtx from now on (or fight for it! ;) )member_Olivier_14 Nov '10 - 6:22 
To all programmers using IImgCtx, please register on connect.microsoft.com, demand access to project IE (it's quick, free and immediate)
Then you can add yourself to the number of people having encountered this bug (see bug link above).
Hopefully Microsoft will consider to fix the issue before IE9 final.
GeneralRe: Forget IImgCtx from now on (or fight for it! ;) )memberTreeAd10 Feb '11 - 17:15 
Has anyone tried IImgCtx under the IE 9 Release Candidate?
GeneralRe: Forget IImgCtx from now on (or fight for it! ;) )memberMember 819502816 Nov '11 - 14:05 
IImgCtx fails to draw after installing IE9 beta.
Check it out
GeneralGreate!memberHong_J9 May '10 - 23:26 
I want to get a bitmap file from GIF file
 
I think I will to that using this library
 
after know how to use this, I will make animated window using this and transparent window property
 
thiank for it ^^
 
p.s. I want to know how to play animated GIF, too ~
QuestionDid someone implemented the setcallback method?membermanchukuo1 Feb '09 - 18:23 
Hi all!!
 
To use SetCallback you need to pass a pointer to function of type PFNIMGCTXCALLBACK
 
STDMETHOD(SetCallback)(THIS_ PFNIMGCTXCALLBACK pfn, void * pvPrivateData) PURE;
 
how do you implement this function?, i have tried but with not luck, could someone help me? Sigh | :sigh:
QuestionGetBitmapFromFile ProblemmemberMember 355274924 Aug '08 - 23:39 
i use GetBitmapFromFile() function to decode JPEG file into a HBITMAP buffer, then load on screen, to avoid form redraw problem (so i don't have to redecode jpg file everytime OnPaint())
 
now i am encountering one problem, right after i use GetBitmapFromFile(), file handle doesn't seem to release? so i cannot rename the jpg file which decoded by this program, how do i release file handler after i call GetBitmapFromFile()?? it looks like the fclose function doesn't work well somewhere
 
thank you!!
GeneralGreat Work (Sorry for digging this up but I got ask something...)memberjorl1713 Jan '08 - 2:52 
Nice work...quite a detective...
You just put my game with a PNG decoder to use my own GUI system. My only question is... Did you detect some flickering? I detect some flickering when to many paint msgs are sent, but I found a way to only send one at a time (meaning I reduced them). Still, sometimes I see flickering. Do you think there is a need for Double-buffering? Or is it already implemented?
 
Thanks in advice to anyone who can answer...
Generaluse callbackmemberdstzr30 Jul '06 - 22:57 
i test this interface
   all in iimgctx.h
 
hr =m_pImgCtx->SetCallback(Imagecallback,NULL);
hr= m_pImgCtx->SelectChanges(IMGCHG_COMPLETE,IMGCHG_COMPLETE,FALSE);
 
now,get it.
 
dstzr
QuestionImage Encoder?memberbdv12319 Aug '05 - 7:55 
Does anyone know of a similar ability in windows to encode bitmap images to these same formats? For example in pbrush.exe you can save to any of the formats, so I know that the ability exists, I just don't know how to access it.
AnswerRe: Image Encoder?memberYoSilver20 Aug '05 - 11:57 
pbrush seems to use GDI+ for file save ops.
BTW, GDI+ is not bad for that purpose.
You can redistribute gdiplus.dll if needed.
 
One always gets the deserved.

http://www.silveragesoftware.com/hffr.html
HandyFile Find And Replace
GeneralRe: Image Encoder?memberbdv12320 Aug '05 - 12:58 
Yes, GDI+ could be used. But the point of this article was to use what is built in, specifically to avoid redistributing a large component like GDI+, or linking to various other libraries.
 
And in any case, Pbrush has a delay load reference to GDI+, but I did not see gdiplus.dll load when running pbrush under the debugger, and saving a png file.

GeneralRe: Image Encoder?memberYoSilver20 Aug '05 - 16:17 
You can try to delay load gdiplus.dll and use SEH to catch exceptions in case it is unavailable and then ask a user to download it:
 
    __try
    {
        CLSID pngClsID;
        Gdiplus::GetEncoderClsid(L"image/png", &pngClsID);
        pGdiPlusImage->Save(L"MyImage.png", &pngClsID, NULL);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        return ASK_USER_TO_DOWNLOAD_GDI_PLUS;
    }
Among other imports from gdiplus.dll, PBrush imports GdipSaveImageToFile, so it is obvious that gdiplus.dll is used to save files. Debugger may not be able to see DLL's delay loaded.
 
One always gets the deserved.

http://www.silveragesoftware.com/hffr.html
HandyFile Find And Replace
GeneralRe: Image Encoder?memberbdv12320 Aug '05 - 17:43 
Yes, I could. And that would work *some* of the time. Which is no solution at all. Obviously, pbrush does not rely on GDI+ so there must be some other way. Reply only if you know that method.

GeneralRe: Image Encoder?memberbdv12321 Aug '05 - 7:28 
Some more digging shows that the list of image export filters can be obtained from:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Graphics Filters\Export
 
Corresponding to files located in:
C:\Program Files\Common Files\Microsoft Shared\Grphflt
 
These filters are installed by office, works, and perhaps other programs, so it seems that they cannot be counted on to be there either.
 
By opening the various FLT files (really DLLs) in Depends, you can see that they implement a set of entry points that, of course, are not documented.
 
Running dumpbin -exports on png32.flt yields:
 
Dump of file png32.flt
 
File Type: DLL
 
Section contains the following exports for PNG32.FLT
 
00000000 characteristics
36474C0A time date stamp Mon Nov 09 12:09:46 1998
0.00 version
1 ordinal base
12 number of functions
12 number of names
 
ordinal hint RVA name
 
4 0 00004530 ExportGr
1 1 00004C40 GetFilterInfo
3 2 000051E0 GetFilterPref
2 3 000051F0 ImportGr
8 4 00001220 MSFFClose
12 5 00001670 MSFFControl
9 6 00001330 MSFFGetLine
7 7 00001000 MSFFOpen
10 8 00001450 MSFFPutLine
11 9 00001650 MSFFSeek
6 A 000044E0 RegisterPercentCallback
5 B 00004E40 SetFilterPref

 

GeneralRe: Image Encoder?memberYoSilver27 Aug '05 - 9:31 
Yes, Office filters are known to be used... by Office only. They are not installed unless Office is installed. What is more, a user may select to not install a filter. And these are not redistributable.
 
Never the less, there is an example code in which you can find how to use filters, and plus some more techniques:
http://www.rsdn.ru/article/qna/gdi/drawimg/drawimg.zip[^]
 
There is a corresponding artice, but it's in Russian.
 
One always gets the deserved.

http://www.silveragesoftware.com/hffr.html
HandyFile Find And Replace
GeneralWinXP picture quality degradationmemberjamesw20033 Aug '05 - 5:29 
If I want to draw a picture at a different size than it's original size in WinXP the picture quality is severely degraded. It works fine in windows 98. Does anyone know why this happens ? I know some image classes need to include it's dll file, could this be the problem.
 
//*******************
// sample code below
//*******************
if (m_hBitmap)
{
HDC hMemDC = CreateCompatibleDC(pDC->GetSafeHdc());
if (hMemDC)
{
// select new bitmap into memory DC
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, m_hBitmap);
 
// show it
CSize sizeTotal;
::GetBitmapDimensionEx(m_hBitmap, &sizeTotal);

//******************************************************
// Draw the original picture at half the size
//******************************************************
::StretchBlt(pDC->GetSafeHdc(), 0, 0, sizeTotal.cx*.5, sizeTotal.cy*.5,
hMemDC, 0,0,sizeTotal.cx ,sizeTotal.cy, SRCCOPY);
 
// select old bitmap back into memory DC and get handle to bitmap
SelectObject(hMemDC, hOldBitmap);
 
DeleteDC(hMemDC);
}
}
GeneralUse halftonememberstrnghrs3 Aug '05 - 14:38 
like this:
 
// show it
CSize sizeTotal;
::GetBitmapDimensionEx(m_hBitmap, &sizeTotal);
 
// use halftone
::SetStretchBltMode(pDC->m_hDC, HALFTONE);
::SetBrushOrgEx(pDC->m_hDC, 0, 0, 0);
 
//******************************************************
// Draw the original picture at half the size
//******************************************************
::StretchBlt(pDC->GetSafeHdc(), 0, 0, sizeTotal.cx*.5, sizeTotal.cy*.5,
hMemDC, 0,0,sizeTotal.cx ,sizeTotal.cy, SRCCOPY);
 

GeneralRe: Use halftonememberjamesw20034 Aug '05 - 9:43 
Thank you for your answer. Smile | :)
 
Adding the code below corrected my problem.
 
// use halftone
::SetStretchBltMode(pDC->m_hDC, HALFTONE);
::SetBrushOrgEx(pDC->m_hDC, 0, 0, 0);

JokeRe: Off TopicmemberKarstenK15 Jun '06 - 21:57 
I have moved the CoInitialize( NULL ); to InitInstance and the CoUninitialize(); to ExitInstance().
 
I hope this is an improvement of speed to avoid startup und shutdown code. Roll eyes | :rolleyes:

 
Greeting from Germany
GeneralAnimated GIFmemberalervd17 Jan '05 - 20:42 
How to play using IImgCtx?
GeneralRe: Animated GIFmemberqiang.lin22 Aug '07 - 19:58 
i have the same question Smile | :)
GeneralThe homepage of CxImage is move to http://www.xdp.it/cximage.htmmembergu mingqiu2 Jun '04 - 15:36 
The homepage of CxImage is move to here
Generalwow shomoi :)memberRenato Czar Tome31 May '04 - 22:10 
Excellent job! shomoi na sab. bwahahaha Big Grin | :-D
GeneralRe: wow shomoi :)memberbosyotech6 Oct '04 - 20:55 
Very Good Job!!! Hastang hayaya sa mga tapulan. Laugh | :laugh:

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 26 May 2004
Article Copyright 2004 by strnghrs
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid