Provided by: libmng-dev_2.0.3+dfsg-3_amd64 bug


       libmng - Multiple-image Network Graphics (MNG) Reference Library 1.0.9


       #include <libmng.h>


       The   libmng   library   supports   decoding,  displaying,  encoding,  and  various  other
       manipulations of the Multiple-image Network Graphics (MNG) format image files. It uses the
       zlib(3) compression library, and optionally the JPEG library by the Independent JPEG Group
       (IJG) and/or lcms (little cms), a color-management library by Marti Maria Saguer.

I. Introduction

       This file describes how to use and modify the MNG reference library (known as libmng)  for
       your   own  use.   There  are  seven  sections  to  this  file:  introduction,  callbacks,
       housekeeping, reading, displaying, writing, and modification and configuration  notes  for
       various   special  platforms.  We  assume  that  libmng  is  already  installed;  see  the
       INSTALL.README file for instructions on how to install libmng.

       Libmng was written to support and promote the MNG specification.

       The MNG-1.0 specification is available at <>.

       Other   information   about   MNG   can   be    found    at    the    MNG    home    page,
       <>.   The  latest  version of libmng can be found at its own
       homepage at <>.

       In most cases the library will not need to be changed.  For standardization  purposes  the
       library contains both a Windows DLL and a makefile for building a shared library (SO). The
       library is written in C, but an interface for Borland Delphi is also available.

       Libmng has been designed to handle multiple sessions at one time, to be easily modifiable,
       to  be  portable  to the vast majority of machines (ANSI, K&R, 32-, and 64-bit) available,
       and to be easy to use.

       Libmng uses zlib for its compression and decompression of MNG files.  Further  information
       about  zlib,  and  the  latest  version  of  zlib,  can  be  found  at the zlib home page,
       <>.  The zlib compression utility is a general purpose utility that is
       useful for more than MNG/PNG files, and can be used without libmng.  See the documentation
       delivered with zlib for more details.

       Libmng optionally uses the JPEG library by the Independent JPEG Group (IJG). This  library
       is  used  for  the  JNG sub-format, which is part of the MNG specification, and allows for
       inclusion of JPEG decoded and  thus  highly  compressed  (photographic)  images.   Further
       information  about  the  IJG  JPEG  library  and  the  latest  sources  can  be  found  at

       Libmng can also optionally use the lcms (little CMS) library by Marti Maria  Saguer.  This
       library  provides  an  excellent  color-management  system  (CMS),  which gives libmng the
       ability to provide full color-correction for  images  with  the  proper  color-information
       encoded.     Further    information   and   the   latest   sources   can   be   found   at

       Libmng is thread safe, provided the threads are using different handles as returned by the
       initialization  call.   Each  thread  should  have  its own handle and thus its own image.
       Libmng does not protect itself against two threads using the same instance of a handle.

       The libmng.h header file is the single reference needed for programming with libmng:

       #include <libmng.h>

II. Callbacks

       Libmng makes extensive use of callback functions. This is meant to  keep  the  library  as
       platform-independant  and flexible as possible.  Actually, the first call you will make to
       the library, already contains three parameters you can  use  to  provide  callback  entry-

       Most functions must return a mng_bool (boolean). Returning MNG_FALSE indicates the library
       the callback failed in some way and the library will immediately return from  whatever  it
       was doing back to the application. Returning MNG_TRUE indicates there were no problems and
       processing can continue.

       Let's step through each of the possible callbacks. The sections on reading, displaying and
       writing will also explain which callbacks are needed when and where.

       - mng_ptr mng_memalloc (mng_size_t iLen)

       A  very  basic  function  which the library uses to allocate a memory-block with the given
       size. A typical implementation would be:

           mng_ptr my_alloc (mng_size_t iLen) {
             return calloc (1, iLen);

       Note that the library requires you to zero-out the memory-block!!!

       - void mng_memfree (mng_ptr    pPtr,
                           mng_size_t iLen)

       Counterpart of the previous function. Typically:

           void my_free (mng_ptr pPtr, mng_size_t iLen) {
             free (pPtr);

       - mng_bool mng_openstream  (mng_handle hHandle)

       - mng_bool mng_closestream (mng_handle hHandle)

       These are called by the library just before it starts to process (either read or write)  a
       file  and  just  after  the  processing  stops.   This  is the recommended place to do I/O
       initialization & finalization.  Whether you do or not, is up to you. The library does  not
       put any meaning into the calls. They are simply provided for your convenience.

       - mng_bool mng_readdata (mng_handle  hHandle,
                                mng_ptr     pBuf,
                                mng_uint32  iBuflen,
                                mng_uint32p pRead)

       This function is called when the library needs some more input while reading an image. The
       reading  process  supports  two  modes:  Suspension-mode  (SMOD)  and  non-suspension-mode
       (NSMOD).  See mng_set_suspensionmode() for a more detailed description.

       In  NSMOD,  the  library  requires  you to return exactly the amount of bytes requested (=
       iBuflen). Any lesser amount indicates the input file is exhausted  and  the  library  will
       return a MNG_UNEXPECTEDEOF errorcode.

       In  SMOD, you may return a smaller amount of bytes than requested.  This tells the library
       it  should  temporarily  wait  for  more  input  to  arrive.  The  lib  will  return  with
       MNG_NEEDMOREDATA,  and  will  expect  a  call to mng_read_resume() or mng_display_resume()
       next, as soon as more input-data has arrived.

       For NSMOD this function could be as simple as:

           mng_bool my_read (mng_handle  hHandle,
                             mng_ptr     pBuf,
                             mng_uint32  iBuflen,
                             mng_uint32p pRead) {
             *pRead = fread (pBuf, 1, iBuflen, myfile);
             return MNG_TRUE;

       - mng_bool mng_writedata (mng_handle  hHandle,
                                 mng_ptr     pBuf,
                                 mng_uint32  iBuflen,
                                 mng_uint32p pWritten)

       This function is called during the mng_write() function to actually  output  data  to  the
       file.  There  is no suspension-mode during write, so the application must return the exact
       number of bytes the library requests to be written.

       A typical implementation could be:

           mng_bool my_write (mng_handle  hHandle,
                              mng_ptr     pBuf,
                              mng_uint32  iBuflen,
                              mng_uint32p pWritten) {
             *pWritten = fwrite (pBuf, 1, iBuflen, myfile);
             return MNG_TRUE;

       - mng_bool mng_errorproc (mng_handle  hHandle,
                                 mng_int32   iErrorcode,
                                 mng_int8    iSeverity,
                                 mng_chunkid iChunkname,
                                 mng_uint32  iChunkseq,
                                 mng_int32   iExtra1,
                                 mng_int32   iExtra2,
                                 mng_pchar   zErrortext)

       This function is called whenever an error is detected inside  the  library.  This  may  be
       caused by invalid input, callbacks indicating failure, or wrongfully calling functions out
       of place.

       If you do not provide this callback the library will still return an  errorcode  from  the
       called  function,  and  the  mng_getlasterror() function can be used to retrieve the other

       This function is currently only provided for convenience, but may at some point be used to
       indicate certain errors may be acceptable, and processing should continue.

       - mng_bool mng_traceproc (mng_handle hHandle,
                                 mng_int32  iFuncnr,
                                 mng_int32  iFuncseq,
                                 mng_pchar  zFuncname)

       This  function  is  provided  to  allow  a functional analysis of the library. This may be
       useful if you encounter certain errors and cannot determine what the problem is.

       Almost all functions inside the library will activate this callback  with  an  appropriate
       function-name  at  the  start  and  end of the function. Please note that large images may
       generate an enormous amount of calls.

       - mng_bool mng_processheader (mng_handle hHandle,
                                     mng_uint32 iWidth,
                                     mng_uint32 iHeight)

       This function is called once the header information of an input- image has been processed.
       At  this point the image dimensions are available and also some other properties depending
       on the type of the image. Eg. for a  MNG  the  frame-/layercount,  playtime  &  simplicity
       fields are known.

       The  primary  purpose  of  this  callback  is to inform the application of the size of the
       image, and for the application to initialize the drawing canvas to be used by the library.
       This is also a good point to set the canvas-style. Eg. mng_set_canvasstyle().

       - mng_bool mng_processtext (mng_handle hHandle,
                                   mng_uint8  iType,
                                   mng_pchar  zKeyword,
                                   mng_pchar  zText,
                                   mng_pchar  zLanguage,
                                   mng_pchar  zTranslation)

       This  callback  is  activated  for each textual chunk in the input- image. These are tEXt,
       zTXt & iTXt. It may be used to retain specific comments for presentation to the user.

       - mng_bool mng_processsave (mng_handle hHandle)

       - mng_bool mng_processseek (mng_handle hHandle,
                                   mng_pchar  zName)

       The purpose of these callbacks is to signal the processing of the SAVE & SEEK chunks in  a
       MNG  input-file. This may be used in the future to specify some special processing. At the
       moment these functions are only provided as a signal.

       - mng_ptr mng_getcanvasline (mng_handle hHandle,
                                    mng_uint32 iLinenr)

       - mng_ptr mng_getbkgdline   (mng_handle hHandle,
                                    mng_uint32 iLinenr)

       - mng_ptr mng_getalphaline  (mng_handle hHandle,
                                    mng_uint32 iLinenr)

       These callbacks are used to access the drawing canvas, background canvas and  an  optional
       separate alpha-channel canvas. The latter is used only with the MNG_CANVAS_RGB8_A8 canvas-

       If the getbkgdline() callback  is  not  supplied  the  library  will  composite  fully  or
       partially  transparent  pixels  in  the  image  against  a specified background color. See
       mng_set_bgcolor() for more details.  If a chosen canvas-style includes  an  alpha-channel,
       this callback is very likely not needed.

       The  application  is responsible for returning a pointer to a line of pixels, which should
       be  in  the  exact  format  as  defined  by  the   call   to   mng_set_canvasstyle()   and
       mng_set_bkgdstyle(),  without  gaps  between  the  representation  of  each  pixel, unless
       specified by the canvas-style.

       - mng_bool mng_refresh (mng_handle hHandle,
                               mng_uint32 iX,
                               mng_uint32 iY,
                               mng_uint32 iWidth,
                               mng_uint32 iHeight)

       This callback is called when the library has drawn  a  complete  frame  onto  the  drawing
       canvas,  and it is ready to be displayed.  The application is responsible for transferring
       the drawing canvas from memory onto the actual output device.

       - mng_uint32 mng_gettickcount (mng_handle hHandle)

       This function should return the number of milliseconds on some internal clock. The  entire
       animation  timing  depends  heavily on this function, and the number returned should be as
       accurate as possible.

       - mng_bool mng_settimer (mng_handle hHandle,
                                mng_uint32 iMsecs)

       This callback is activated every time the library  requires  a  "pause".   Note  that  the
       function  itself  should  NOT  execute the wait. It should simply store the time-field and
       allow the  library  to  return.  Libmng  will  return  with  the  MNG_NEEDTIMERWAIT  code,
       indicating the callback was called and it is now time to execute the pause.

       After  the  indicated  number  of  milliseconds  have elapsed, the application should call
       mng_display_resume(), to resume the animation as planned.

       This method allows for both a real timer or a simple  wait  command  in  the  application.
       Whichever  method you select, both the gettickcount() and settimer() callbacks are crucial
       for proper animation timing.

       - mng_bool mng_processgamma  (mng_handle hHandle,
                                     mng_uint32 iGamma)

       - mng_bool mng_processchroma (mng_handle hHandle,
                                     mng_uint32 iWhitepointx,
                                     mng_uint32 iWhitepointy,
                                     mng_uint32 iRedx,
                                     mng_uint32 iRedy,
                                     mng_uint32 iGreenx,
                                     mng_uint32 iGreeny,
                                     mng_uint32 iBluex,
                                     mng_uint32 iBluey)

       - mng_bool mng_processsrgb   (mng_handle hHandle,
                                     mng_uint8  iRenderingintent)

       - mng_bool mng_processiccp   (mng_handle hHandle,
                                     mng_uint32 iProfilesize,
                                     mng_ptr    pProfile)

       - mng_bool mng_processarow   (mng_handle hHandle,
                                     mng_uint32 iRowsamples,
                                     mng_bool   bIsRGBA16,
                                     mng_ptr    pRow)

       These callbacks are only required when  you  selected  the  MNG_APP_CMS  directive  during
       compilation of the library. See the configuration section for more details.

       - mng_bool mng_iteratechunk (mng_handle  hHandle,
                                    mng_handle  hChunk,
                                    mng_chunkid iChunkid,
                                    mng_uint32  iChunkseq)

       This  callback  is  only used for the mng_iterate_chunks() function.  It is called exactly
       once for each chunk stored.

III. Housekeeping

   Memory management
       The library can use internal memory allocation/deallocation or use provided callbacks  for
       its  memory  management.  The  choice  is  made  at  compilation  time. See the section on
       customization for details.

       If internal management has been selected,  the  memory  callback  functions  need  not  be
       supplied.  Even  if  you  do  supply  them they will not be used.  The actual code used is
       similar to the code discussed in the callback section:

             pPtr = calloc (1, iLen);

             free (pPtr);

       If your compiler does not support these functions, or you wish to  monitor  the  library's
       use  of  memory  for  certain reasons, you can choose to compile the library with external
       memory management. In this case the memory callback functions MUST be supplied, and should
       function as if the above code was used.

       The basic initialization of the library is short and swift:

           myhandle = mng_initialize (myuserdata, my_alloc,
                                      my_free, MNG_NULL);
           if (myhandle == MNG_NULL)
             /* process error */;

       The  first  field  is  an  application-only  parameter.  It  is saved in libmng's internal
       structures and available at all times through the  mng_get_userdata()  function.  This  is
       especially  handy  in callback functions if your program may be handling multiple files at
       the same time.

       The second and third field supply the library with the  memory  callback  function  entry-
       points.  These  are  described  in  more  detail  in the callback section and the previous

       The fourth and last field may be used to supply the library  with  the  entry-point  of  a
       trace callback function. For regular use you will not need this!

       The  function  returns  a  handle  which  will  be  your  ticket to MNG-heaven.  All other
       functions rely on this handle. It is the single fixed unique reference-point between  your
       application and the library.

       You  should  call  the  initialization  function  for  each  image  you  wish  to  process
       simultaneously. If you are processing images consecutively, you  can  reset  the  internal
       status  of  the  library  with  the  mng_reset()  function.   This function will clear all
       internal state variables, free any stored chunks and/or objects, etc, etc. Your  callbacks
       and other external parameters will be retained.

       After  you  successfully received the handle it is time to set the required callbacks. The
       sections on reading, displaying & writing indicate which callbacks are required and  which
       are optional.  To set the callbacks simply do:

           myretcode = mng_setcb_xxxxxx (myhandle, my_xxxxxx);
           if (myretcode != MNG_NOERROR)
             /* process error */;

       Naturally you'd replace the x's with the name of the callback.

       Once you've gotten hold of that precious mng_handle, you should always, and I mean always,
       call the cleanup function when you're done.  Just do:

           mng_cleanup (myhandle);

       And you're done. There shouldn't be an ounce of memory spilled after that call.

       Note that if you would like to process multiple files consecutively you do not need to  do
       mng_cleanup() / mng_initialize() between each file but simply

           myretcode = mng_reset (myhandle);
           if (myretcode != MNG_NOERROR)
             /* process error */;

       will suffice. Saves some time and effort, that.

   Error handling
       From  the examples in the previous paragraphs you may have noticed a meticulous scheme for
       error handling. And yes, that's exactly what it is.  Practically each call simply  returns
       an   errorcode,  indicating  success,  eg.  MNG_NOERROR  or  failure,  anything  else  but
       MNG_NEEDMOREDATA and MNG_NEEDTIMERWAIT. These latter two will be discussed in more  detail
       in  their  respective  fields  of  interest:  the  reading  section and displaying section

       It is the application's responsibility to check the returncode after each  call.  You  can
       call  mng_getlasterror()  to  receive  the  details  of the last detected error. This even
       includes a discriptive error-message if you enabled that option during compilation of  the

       Note that after receiving an error it is still possible to call the library, but it's also
       very likely that any following call will fail.  The only functions deemed to work will  be
       mng_reset()  and mng_cleanup().  Yes, if you abort your program after an error, you should
       still call mng_cleanup().

IV. Reading

       Reading a MNG, JNG or PNG is fairly easy. It depends slightly on your  ultimate  goal  how
       certain specifics are to be handled, but the basics are similar in all cases.

       For   the   read  functioins  to  work  you  must  have  compiled  the  library  with  the
       MNG_READ_SUPPRT directive. The standard DLL and Shared Library have this on by default!

       Naturally you must have initialized the library and be the  owner  of  a  mng_handle.  The
       following callbacks are essential:

           mng_openstream, mng_readdata, mng_closestream

       You may optionally define:

           mng_errorproc, mng_traceproc
           mng_processheader, mng_processtext
           mng_processsave, mng_processseek

       The  reading  bit will also fail if you are already creating or displaying a file. Seems a
       bit obvious, but I thought I'd mention it, just in case.

   To suspend or not to suspend
       There is one choice you need to make before calling the read function.  Are you in need of
       suspension-mode or not?

       If  you're  reading  from  a disk you most certainly do not need suspension-mode. Even the
       oldest and slowest of disks will be fast enough for straight reading.

       However, if your input comes from a really slow device,  such  as  a  dialup-line  or  the
       likes, you may opt for suspension-mode. This is done by calling

           myretcode = mng_set_suspensionmode (myhandle,
           if (myretcode != MNG_NOERROR)
             /* process error */;

       Suspension-mode  will force the library to use special buffering on the input. This allows
       your  application  to  receive  data  of  arbitrarily  length  and  return  this  in   the
       mng_readdata() callback, without disturbing the chunk processing routines of the library.

       Suspension-mode does require a little extra care in the main logic of the application. The
       read function may return with MNG_NEEDMOREDATA when the  mng_readdata()  callback  returns
       less  data then it needs to process the next chunk. This indicates the application to wait
       for more data to arrive and then resume processing by calling mng_read_resume().

   The read HLAPI
       The actual reading is just plain simple. Since all I/O is done outside the library through
       the  callbacks,  the  library  can  focus  on  its  real task. Understanding, checking and
       labelling the input data!

       All you really need to do is this:

           myretcode = mng_read (myhandle);
           if (myretcode != MNG_NOERROR)
             /* process error */;

       Of course, if you're on suspension-mode the code is a little more complicated:

           myretcode = mng_read (myhandle);

           while (myretcode == MNG_NEEDMOREDATA) {
             /* wait for input-data to arrive */
             myretcode = mng_read_resume (myhandle);

           if (myretcode != MNG_NOERROR)
             /* process error */;

       This is rather crude and  more  sophisticated  programming  methods  may  dictate  another
       approach.  Whatever  method  you  decide on, it should act as if the above code was in its

       There is also the mng_readdisplay() function, but this  is  discussed  in  the  displaying
       section.  It functions pretty much as the mng_read() function, but also immediately starts
       displaying the image.  mng_read_resume() should be  replaced  by  mng_display_resume()  in
       that case!

   What happens inside
       What  actually  happens inside the library depends on the configuration options set during
       the compilation of the library.

       Basically the library will first read the 8-byte file header, to  determine  its  validity
       and the type of image it is about to process. Then it will repeatedly read a 4-byte chunk-
       length and then the remainder of the chunk until it either reaches EOF (indicated  by  the
       mng_readdata()  callback)  or  implicitly  decides  EOF as it processed the logically last
       chunk of the image.

       Applications that require strict conformity and do not allow superfluous  data  after  the
       ending chunk, will need to perform this check in their mng_closestream() callback.

       Each  chunk is then checked on CRC, after which it is handed over to the appropriate chunk
       processing routine. These routines will disect  the  chunk,  check  the  validity  of  its
       contents, check its position with respect to other chunks, etc, etc.

       If everything checks out, the chunk is further processed as follows:

       If   display   support   has   been   selected  during  compilation,  certain  pre-display
       initialization will take place.

       If chunk-storage support has been selected during compilation,  the  chunks  data  may  be
       stored in a special internal structure and held for future reference.

   Storing and accessing chunks
       One  of  the  compilation options activates support for chunk storage.  This option may be
       useful if you want to examine an image. The directive is MNG_STORE_CHUNKS. You  must  also
       turn on the MNG_ACCESS_CHUNKS directive.

       The  actual  storage  facility  can  be  turned  on  or off with the mng_set_storechunks()
       function. If set to MNG_TRUE, chunks will be stored as they are read.

       At any point you can then call the mng_iterate_chunks() function to  iterate  through  the
       current  list  of chunks. This function requires a callback which is called for each chunk
       and receives  a  specific  chunk-handle.  This  chunk-handle  can  be  used  to  call  the
       appropriate mng_getchunk_xxxx() function, to access the chunks properties.

       A typical implementation may look like this:

           mng_bool my_iteratechunk (mng_handle  hHandle,
                                     mng_handle  hChunk,
                                     mng_chunkid iChunkid,
                                     mng_uint32  iChunkseq) {
             switch (iChunkid) {
               case MNG_UINT_MHDR : { /* process MHDR */;
                                      break; }
               case MNG_UINT_FRAM : { /* process FRAM */;
                                      break; }


               case MNG_UINT_HUH  : { /* unknown chunk */;
                                      break; }
               default : { /* duh; forgot one */; }

             return MNG_TRUE; /* keep'm coming */

       To get to the actual chunk fields of lets say a SHOW chunk you would do:

           mng_bool isempty;
           mng_uint16 firstid, lastid;
           mng_uint8 showmode;

           myretcode mng_getchunk_show (hHandle, hChunk,
                                        isempty, firstid,
                                        lastid, showmode);
           if (myretcode != MNG_NOERROR)
             /* process error */;

V. Displaying

       Assuming you have initialized the library and are the owner of a mng_handle. The following
       callbacks are essential:

           mng_getcanvasline, mng_refresh
           mng_gettickcount, mng_settimer

       If you wish to use an application supplied background you must supply:


       If you wish to use the MNG_CANVAS_RGB8_A8 canvas style you must supply:


       You may optionally define:

           mng_errorproc, mng_traceproc
           mng_processheader, mng_processtext
           mng_processsave, mng_processseek

       Note that the mng_processheader() callback is optional but will be quite  significant  for
       proper operation!

       Displaying  an  image will fail if you are creating a file or already displaying one. Yes,
       you can't display it twice!

   A word on canvas styles
       The canvas style describes how your drawing canvas is made up.  You must set  this  before
       the  library actually starts drawing, so the mng_processheader() callback is a pretty good
       place for it.

       Currently only 8-bit RGB canvas styles are supported, either  with  or  without  an  alpha

       If  you like to do alpha composition yourself you can select one of the canvas styles that
       include an alpha channel. You can even have a  separate  alpha  canvas  by  selecting  the
       MNG_CANVAS_RGB8_A8 style.

       All  styles  require  a  compact  model. Eg. MNG_CANVAS_BGR8 requires your canvas lines in
       bgrbgrbgr... storage, where each letter represents an 8-bit  value  of  the  corresponding
       color, and each threesome makes up the values of one(1) pixel.

       The  library  processes  a  line at a time, so the canvas lines do not actually need to be
       consecutive in memory.

   Alpha composition and application backgrounds
       All Network Graphics can be partially transparent. This requires special processing if you
       need  to  display  an image against some background. Note that the MNG header (MHDR chunk)
       contains a simplicity field indicating whether transparency information  in  the  file  is
       critical or not. This only applies to embedded images, which means the full image-frame of
       the MNG may still contain fully transparent pixels!

       Depending on your needs you can supply a single background color, a background  canvas  or
       tell the library to return the alpha-channel and do alpha composition yourself.

       This  is different from the BACK chunk in a MNG, or the bKGD chunk in an (embedded) PNG or
       JNG. The BACK chunk indicates an optional or mandatory background color and/or image.  The
       bKGD  chunk only indicates an optional background color. These chunks indicate the Authors
       preferences. They may be absent in which case you need to supply some sort  of  background

   Composing against a background color
       This  is  the easiest method. Call the mng_set_bgcolor() function to set the values of the
       red, green and blue component of your preferred background color.

       Use one of the canvas styles that do not have an alpha-channel,  and  which  matches  your
       output requirements.

   Composing against a background canvas
       This  is  somewhat  more complicated. You will need to set the mng_getbkgdline() callback.
       This will be called whenever the library needs to compose a partially transparent line.

       This canvas must hold the background against which the image should be composed. Its  size
       must match exactly with the image dimensions and thus the drawing canvas!

       Use  one  of  the  canvas styles that do not have an alpha-channel, and which matches your
       output requirements. The canvas style of the background canvas may even  differ  from  the
       drawing canvas. The library's composing will still function properly.

   Composing within the application
       If you have the option in your application to draw a (partially) transparent canvas to the
       output device, this option is preferred.

       Select one of the canvas styles that do have  an  alpha-channel.   The  library  will  now
       supply the appropriate alpha information, allowing the application to compose the image as
       it sees fit.

   Color information and CMS
       Network Graphics  may,  and  usually  will,  contain  color-correction  information.  This
       information  is intended to compensate for the difference in recording and display devices

       This  document  does  not  address  the  specifics  of  color-management.   See  the   PNG
       specification for a more detailed description.

   Using little cms by Marti Maria Saguer
       This  is  the  easiest  method,  providing  you  can compile the lcms package.  Select the
       MNG_FULL_CMS directive during compilation, and sit back and relax. The library  will  take
       care of all color-correction for you.

   Using an OS- or application-supplied CMS
       If  you are so lucky to have access to CMS functionality from within your application, you
       may instruct the library to leave color-correction to you.

       Select the MNG_APP_CMS directive during compilation of the library.  You MUST also set the
       following callbacks:

           mng_processgamma, mng_processchroma,
           mng_processsrgb, mng_processiccp and

       The  last  callback  is  called when the library needs you to correct an arbitrary line of
       pixels. The other  callbacks  are  called  when  the  corresponding  color-information  is
       encountered  in  the  file.   You  must  store  this  information somewhere for use in the
       mng_processarow() callback.

   Using gamma-only correction
       This isn't a preferred method, but it's better  than  no  correction  at  all.  Gamma-only
       correction  will  at  least compensate for gamma-differences between the original recorder
       and your output device.

       Select the MNG_GAMMA_ONLY directive during compilation of the library. Your compiler  MUST
       support fp operations.

   No color correction
       Ouch. This is really bad. This is the least preferred method, but may be necessary if your
       system cannot use lcms, doesn't have its own CMS, and does not allow fp operations, ruling
       out the gamma-only option.

       Select  the  MNG_NO_CMS  directive  during  compilation.   Images  will  definitely not be
       displayed as seen by the Author!!!

   Animations and timing
       Animations require some form of timing support. The library relies on  two  callbacks  for
       this  purpose.  The mng_gettickcount() and mng_settimer() callbacks. mng_gettickcount() is
       used to determine the  passing  of  time  in  milliseconds  since  the  beginning  of  the
       animation.  This  is  also  used to compensate during suspension-mode if you are using the
       mng_readdisplay() function to read & display the file simultaneously.

       The callback may return an arbitrary number of milliseconds, but this number must increase
       proportionaly between calls. Most modern systems will have some tickcount() function which
       derives its input from an internal clock. The value returned from this  function  is  more
       than adequate for libmng.

       The  mng_settimer()  callback  is  called  when the library determines a little "pause" is
       required before rendering another frame of the  animation.  The  pause  interval  is  also
       expressed   in  milliseconds.   Your  application  should  store  this  value  and  return
       immediately.  The library will then make appropriate arrangements to  store  its  internal
       state and returns to your application with the MNG_NEEDTIMERWAIT code.

       At  that  point you should suspend processing and wait the given interval. Please use your
       OS features for this. Do not engage some sort  of  loop.  That  is  real  bad  programming
       practice.  Most  modern  systems will have some timing functions. A simple wait() function
       may suffice, but this may prevent your applications main-task from running,  and  possibly
       prevent the actual update of your output device.

   The mng_refresh() callback
       The  mng_refresh()  callback  is  called whenever the library has "finished" drawing a new
       frame onto your canvas, and just before it will call the mng_settimer() callback.

       This allows you to perform some actions necessary to "refresh" the canvas onto your output
       device.  Please do NOT suspend processing inside this callback. This must be handled after
       the mng_settimer() callback!

   Displaying while reading
       This method is preferred if you are reading from a slow input device (such  as  a  dialup-
       line)   and  you  wish  to  start  displaying  something  as  quickly  as  possible.  This
       functionality is provided mainly for browser-type applications but may be appropriate  for
       other applications as well.

       The  method  is  usually  used  in  unison  with the suspension-mode of the read module. A
       typical implementation would look like this:

           /* initiale library and set required callbacks */

           /* activate suspension-mode */
           myretcode = mng_set_suspensionmode (myhandle,
           if (myretcode != MNG_NOERROR)
             /* process error */;

           myretcode = mng_readdisplay (myhandle);

           while ((myretcode == MNG_NEEDMOREDATA) ||
                  (myretcode == MNG_NEEDTIMERWAIT)) {
             if (myretcode == MNG_NEEDMOREDATA)
               /* wait for more input-data */;
               /* wait for timer interval */;

             myretcode = mng_display_resume (myhandle);

           if (myretcode != MNG_NOERROR)
             /* process error */;

       More advanced programming methods may require a different approach, but the  final  result
       should function as in the code above.

   Displaying after reading
       This method is used to display a file that was previously read.  It is primarily meant for
       viewers with direct file access, such as 1a local harddisk.

       Once you have successfully read the file, all you need to do is:

           myretcode = mng_display (myhandle);

           while (myretcode == MNG_NEEDTIMERWAIT) {
             /* wait for timer interval */;
             myretcode = mng_display_resume (myhandle);

           if (myretcode != MNG_NOERROR)
             /* process error */;

       Again, more advanced programming methods may require a different approach, but  the  final
       result should function as in the code above.

   Display manipulation
       Several  HLAPI  functions are provided to allow a user to manipulate the normal flow of an

       - mng_display_freeze (mng_handle hHandle)

       This will "freeze" the animation in place.

       - mng_display_resume (mng_handle hHandle)

       This function can be used to resume a frozen animation, or to force the library to advance
       the animation to the next frame.

       - mng_display_reset (mng_handle hHandle)

       This  function  will "reset" the animation into its pristine state.  Calling mng_display()
       afterwards will re-display the animation from the first frame.

       - mng_display_golayer (mng_handle hHandle,
                               mng_uint32 iLayer)

       - mng_display_goframe (mng_handle hHandle,
                               mng_uint32 iFrame)

       - mng_display_gotime (mng_handle hHandle,
                              mng_uint32 iPlaytime)

       These three functions can be used to "jump" to a specific layer, frame or timeslot in  the
       animation. You must "freeze" the animation before using any of these functions.

       All  above  functions  may only be called during a timer interval!  It is the applications
       responsibility to cleanup any resources with respect to the timer wait.

VI. Writing

       The main focus of the library lies in its displaying  capabilities.   But  it  does  offer
       writing  support  as  well.   You can create and write a file, or you can write a file you
       have previously read, providing the storage of chunks was enabled and active.

       For this to work you must have  compiled  the  library  with  the  MNG_WRITE_SUPPO1RT  and
       MNG_ACCESS_CHUNKS directives. The standard DLL and Shared Library have this on by default!

       As  always  you  must  have  initialized the library and be the owner of a mng_handle. The
       following callbacks are essential:

           mng_openstream, mng_writedata, mng_closestream

       You can optionally define:

           mng_errorproc, mng_traceproc

       The creation and writing functions will fail if you are in the middle of reading, creating
       or writing a file.

   Creating a new file
       To  start a new file the library must be in its initial state.  First you need to tell the
       library your intentions:

           myretcode = mng_create (myhandle);
           if (myretcode != MNG_NOERROR)
             /* process error */;

       After that you start adding the appropriate chunks:

           myretcode = mng_put1chunk_mhdr (myhandle, ...);
           if (myretcode != MNG_NOERROR)
             /* process error */;

       And so on, and so forth. Note that the library will automatically signal the  logical  end
       of  the  file  by  the  ending  chunk.  Also the first chunk will indicate the library the
       filetype (eg. PNG, JNG or MNG) and force the proper signature when writing the file.

       The code above can be simplified, as you can always get the last errorcode  by  using  the
       mng_getlasterror() function:

           if ( (mng_putchunk_xxxx (myhandle, ...)) or
                (mng_putchunk_xxxx (myhandle, ...)) or
                    ...etc...                          )
             /* process error */;

       Please  note  that  you  must have a pretty good understanding of the chunk specification.
       Unlike the read functions, there are virtually no checks, so it is quite possible to write
       completely  wrong files.  It is a good practice to read back your file into the library to
       verify its integrity.

       Once you've got all the chunks added, all you do is:

           myretcode mng_write (myhandle);
           if (myretcode != MNG_NOERROR)
             /* process error */;

       And presto. You're done. The real work is of course carried out in  your  callbacks.  Note
       that this is a single operation as opposed to the read & display functions that may return
       with MNG_NEEDMOREDATA and/or MNG_NEEDTIMERWAIT. The write function just does the job,  and
       only returns after it's finished or if it encounters some unrecoverable error.

   Writing a previously read file
       If you have already successfully read a file, you can use the library to write it out as a
       copy or something. You MUST have compiled the library with the MNG_STORE_CHUNKS directive,
       and you must have done mng_set_storechunks (myhandle, MNG_TRUE).

       This  doesn't  require the MNG_ACCESS_CHUNKS directive, unless you want to fiddle with the
       chunks as well.

       Again all you need to do is:

           myretcode mng_write (myhandle);
           if (myretcode != MNG_NOERROR)
             /* process error */;

VII. Modifying/Customizing libmng:

       not finished yet

   Compilation directives
       not finished yet

   Platform dependent modification
       not finished yet



       libmng :


       zlib :


       IJG JPEG library :


       lcms (little CMS) by Marti Maria Saguer :


       MNG specification:


       In the case of any inconsistency between the  MNG  specification  and  this  library,  the
       specification takes precedence.


       This man page: Gerard Juyn <gerard at>

       The contributing authors would like to thank all those who helped with testing, bug fixes,
       and patience.  This wouldn't have been possible without all of you!!!


       Copyright (c) 2000-2002 Gerard Juyn

       For the purposes of this copyright and license, "Contributing Authors" is defined  as  the
       following set of individuals:

          Gerard Juyn

       The  MNG  Library  is supplied "AS IS".  The Contributing Authors disclaim all warranties,
       expressed or implied, including, without limitation, the warranties of merchantability and
       of  fitness  for  any  purpose.   The Contributing Authors assume no liability for direct,
       indirect, incidental, special, exemplary, or consequential damages, which may result  from
       the use of the MNG Library, even if advised of the possibility of such damage.

       Permission  is  hereby  granted  to use, copy, modify, and distribute this source code, or
       portions hereof, for any purpose, without fee, subject to the following restrictions:

       1. The origin of this source code must not be misrepresented; you must not claim that  you
       wrote the original software.

       2. Altered versions must be plainly marked as such and must not be misrepresented as being
       the original source.

       3. This Copyright notice may not be removed or altered from any source or  altered  source

       The  Contributing  Authors specifically permit, without fee, and encourage the use of this
       source code as a component to supporting  the  MNG  and  JNG  file  format  in  commercial
       products.   If  you  use  this  source  code  in a product, acknowledgment would be highly


       Parts of this software have been adapted from the libpng library.  Although  this  library
       supports  all  features  from  the PNG specification (as MNG descends from it) it does not
       require the libpng library.  It does require the zlib library and optionally the IJG  JPEG
       library, and/or the "little-cms" library by Marti Maria Saguer (depending on the inclusion
       of support for JNG and Full-Color-Management respectively.

       This library's function is primarily to read and display MNG animations. It is  not  meant
       as  a  full-featured  image-editing  component! It does however offer creation and editing
       functionality at the chunk level. (future modifications may include some more support  for
       creation and or editing)

                                        January 30th, 2005                              LIBMNG(3)