Loading animated gifs in MDX

Published August 07, 2006
Advertisement
Another little side project this time. It's not that I'm not working on GB.Net, I am. I even set a goal of adding at least 20 opcodes a day. It's just that I don't have anything to show screenshot wise, unless you want some IDE screenshots[wink].

Anyway todays entry is about loading animated gifs in MDX. The process is rather simple since the .Net Bitmap class takes care of all the work [smile].

Currently though it just stores all the seperate frames as individual textures, which seems like a bad idea for batching. What I'd like to do is make it into one big sprite sheet. The problem is that I can't figure out how to read pixels from the bitmap. I tried creating a Graphics object around the Bitmap, but that doesn't seem to do what I want. Anyone have any ideas?

I figured it out. Now it builds a large sprite sheet in memory and generates a texture from that. It reads the frames in a horizontal fashion and makes sure not to go past the maximum texture width, so you can load large animated gifs. Unfortunately if you go past both the max width and max height, then you're totally fucked [grin].

I've left the simpler texture array version below.

Image time(as usual).

The gif I'm loading:


The result:


The (new) codes:
using System;using Diagnostics = System.Diagnostics;using Drawing = System.Drawing;using DirectX = Microsoft.DirectX;using Direct3D = Microsoft.DirectX.Direct3D;namespace Test{	public class GifSprite	{				public readonly int FrameHeight = 0;				public readonly int FramesHorizontal = 0;				public readonly int Frames = 0;				public readonly int FramesVertical = 0;				public readonly int FrameWidth = 0;				public readonly int Height = 0;				private static Direct3D.Sprite Sprite = null;				private Direct3D.Texture Texture = null;				private Drawing.Rectangle[] RectangleArray = null;						public readonly int Width = 0;				public GifSprite( string FileName, Direct3D.Device Device  )		{			if( Sprite == null )			{				Sprite = new Direct3D.Sprite( Device );			}			Drawing.Image GifImage = Drawing.Image.FromFile( FileName );			Drawing.Graphics GifImageGraphics = null;			FrameWidth = GifImage.Width;			FrameHeight = GifImage.Height;			Frames = GifImage.GetFrameCount( new Drawing.Imaging.FrameDimension( GifImage.FrameDimensionsList[0] ) );			FramesHorizontal = Device.DeviceCaps.MaxTextureWidth / FrameWidth;			if( FramesHorizontal > Frames )			{				FramesHorizontal = Frames;				FramesVertical = 1;			}			else			{				FramesVertical = ( Frames / FramesHorizontal ) + ( ( Frames % FramesHorizontal > 0 ) ? 1 : 0 );			}			Width = FramesHorizontal * FrameWidth;			Height = FramesVertical * FrameHeight;			Drawing.Bitmap Bitmap = new Drawing.Bitmap( Width, Height );			Drawing.Graphics BitmapGraphics = Drawing.Graphics.FromImage( Bitmap );			RectangleArray = new Drawing.Rectangle[Frames];			for( int i = 0; i < Frames; i++ )			{				RectangleArray = new Drawing.Rectangle( ( i % FramesHorizontal ) * FrameWidth, ( i / FramesHorizontal ) * FrameHeight, FrameWidth, FrameHeight );				GifImage.SelectActiveFrame( new Drawing.Imaging.FrameDimension( GifImage.FrameDimensionsList[0] ), i );				GifImageGraphics = Drawing.Graphics.FromImage( GifImage );				BitmapGraphics.DrawImage( GifImage, RectangleArray );			}			Texture = new Direct3D.Texture( Device, Bitmap, Direct3D.Usage.SoftwareProcessing, Direct3D.Pool.Managed );			return;		}				~GifSprite()		{			if( Texture != null )        		{        			if( Texture.Disposed == false )        			{            				Texture.Dispose();        			}        		}            		return;        	}				public static void Begin( Direct3D.SpriteFlags SpriteFlags )		{			Sprite.Begin( SpriteFlags );			return;		}				public void Draw( int X, int Y, int Frame, Drawing.Color Color )		{			Sprite.Draw( Texture, RectangleArray[Math.Abs(Frame)%Frames], DirectX.Vector3.Empty, new DirectX.Vector3( X, Y, 0.1f ), Color.ToArgb() );			return;		}				public static void End()		{			Sprite.End();			return;		}			}	}


Here's what the generated sprite sheet looks like(thanks to Bitmap.Save):


The (old) codes:
using System;using Diagnostics = System.Diagnostics;using Drawing = System.Drawing;using DirectX = Microsoft.DirectX;using Direct3D = Microsoft.DirectX.Direct3D;namespace Test{	public class GifSprite	{				public int Frames		{			get			{				return TextureArray.Length;			}		}				private static Direct3D.Sprite Sprite = null;				private Direct3D.Texture[] TextureArray = null;				public GifSprite( string FileName, Direct3D.Device Device  )		{			if( Sprite == null )			{				Sprite = new Direct3D.Sprite( Device );			}			Drawing.Bitmap Bitmap = new Drawing.Bitmap( FileName );			TextureArray = new Direct3D.Texture[ Bitmap.GetFrameCount( new Drawing.Imaging.FrameDimension(Bitmap.FrameDimensionsList[0] ) ) ];			for( int i = 0; i < Frames; i++ )			{				Bitmap.SelectActiveFrame( new Drawing.Imaging.FrameDimension( Bitmap.FrameDimensionsList[0] ), i );				TextureArray = new Direct3D.Texture( Device, Bitmap, Direct3D.Usage.SoftwareProcessing, Direct3D.Pool.Managed );			}			return;		}				public static void Begin( Direct3D.SpriteFlags SpriteFlags )		{			Sprite.Begin( SpriteFlags );			return;		}				public void Draw( int X, int Y, int Frame, Drawing.Color Color )		{			Sprite.Draw( TextureArray[Math.Abs(Frame)%Frames], DirectX.Vector3.Empty, new DirectX.Vector3( X, Y, 0.1f ), Color.ToArgb() );			return;		}				public static void End()		{			Sprite.End();			return;		}			}	}
Previous Entry Rise of the Parser
Next Entry Yet another project
0 likes 4 comments

Comments

sirob
MDX has a method to create a texture from a bitmap that also allows you to specify the pool. If you create textures in the scratch pool using this method, you could lock them and copy them to a default pool texture.
The great benefit of using this method is that MDX would take care of any conversions that need to take place from the bitmap format to the texture format.

Also, cool gif.

Hope this helps :)
August 07, 2006 10:37 AM
Scet
hmm I see what you're getting at. Use the current method but instead of storing each texture just copy it's data to a bigger one.

Actually I think could do the same thing with the Bitmap, thus avoiding creating and managing a bunch of Textures. I think I'll try that.

Thanks.
August 07, 2006 10:46 AM
Rob Loach
One thing to note is the low quality of GIF images. But that certainly is pretty awesome!
August 07, 2006 03:29 PM
Scet
Yeah I know GIFs for the most part really suck, but they are OK for low-res paletted images.

Anyway I'll probably just stick to using bitmap sprite sheets, but at least I can load animated gifs if should ever want to.
August 07, 2006 04:17 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement