Loading JPEGs to DirectDraw Surfaces
The first step to loading JPEGs is to download the Intel JPEG Library from Intel's website. The Library is loaded with documentation and examples, all of which we're really not interested in. What we really want are the IJL.H, IJL15.LIB, and IJL15.DLL files that come with the package. Once you have those files, include the IJL.H header to your source file, add the IJL15.LIB file to your project, and make sure the IJL15.DLL is in a valid location such as the C:\WINDOWS\SYSTEM folder.
There are a few more things we need to do before beginning. We need to make sure that we have a Direct Draw Surface to work with:
LPDIRECTDRAWSURFACE7 Surface = NULL;DDObject->SetDisplayMode(640, 480, 24, 0, 0);IJLERR jerr;
JPEG_CORE_PROPERTIES jcprops;jerr = ijlInit(&jcprops);
if (jerr != IJL_OK)
//report initialization errorAt this point, we must decide if we are going to load our JPEG image from a file or from a buffer. Because loading from a file takes fewer steps, we will do that here. However, I give an example of loading from both in the EXAMPLE.ZIP file included with this article. We load from a file by changing our JPEG object's JPGFile member to a file name. We then call ijlRead to retrieve the file parameters.
jcprops.JPGFile = FileName;
jerr = ijlRead(&jcprops, IJL_JFILE_READPARAMS);
if (jerr != IJL_OK)
//report read errorWe start by creating a buffer to hold our image data. After the buffer is created, we must resize it to fit a 24Bit image:
//Prepare a 24Bit buffer to receive image data
BYTE *buffer24;
//Determine the required size
long szbuff24 = (jcprops.JPGWidth * 24 + 7) / 8
* jcprops.JPGHeight;
//Resize the buffer and check for null
buffer24 = new BYTE [szbuff24];
if (buffer24 == NULL)
//Report memory allocation errorjcprops.DIBWidth = jcprops.JPGWidth;
jcprops.DIBHeight = jcprops.JPGHeight; //Implies a bottom-up DIB.
jcprops.DIBChannels = 3;
jcprops.DIBColor = IJL_BGR;
jcprops.DIBPadBytes = IJL_DIB_PAD_BYTES(jcprops.JPGWidth, 3);
jcprops.DIBBytes = reinterpret_cast <BYTE*> (buffer24);//This is what you should do if you find your images are coming out upside down.
jcprops.DIBHeight = - jcprops.JPGHeight;//Set the JPG color space ... this will always be somewhat of an
//educated guess at best because JPEG is "color blind" (i.e.,
//nothing in the bit stream tells you what color space the data was
//encoded from.
switch(jcprops.JPGChannels)
{
case 1: jcprops.JPGColor = IJL_G;
break;
case 3: jcprops.JPGColor = IJL_YCBCR;
break;
default:
//This catches everything else, but no color twist will be
//performed by the IJL.
jcprops.DIBColor = (IJL_COLOR)IJL_OTHER;
jcprops.JPGColor = (IJL_COLOR)IJL_OTHER;
break;
}//Read in image from file
jerr = ijlRead(&jcprops, IJL_JFILE_READWHOLEIMAGE);
if (jerr != IJL_OK)
//Report read errorHBITMAP hbm;
//Create the bitmap and get a handle to it
hbm = CreateBitmap (jcprops.JPGWidth, jcprops.JPGHeight, 1, 24, buffer24);
if(hbm == NULL)
//Report failure to create bitmapBefore we go any further, we need to make sure that we have a Direct Draw surface to copy our bitmap to. Set up the Direct Draw surface description and create the surface:
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = jcprops.JPGWidth;
ddsd.dwHeight = jcprops.JPGHeight;
Result = DDObject->CreateSurface(&ddsd, &Surface, NULL);
if (Result != DD_OK)
//Report surface creation errorDDCopyBitmap(Surface, hbm, 0, 0, 0, 0);//We no longer need our image buffer
delete buffer24;
//Release the JPEG object
ijlFree(&jcprops);RECT Image;
//Reset surface description
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof( ddsd );
//Get the surface description so that we can dynamically
//find the width and height of our surface
Result = Surface->GetSurfaceDesc(&ddsd);
if (Result == DD_OK)
{
//Coordinates of image size
Image.left = 0;
Image.top = 0;
Image.right = ddsd.dwWidth;
Image.bottom = ddsd.dwHeight;
//Blit image to back buffer
while (true)
{
Result = BackBuffer->BltFast (0, 0, Surface, &Image,
DDBLTFAST_WAIT | DDBLTFAST_NOCOLORKEY);
if( Result == DD_OK ) break;
if( Result == DDERR_SURFACELOST )
{ Result = RestoreAll();
if( Result != DD_OK ) break; }
if( Result != DDERR_WASSTILLDRAWING ) break;
}
}Good luck, and have fun with JPEGs!
Johnny Wood
[email="blake@cst.net"]blake@cst.net[/email]
[email="johnnynin@yahoo.com"]johnnynin@yahoo.com[/email]
http://www.cst.net/~blake
Related Tutorials
Procedural Generation of 2D Tile Maps in Games
The article explains how to build a procedural 2D cave map generator using cellular automata. It covers map representat…
Localizing A Game Into French — Which Variant Should You Choose?
So, you’re making an awesome indie game, and now you’re thinking about localizing it into French? Great idea! There ar…
How Long Does It Take To Localize An Indie Game?
So you’re planning on localizing your indie game, but you’re not sure how much time to schedule in. While the timing o…
Creating game videos: best practices and pitfalls to avoid
Game video production: practical tips on how to create a game trailer or teaser that you can be proud of. Give your aud…
Adopting CI/CD: How Midwinter Entertainment iterates at speed with the help of IMS
Game development was once like one long sprint: a huge effort until you reached the finish line — at which point you co…
GameDev.net
5 Things to Consider When Making a Video to Promote Your App or Game
How can you show an app or game in your video in a way that attracts new users? Let’s take a look at what to go by when…
Discussion
More from Johnny Wood
Comparing Shadow Mapping Techniques with Shadow Explorer
New Incentives and a Whole New Platform From The Intel AppUp developer program
The final installment in this series on Intel's AppUp program details additional incentives and opportunities for devel…
The Game Maker
This book excerpt contains the first chapter of the book that introduces beginning game developers to the Game Maker pr…
Discussion