5,692,513 members and growing! (18,230 online)
Email Password   helpLost your password?
Multimedia » GDI+ » General     Intermediate

Adding GIF-animation using GDI+

By Norm .net

Norm demonstrates how to coerce GDI+ into displaying animated GIFs
VC6, VC7, C++Windows, Win2K, WinXP, GDI+, VS6, Visual Studio, Dev

Posted: 29 Jan 2002
Updated: 29 Jan 2002
Views: 201,089
Bookmarked: 56 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
32 votes for this Article.
Popularity: 6.72 Rating: 4.46 out of 5
2 votes, 8.7%
1
0 votes, 0.0%
2
0 votes, 0.0%
3
2 votes, 8.7%
4
19 votes, 82.6%
5

Motive

How many of you developers are using GDI+? I reckon, not many. As a seasoned Windows C++ programmer developing for desktop applications, I've been  using the archaic GDI on regular basis. Since the release of GDI+ (see (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdicpp) I've been using GDI+ in new applications and also converting existing applications to use GDI+. There numerous compelling reasons why you should be using GDI+, here are some:

  • Successor to GDI
  • Compatible with .NET
  • Optimizes many of the capabilities of GDI
  • Supports: Gradient Brushes, Independent Path Objects, Transformations and the Matrix Object, Scalable Regions, Alpha Blending and support for multiple image formats:
    • BMP
    • GIF
    • JPEG
    • Exif
    • PNG
    • TIFF
    • ICON
    • WMF
    • EMF

During my development of Windows GUI based applications with GDI+, I've come across the need to display animated GIFs, whilst GDI+ does not support displaying animated GIFs directly, in can be done with a little coding.

Implementation

Firstly lets look at drawing a simple image using GDI+.

void CMyWnd::OnPaint()
{
	CPaintDC dc(this);
	
	Graphics graphics(&dc); // Create a GDI+ graphics object


	Image image(L"Test.Gif"); // Construct an image

	
	graphics.DrawImage(&image, 0, 0, image.GetWidth(), image.GetHeight());	
		
}

Straight away we can see the simplistic C++ interface for using GDI objects. This makes it a sure fire way for using GDI objects. There is no need for using SelectObject to select GDI objects in and out of the device context.

For those of the readers who are not familiar with the format of an animated GIF, animated GIF is actually a series of GIF frames with a delay time associated each frame, therefore each frame can have a different delay time.

My implementation of encapsulating an animated GIF functionality derives a class called from ImageEx from the GDI+ Image class. The first task is to determine whether or not a GIF is of the animated kind. The following code demonstrates this:

bool ImageEx::TestForAnimatedGIF()
{
	UINT count = 0;
	count = GetFrameDimensionsCount();
	GUID* pDimensionIDs = new GUID[count];

	// Get the list of frame dimensions from the Image object.

	GetFrameDimensionsList(pDimensionIDs, count);

	// Get the number of frames in the first dimension.

	m_nFrameCount = GetFrameCount(&pDimensionIDs[0]);

	// Assume that the image has a property item of type PropertyItemEquipMake.

	// Get the size of that property item.

	int nSize = GetPropertyItemSize(PropertyTagFrameDelay);

	// Allocate a buffer to receive the property item.

	m_pPropertyItem = (PropertyItem*) malloc(nSize);

	GetPropertyItem(PropertyTagFrameDelay, nSize, m_pPropertyItem);


	delete pDimensionIDs;

	return m_nFrameCount > 1;
}

m_pPropertyItem->value is actually a pointer to an array of longs, each long is a delay time which corresponds to a GIF frame. Because GetPropertyItem returns a different size depending on what property using interested in, a Size is require and its the programmer responsibility to allocate and deallocate the memory associated with GetPropertyItem. The size is determined by calling GetPropertyItemSize supplying property tag your interested in.

Once the number of frames and delay times have been retrieved from the image, a thread is created which calls to DrawFrameGIF until the object destructs. See DrawFrameGIF below:

bool ImageEx::DrawFrameGIF()
{

	::WaitForSingleObject(m_hPause, INFINITE);

	GUID pageGuid = FrameDimensionTime;

	long hmWidth = GetWidth();
	long hmHeight = GetHeight();

	HDC hDC = GetDC(m_hWnd);
	if (hDC)
	{
		Graphics graphics(hDC);
		graphics.DrawImage(this, m_rc.left, m_rc.top, hmWidth, hmHeight);
		ReleaseDC(m_hWnd, hDC);
	}

	SelectActiveFrame(&pageGuid, m_nFramePosition++); 

	if (m_nFramePosition == m_nFrameCount)
		m_nFramePosition = 0;


	long lPause = ((long*) m_pPropertyItem->value)[m_nFramePosition] * 10;

	DWORD dwErr = WaitForSingleObject(m_hExitEvent, lPause);

	return dwErr == WAIT_OBJECT_0;
}

One other interesting aspect of this class is it has the ability of loading a image directly as a resource from an executable. I usually import my GIF into a project and give it a resource type of "GIF" and then rename the resource ID from a numeric constant to a string (see the example code).

Conclusion

If you familiar with the concepts and programming of GDI, GDI+ provides some advance features and the interface almost mirrors the .NET GDI namespace. The sample apps and code include the full listings for implementing animated GIF in your code applications. For code reference just search for GDI+ within the code. One thing I haven't included in this article is starting up and shutting the GDI+ subsystem.

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

Norm .net



Occupation: Architect
Company: Software Kinetics
Location: United Kingdom United Kingdom

Other popular GDI+ articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 25 of 79 (Total in Forum: 79) (Refresh)FirstPrevNext
GeneralVC++.Net and Imagesmemberminad_7864:54 5 Sep '07  
GeneralRe: VC++.Net and Imagesmembernorm .net4:59 5 Sep '07  
GeneralRe: VC++.Net and Imagesmemberminad_7860:40 6 Sep '07  
GeneralRe: VC++.Net and Imagesmembernorm .net3:09 6 Sep '07  
GeneralCreate animated GIFmemberTall Dude9:58 19 Jan '07  
GeneralRe: Create animated GIFmembernorm .net23:48 25 Jan '07  
GeneralGDI+ function to identify moving GIF image programaticallymembermukta_here4:31 8 Sep '06  
QuestionProblem with Image object in GDI+ (VC++)memberDhananjayak025:10 14 Aug '06  
AnswerRe: Problem with Image object in GDI+ (VC++)memberInfro12:45 3 Sep '06  
AnswerRe: Problem with Image object in GDI+ (VC++)memberddzh23:50 22 Nov '07  
GeneralGDI+ Buffered imagememberdarb214:47 9 Aug '06  
GeneralRe: GDI+ Buffered imagemembernorm .net0:36 10 Aug '06  
GeneralMagnificent !!!!!memberHiigara4:12 3 Nov '05  
GeneralRe: Magnificent !!!!!membernorm.net0:03 8 Apr '06  
GeneralAnimated GIFs with transparecysussliqutttt9:10 13 Apr '05  
GeneralRe: Animated GIFs with transparecymemberdefrog5:45 11 Oct '05  
GeneralRe: Animated GIFs with transparecymemberClaudio Sampaio12:02 25 Apr '06  
GeneralRe: Animated GIFs with transparecymembergame00717:30 1 Sep '06  
GeneralRe: Animated GIFs with transparecymemberKenDang6:02 8 Aug '07  
GeneralRe: Animated GIFs with transparecy (The best way for transparency!!)memberGreg Ellis12:19 11 Nov '08  
QuestionRe: Animated GIFs with transparecy (The best way for transparency!!)memberIstvan Lengyel6:03 27 Nov '08  
GeneralRendering Time of each FramememberKohaku-Chan11:36 20 Dec '04  
GeneralRe: Rendering Time of each FramememberTDK90000023:00 16 Oct '05  
GeneralHow to create a multi-frame .gif file in C#?memberjackyxio0:36 24 Jul '04  
GeneralHow do I change the Color Palette of Gif Imagesusspubba18:04 2 Jul '04  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 29 Jan 2002
Editor: Brian Delahunty
Copyright 2002 by Norm .net
Everything else Copyright © CodeProject, 1999-2008
Web15 | Advertise on the Code Project