Click here to Skip to main content
15,886,689 members
Articles / Desktop Programming / MFC

Dynamically generating images in ISAPI extension using GDI+ with live demo

Rate me:
Please Sign up or sign in to vote.
3.88/5 (8 votes)
3 Oct 20022 min read 65.3K   424   26  
A class wrapper to write GDI+ images to the client browser using an ISAPI extension.
#pragma once
#include <math.h>

/*! \brief A GDI+ Image Renderer for MFC ISAPI Extensions

\par Description

<p>This class enables you to render GDI+ image on the server and send them directly to the client browser
without passing by temporarly files.</p>

\par Basic use
<p>The use of the class is straight forward: build a CGDIpISAPI object with all the pointers and call WriteImage:</p>
\code
void CHttpServerDerviedClass::Default( CHttpServerContext* pCtxt)
{
	using namespace Gdiplus;

	// creating bitmap
	Bitmap bitmap(320,200);
	// drawing on this bitmap
	...
	
	// sending bitmap to the browser
	CGDIpISAPI renderer( this, pCtxt, &bitmap );
		// sending image
	renderer.WriteImage();
}
\endcode

\par Output options
<p>You can choose the image code (PNG, JPEG, BMP or TIFF) and change the quality ratio for the PNG and JPEG files.
The quality must be between 0 and 100.</p>
<p>All these options can be set at the construction or by setters.</p>
\code 
// Setting bmp type
renderer.SetImageType( CGDIpISAPI::ImageBMP);
\endcode
\code 
// Changing quality
renderer.SetQuality( 98 );
\endcode

\par Initializing GDI+
<p>Do not forget to initialize and deinitialize GDI+. I'm using a helper class for that: CGDIpInitializer.</p>
\code 
class CMyExtension
{
...
	CGDIpInitializer m_GDIpInitializer;
}
\endcode
\code
BOOL CMyExtension::GetExtensionVersion(HSE_VERSION_INFO* pVer)
{
	// Appelez l'impl�mentation par d�faut pour l'initialisation
	CHttpServer::GetExtensionVersion(pVer);

	// Initialize GDI+
	m_GDIpInitializer.Initialize();
	...
\endcode
\code
BOOL CMyExtension::TerminateExtension(DWORD dwFlags)
{
	// l'extension est arr�t�e
	//TODO�: nettoyez les ressources par instance
	m_GDIpInitializer.Deinitialize();
\endcode
\par What not to do...
<ul>
<li>When writing an image, do not write anything else!</li>
</ul>

\author Jonathan de Halleux, dehalleux@auto.ucl.ac.be
*/
class CGDIpISAPI
{
public:
	//! \name Typdefs
	//@{
	//! Different supported image codecs
	static enum EImageType
	{
		//! Portable Network Graphics
		ImagePNG = 0,
		//! Famous JPEG
		ImageJPEG = 1,
		//! Bitmap
		ImageBMP=2
	};
	//@}

	//! \name Constructors
	//@{
	/*! \brief Default constructor

	  \param pServer pointer to the CHttpServer class
	  \param pCtxt pointer to the CHttpServerContext object
	  \param pImage pointer to a GDI+ image object
	  \param eImageType image type (default is PNG)
	  \param ulQuality quality. Applies to PNG and JPEG (default is 80)

	  The quality must be an integer between 0 (ugly, good compression) and 100 (nice, poor compression).
	 */
	CGDIpISAPI(CHttpServer* pServer=NULL, 
		CHttpServerContext* pCtxt=NULL,
		Gdiplus::Image* pImage=NULL, EImageType eImageType = ImagePNG, ULONG ulQuality = 80)
	: m_pServer(pServer),m_pCtxt(pCtxt), m_pImage(pImage), m_eImageType(ImagePNG)
	{	SetQuality(ulQuality);};
	~CGDIpISAPI(){};
	//@}

	//! \name Output options
	//@{
	//! Sets the image type
	void SetImageType(EImageType eImageType)	{	m_eImageType = eImageType;};
	//! return the image type
	EImageType GetImageType() const				{	return m_eImageType;};
	//! returns CGI string describing the current image type
	LPCTSTR CGDIpISAPI::GetImageTypeString() const;
	//! Sets the quality between 0 (ugly, good compression) and 100 (nice, poor compression)
	void SetQuality(ULONG ulQuality)			{	m_ulQuality=__min(100,ulQuality);};
	//! return the quality
	ULONG GetQuality() const					{	return m_ulQuality;};
	//@}

	//! \name Output functions
	//@{
	//! Send the image to the brower
	void WriteImage();
	//! Writes info about the image
	void WriteInfo(void);
	//@}

private:
	//! \name Helpers
	//@{
	void DumpError(LPCTSTR pszFormat, ...);
	void WriteContext(LPCTSTR szFormat,...);
	int GetEncoderClsid(const WCHAR* format, CLSID* pClsid);
	//@}
		
	CHttpServer* m_pServer;
	CHttpServerContext* m_pCtxt;
	Gdiplus::Image* m_pImage;
	EImageType m_eImageType;
	UINT m_ulQuality;
};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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


Written By
Engineer
United States United States
Jonathan de Halleux is Civil Engineer in Applied Mathematics. He finished his PhD in 2004 in the rainy country of Belgium. After 2 years in the Common Language Runtime (i.e. .net), he is now working at Microsoft Research on Pex (http://research.microsoft.com/pex).

Comments and Discussions