• Advertisement
Sign in to follow this  
  • entries
    177
  • comments
    531
  • views
    163906

Loading animated gifs in MDX

Sign in to follow this  

161 views

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;
}

}

}







Sign in to follow this  


4 Comments


Recommended Comments

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 :)

Share this comment


Link to comment
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.

Share this comment


Link to comment
One thing to note is the low quality of GIF images. But that certainly is pretty awesome!

Share this comment


Link to comment
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.

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement