CxImageMNG – A class to read MNG, JNG and PNG images

Environment: VC6

Introduction

CxImageMNG is the module of CxImage
used to play MNG animations. It uses the CxImage members, but to play the animation
are necessary additional variables and functions. I decided to keep separated
the MNG stuff from the "static" formats, to limit the growth of the
base class due to the new features.

As with the other modules, CxImageMNG is mainly an interface for the LibMNG
functions, it takes care of the I/O operations and of the specific requirements
of the library. CxImageMNG can read also PNG and JNG images.

This class requires some extra libraries to work: LibMNG, you can find
here the latest version; JPEG and ZLIB libraries, used by LibMNG to endode/decode files. All these libraries are included in the source code.

Structures & callbacks

"Libmng makes extensive use of callback functions. This is meant to keep
the library as platform-independant and flexible as possible.", in CxImageMNG
these are declared as:

mng_setcb_errorproc    (mng_handle, mymngerror);
mng_setcb_openstream   (mng_handle, mymngopenstream);
mng_setcb_closestream  (mng_handle, mymngclosestream);
mng_setcb_readdata     (mng_handle, mymngreadstream);
mng_setcb_processheader(mng_handle, mymngprocessheader);
mng_setcb_getcanvasline(mng_handle, mymnggetcanvasline);
mng_setcb_refresh      (mng_handle, mymngrefresh);
mng_setcb_gettickcount (mng_handle, mymnggetticks);
mng_setcb_settimer     (mng_handle, mymngsettimer);
mng_setcb_refresh      (mng_handle, mymngrefresh);

Some of these are empty (mymngopenstream), or obvious (mymngreadstream), the most useful for the final applications are mymngprocessheader, where we get the first informations about the image, and mymngsettimer, where get the essential value for the timer.

Another important parameter is pUserdata, where the application
can store its parameters, in CxImageMNG this is a pointer to the mnginfo variable.

typedef struct
  {
  FILE *file;        // file handle
  BYTE *image;       // image pixels
  HANDLE thread;     // timer
  mng_uint32 delay;  // timer duration
  mng_uint32 width;  // image attributes
  mng_uint32 height;
  mng_uint32 effwdt;
  mng_int16 bpp;
  mng_bool animation; // true if it's an animation
  mng_bool animation_enabled; // enable the timer
  float speed;       // speed factor
  } mngstuff;

In the callbacks, these informations are available at all times through the
mng_get_userdata function.

How to play animations

First we must load the file:

image = new CxImageMNG();
image->ReadFile(filename);

then, if it’s an animation, we must create a thread to play it:

if (image->mnginfo.animation) {
  image->mnginfo.animation_enabled=1;
  DWORD dwID;
  image->mnginfo.thread = CreateThread( NULL,
                                        0,
                                        RunMNGThread,
                                        this,
                                        0,
                                        &dwID);
}

In the end we must handle the execution of the thread :

unsigned long _stdcall RunMNGThread(void *lpParam){
  Sleep((DWORD)(image->mnginfo.delay / image->mnginfo.speed));
  while (image->mnginfo.animation_enabled && image->Resume()){
    SendMessage(hWnd, WM_USER_NEWFRAME,0,0);
    Sleep((DWORD)(image->mnginfo.delay / image->mnginfo.speed));
  }
  image->mnginfo.thread=0;
  return 0;
}

The WM_USER_NEWFRAME message tells to the main application that
a new frame is ready to be shown. The Resume() function is used
to obtain the next frame.
To stop the animation simply set image->mnginfo.animation_enabled =
0.
The thread is automatically closed in the CxImageMNG destructor.

Finally you can display the image: image->Draw(pDC->GetSafeHdc());

Credits.

More specific credits and disclaimers are in every header file of each library.

Downloads

Download demo – 166 Kb

Download full source code – 754 Kb

More by Author

Must Read