plucky (3) libmng.3.gz

Provided by: libmng-dev_2.0.3+dfsg-4build1_amd64 bug

NAME

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

SYNOPSIS

       #include <libmng.h>

DESCRIPTION

       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 <http://www.libpng.org/pub/mng/spec/>.

       Other  information  about  MNG  can be found at the MNG home page, <http://www.libpng.org/pub/mng/>.  The
       latest version of libmng can be found at its own homepage at <http://www.libmng.com/>.

       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,  <http://www.zlib.org/>.   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 <http://www.ijg.org/>.

       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 <http://www.littlecms.com/>.

       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-points.

       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 parameters.

       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-style.

       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.

   Initialization
       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 paragraph.

       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.

   Cleanup
       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 respectively.

       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 library.

       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!

   Setup
       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,
                                               MNG_TRUE);
           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 place.

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

                   ...etc...

               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

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

           mng_getbkgdline

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

           mng_getalphaline

       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 channel.

       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 yourself.

   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 used.

       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
           mng_processarow

       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,
                                               MNG_TRUE);
           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 */;
             else
               /* 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 animation.

       - 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!

   Setup
       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

SEE ALSO

       mng(5),jng(5),png(5),libpng(3)

       libmng :

              http://www.libmng.com

       zlib :

              http://www.info-zip.org/pub/infozip/zlib/

       IJG JPEG library :

              http://www.ijg.org

       lcms (little CMS) by Marti Maria Saguer :

              http://www.littlecms.com/

       MNG specification:

              http://www.libpng.org/pub/mng

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

AUTHORS

       This man page: Gerard Juyn <gerard at libmng.com>

       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 distribution.

       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 appreciated.

Remarks

       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)