libmng(3)


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

   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)





Opportunity


Personal Opportunity - Free software gives you access to billions of dollars of software at no cost. Use this software for your business, personal use or to develop a profitable skill. Access to source code provides access to a level of capabilities/information that companies protect though copyrights. Open source is a core component of the Internet and it is available to you. Leverage the billions of dollars in resources and capabilities to build a career, establish a business or change the world. The potential is endless for those who understand the opportunity.

Business Opportunity - Goldman Sachs, IBM and countless large corporations are leveraging open source to reduce costs, develop products and increase their bottom lines. Learn what these companies know about open source and how open source can give you the advantage.





Free Software


Free Software provides computer programs and capabilities at no cost but more importantly, it provides the freedom to run, edit, contribute to, and share the software. The importance of free software is a matter of access, not price. Software at no cost is a benefit but ownership rights to the software and source code is far more significant.


Free Office Software - The Libre Office suite provides top desktop productivity tools for free. This includes, a word processor, spreadsheet, presentation engine, drawing and flowcharting, database and math applications. Libre Office is available for Linux or Windows.





Free Books


The Free Books Library is a collection of thousands of the most popular public domain books in an online readable format. The collection includes great classical literature and more recent works where the U.S. copyright has expired. These books are yours to read and use without restrictions.


Source Code - Want to change a program or know how it works? Open Source provides the source code for its programs so that anyone can use, modify or learn how to write those programs themselves. Visit the GNU source code repositories to download the source.





Education


Study at Harvard, Stanford or MIT - Open edX provides free online courses from Harvard, MIT, Columbia, UC Berkeley and other top Universities. Hundreds of courses for almost all major subjects and course levels. Open edx also offers some paid courses and selected certifications.


Linux Manual Pages - A man or manual page is a form of software documentation found on Linux/Unix operating systems. Topics covered include computer programs (including library and system calls), formal standards and conventions, and even abstract concepts.