Blue Theme Orange Theme Green Theme Red Theme
 
Home | Forums | Videos | Advertise | Certifications | Downloads | Blogs | Interviews | Jobs | Beginners | Training
 | Consulting  
Submit an Article Submit a Blog 
 Jump to
Skip Navigation Links
TechnologyExpand Technology
WebsiteExpand Website
6 Months Free & No Setup Fees ASP.NET Hosting!
Search :       Advanced Search »
Home » DirectX C# » Working with DirectDraw and Bitmap Images

Working with DirectDraw and Bitmap Images

This month in the C-sharp DirectX column, we will be adding bitmap image support to our game engine.

Page Views : 42955
Downloads : 1536
Rating :
 Rate it
Level : Intermediate
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
Download Files:
BitmapRectangleEffect.zip | ShowBitmapImage.zip
 
 
6 Months Free & No Setup Fees ASP.NET Hosting!
Become a Sponsor
6 Months Free & No Setup Fees ASP.NET Hosting!
Become a Sponsor
 Tag Cloud
 Latest Jobs
More ... 
 Latest Interview Questions
More ... 

A long time ago........ . . . in another CPU galaxy, people where playing pong, pac-man and a dozen of other sprite-to-screen based games while someone was saying that 640k ought to be enough for everyone.

Since that time many things have changed. This includes the fact that we nowadays store thousands of sprites that have been manipulated with all kinds of colored effects by using an GUI application on a gigabyte hard disk, and started to call the result an image.
Stored images makes live so much easier. You can draw them in whatever paint program you prefer, save them to disk and use the result within your application or hence: game.
A picture image in DirectX is nothing more than a surface which can be loaded from your hard disk. By theory you can have up to as many surfaces as you would like, but for the sake of blue screens on your friends computer we always take memory consumption into account.

You can calculate the amount of bytes needed by using the following formula:
Width * Height * bytes per pixel

So on an canvas with the dimension of 800x600x16bit this will be.
800 x 600 x 2 = 960,000 bytes

If you work with 32bit mode, you will add an extra two bytes per pixel
800 x 600 x 4 = 1,920,000 bytes

Note: For a double-buffering application you will also be using a minimum of two fullsized surfaces for the primary and backbuffer.

Blitting your bits:

If you had a home computer you probably remember some terms like the blitter, or software blits. Blitting is used to make realtime image animations or just to combine a bunch of images on one surface. In more detail it is a way to transport a certain part of your image surface to a destination point on a surface.
 

 

Creating a bitmap surface class

Lets get on with it and extend our little framework to support bitmap images. I will explain the needed parts in between the code, so you will actualy understand the stuff I will present. We will create a new class that is capable of loading an image from a file and blit a certain rectangle on a destination surface.

DirectXBitmapSurface.cs

using System;
using DxVBLib;
namespace DX_CSharp_2
{
///
/// Summary description for DirectXBitmapSurface.
///
public class DirectXBitmapSurface
{
private DirectDrawSurface7 BitmapSurface;
protected DDSURFACEDESC2 BitmapSurfaceDescription;

The DirectDraw DDSURFACEDESC2 structure describes related information about our surface. This includes depth, width and height which must be initialized before actually using the DirectDrawSurface7.

We will create some public properties, so we can play a bit with the DDSURFACEDESC2 structure from outside our class code.

public int Width
{
get { return BitmapSurfaceDescription.lWidth; }
set { BitmapSurfaceDescription.lWidth = value; }
}
public int Height
{
get { return BitmapSurfaceDescription.lHeight; }
set { BitmapSurfaceDescription.lHeight = value; }
}

The DDSURFACEDESC2.lWidth and the DDSURFACEDESC2.lheight properties are quite useful when you got an image that needs to be stretched or shrunk onto the destination surface without touching the actual file. With a minor bit of code, you can use these properties to create your own zoom effects at run-time.

public DirectXBitmapSurface()
{ }

Next, we will create a public initialization function that takes two arguments. The first one is an initialized DirectDraw object needed for the creation of the surface, and the second one is a string containing the path to the Windows bitmap file. The DirectDraw CreateSurfaceFromFile function will populate the reference pointing to the DDSURFACEDESC2 structure. This means that the related information describing the image like e.g. Width, Height, and pixel format is loaded into a seperate structure. DirectDraw can only handle Windows bitmap (.bmp) images directly. This does not mean you can't use .Gif or .Jpg images at all. These picture types it requires to create a filetype specific loader, and then load the surface from memory by using the DirectDraw CreateSurfaceFromResource function. For me a bitmap image is a bitmap image so I don't realy see the point of writting a special .Gif loader, while I can just convert the picture in a paint program. If you realy need to code such a loader, I suggest you get yourself a copy of the book "Tricks of Windows Game programming" second edition, where this is fully explained and is a good read indeed.

public void Initialize( DirectDraw7 DirectDraw, string strBackgroundBitmap)
{
BitmapSurface = DirectDraw.CreateSurfaceFromFile( strBackgroundBitmap,
ref BitmapSurfaceDescription );
}

The following function will globalize the BltFast functions so we can access it from our DirectX application class. The first argument is the DirectDrawSurface7 surface we want to blit our bitmap surface on. The X and Y values specify the location on the destination surface we are going to blit to. The last argument contains the reference to a rectangle which specifies the part of the source we want to blit. I overload the rectangle function, so you can easily blit the complete source image onto the destination position of the surface without the specifying the original size.

public void BltFast(DirectDrawSurface7 objBackBufferSurface, int int_X, int int_Y)
{
objBackBufferSurface.BltFast( int_X, int_Y,
this.BitmapSurface, ref blitRectangle, CONST_DDBLTFASTFLAGS.DDBLTFAST_NOCOLORKEY | CONST_DDBLTFASTFLAGS.DDBLTFAST_DONOTWAIT );
}
public void BltFast(DirectDrawSurface7 objBackBufferSurface, int int_X, int int_Y, RECT RECTblitRectangle)
{
objBackBufferSurface.BltFast( int_X, int_Y,
this.BitmapSurface, ref RECTblitRectangle, CONST_DDBLTFASTFLAGS.DDBLTFAST_NOCOLORKEY | CONST_DDBLTFASTFLAGS.DDBLTFAST_DONOTWAIT );
}
}
}

The DirectX constants CONST_DDBLTFASTFLAGS.DDBLTFAST_DONOTWAIT means that if the blitter is too busy the blit will be ignored. We will be updating game screens at a high rate, so dont worry if a blit gets ignored because the blitter was too busy. If a blit gets ignored it is due the fact that the CPU can not handle it, it is always better to unload some of its work rather than queuing more actions by using CONST_DDBLTFASTFLAGS.DDBLTFAST_WAIT. The DDBLTFAST_NOCOLORKEY constant indicates that I will not make use of transparency keys when blitting to the destionation. If you want to keep the source image transparency for the destionation surface, you should use of the DDBLTFAST_SRCCOLORKEY. You can even specify to apply the destionation transparency to the source blitting rectangle with DDBLTFAST_DESTCOLORKEY.

Thats all for our DirectX bitmap class code for now, so lets go back to our main DirectX application code that we created in the first article and implement the class to view some nifty pics !!!

DirectXApp.cs

using System;
using System.Windows.Forms; // Application DoEvents
using DxVBLib;
namespace DX_CSharp_2
{
///
/// Summary description for DirectXApp.
///
public class DirectXApp
{
private DirectXWrapper DX = new DirectXWrapper();
private DirectXBitmapSurface DX_overlay = new DirectXBitmapSurface();
...

We will jump to the initialization part of the DirectX application class and add the initialization code for our fresh created class object.

...
public void Initialize()
{
DX.InitializeDirectXFullScreen(
this.handle,this.screenwidth,this.screenheight,this.screenbits);
DX.InitializeDirectInput(
this.handle);
DX_overlay.Width =
this.screenwidth;
DX_overlay.Height =
this.screenheight;
DX_overlay.Initialize(DX.DirectDraw, @"critikill.bmp");
}
...

As you can see I decided to stretch the image as the exact screen size in order to fill the whole screen. If you do not specify these properties, the original image width and height will be used.
There is no problem with blitting a smaller surface onto a bigger surface, but the other way around will not work because when blitting a surface you can not exceed the size limit of the destination surface.

Our main loop will clear the backbuffer surface and blit the image when it exceeds the specified FPS limit. In this loop we also check if a quit button is pressed, in order to trigger the Application.Exit.

private void MainLoop()
{
//get the current ticks
int intCurrentTickCount = GetTickCount();
while (this.running)
{
// If the number of milliseconds elapsed the setted frames per second then UPDATE screen
if (GetTickCount() - (1000/this.framespersecond) >= intCurrentTickCount)
{
/*
** KeyHandler
*/

this.DX.DirectInput.Acquire();
this.DX.DirectInput.UpdateKeyBoardState();
if ( DX.DirectInput.KEYB_STATE.key[ (int)CONST_DIKEYFLAGS.DIK_RETURN ]==0x80 | DX.DirectInput.KEYB_STATE.key[ (int)CONST_DIKEYFLAGS.DIK_ESCAPE ]==0x80 )
{
DX.DD_BackbufferSurface.DrawText(100,100,"Exit",
false);
Application.Exit();
}
/*
** Clear BackBuffer
*/

DX.RepaintBackBuffer();
/*
** Blit Background Picture
*/

this.DX_overlay.BltFast( DX.DD_BackbufferSurface,0,0);
/*
** Flip the backbuffer surface to primary surface
*/

DX.FlipBackBufferAndPrimary();
//get current tick count
intCurrentTickCount = GetTickCount();
//do windows events
Application.DoEvents();
}
//do windows events
Application.DoEvents();
}
}

Creating animated effects using the blitter
 
You may not realize it yet, but with the blitting functions that we have created in the DirectXBitmapSurface class are enough to get started with funky bitmap animations effects. The only thing you will need to do is to change the blitting destination position each time a frame or a certain time elapse.

You can also choose to blit multiple different rectangles of the source surface onto the destination surface before flipping to the primary surface. The result of that will look something like below.


Youre still not impressed by this picture, are you? Well okay, I will show you how to create an animated version of this right now, and you can tell me all about it per email later!!!

Explanation of the animation example:
 
The animation effect we will pull off will do the following effects: At initialization point it will create a specified amount of DirectX rectangles with random positions, which then are used in the main loop to blit parts of the source surface onto the backbuffer canvas. If the blitted rectangle is still within the destination screen boundary, it will move across the screen to the bottom-right corner and it will re-appear at a random point on the screen.

RectFX/RandomRect.cs

using System;
using DxVBLib;
namespace DX_CSharp_2.RectFX
{
///
/// RECT Randomizer
///
public class RandomRect
{
private RECT rndrect;
public RECT RndRECT
{
get { return rndrect; }
}
private int rectsize = 40;
public int RectSize
{
get { return rectsize; }
set { rectsize = value; }
}
public int X
{
get { return this.rndrect.Left; }
set
{
rndrect.Left =
value;
rndrect.Right = rndrect.Left +
this.rectsize;
}
}
public int Y
{
get { return this.rndrect.Top; }
set
{
this.rndrect.Top = value;
this.rndrect.Bottom = this.rndrect.Top + this.RectSize;
}
}
public RandomRect()
{ }
public void RandomizeRect(int intSeed, int max_screenWidth, int max_screenHeight)
{
Random r =
new Random(intSeed);
rndrect.Right = r.Next(0,max_screenWidth - rectsize);
rndrect.Bottom = r.Next(0,max_screenHeight - rectsize);
rndrect.Left = rndrect.Right - rectsize;
rndrect.Top = rndrect.Bottom - rectsize;
}
}
}

And there it is !! A nice piece of code that creates a RECT at a random position with the ability to move it's offset by the X and Y properties. Now we need to add some code to our DirectXApp.cs code in order to create an Array of these objects, and do some tricks with it.

DirectXApp.cs

...
//initialize an Array of RandomRectangles
RectFX.RandomRect[] RandomRect = new RectFX.RandomRect[200];
private void CreateRandomRects()
{
for (int i=0;i<=RandomRect.GetUpperBound(0);i++)
{
RandomRect[i] =
new RectFX.RandomRect();
RandomRect[i].RectSize = 40;
RandomRect[i].RandomizeRect(
this.GetTickCount()/(i+2)*100*(i+1), this.ScreenWidth , this.ScreenHeight);
}
}
private void BlitRndRectsToBackBuffer()
{
for (int i=0;i<=RandomRect.GetUpperBound(0);i++)
{
// If the rectangle is out of the screen, we will randomize it again
// to a new point on the screen.
if ( (RandomRect[i].RndRECT.Right& (RandomRect[i].RndRECT.Bottom)
{
RandomRect[i].X++;
RandomRect[i].Y++;
}
else
{
RandomRect[i].RandomizeRect (
this.GetTickCount()/(i+2)*100*(i+1) , this.ScreenWidth , this.ScreenHeight);
}
this.DX_overlay.BltFast ( DX.DD_BackbufferSurface , RandomRect[i].RndRECT.Left , RandomRect[i].RndRECT.Top , RandomRecti].RndRECT);
}
...

Modify the MainLoop to use the BlitRndRectsToBackBuffer instead of displaying the whole picture from our last example and you are all set-up !!!

private void MainLoop()
{
...
/*
** Clear BackBuffer
*/

DX.RepaintBackBuffer();
/*
** Blit Background Picture
*/

//this.DX_overlay.BltFast( DX.DD_BackbufferSurface,0,0);
BlitRndRectsToBackBuffer();
...
}

Thats it for now boys and girls !!!
You should now able to display an image on a DirectX screen and I have also shown you how to create some basic effect using rectangles. Next to rectangle clipping effects, you can also do quite a lot more funky stuff by using locking an surface an reading pixel data, but that was quite a bit out of scope for our first encounter so we will dive into that somewhat later. You should now get your nose up the keyboard and try out your own effects.

Comment Request!
Thank you for reading this post. Please post your feedback, question, or comments about this post Here.
Login to add your contents and source code to this article
 [Top] Rate this article
 
 About the author
 
Tony Tromp
Tony Tromp is an Application Development Leader for one of the mobile telephone providers from the Orange Corporation. In this company he is taking the responsibility for the architecture and lead development of 3G mobile-, web-, and desktop based applications in order to improve the B2B and B2C flows. The last few years he has provided and introduced a great amount of XML based solutions to his company and because of the integrated XML API's in the .Net framework he is currently trying to push .Net based solutions wherever it pays off. Before joining the Orange Corporation, Tony has been working on developments of internet portals and projects. One of the more successful projects includes an Online beer ordering system for Heineken. Next to his mastered skills in C++, C#, ASP, and PHP, he is also senior Oracle Professional with a very good understanding of PL/SQL and performance tuning.
Looking for C# Consulting?
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional consulting company, our consultants are well-known experts in .NET and many of them are MVPs, authors, and trainers. We specialize in Microsoft .NET development and utilize Agile Development and Extreme Programming practices to provide fast pace quick turnaround results. Our software development model is a mix of Agile Development, traditional SDLC, and Waterfall models.
Click here to learn more about C# Consulting.
 
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Dynamic PDF
ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
Discover the Top 5 .NET Memory Management Fundamentals
To write the best .NET code, you need to know exactly how the .NET framework really manages memory. Ricky Leeks presents the Top 5 fundamental facts of .NET memory management. Learn more.
Nevron Chart for .NET 2010.1 Now Available
The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
ASP.NET 4 Hosting
Get 2 Months Free of ASP.NET Hosting for Only $4.95/month! Receive FREE MS SQL and MySQL Databases Including ASP.NET 4/3.5, MVC 3.0, Silverlight 4, Windows 2008/IIS 7.0 Plus FREE IIS 7 Modules. Host UNLIMITED ASP.NET Web Sites – Click Here!
 
 Post a Feedback, Comment, or Question about this article
Subject:
Comment:
Discover the top 5 tips for understanding .NET Interop
Become a Sponsor
 Comments
image by sou On February 15, 2007

I's a good web site.please.I need your help to find some code source in c# detecting contour of image..thank you.

email:sana.sahli@laposte.net

Reply | Email | Modify 
Nevron Chart
 © 2012  contents copyright of their authors. Rest everything copyright Mindcracker. All rights reserved.