---
name: "libmng"
section: "3"
platform: "linux"
package: "libmng"
version: "2.0.3-4"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/libmng"
---

# libmng(3)

Multiple-image Network Graphics (MNG) Reference Library 1.0.9

## 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)](/zlib/3.md)* **compression library, and optionally the JPEG library by the Independant** **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 Independant 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)](/one/1.md) 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 capabilites.** **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 dependant modification

**not finished yet**

## SEE ALSO

*[mng(5)](/mng/5.md),*[jng(5)](/jng/5.md),*[png(5)](/png/5.md),*[libpng(3)](/libpng/3.md)

**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)**
