| 1 | libmng - Multiple-image Network Graphics (MNG) Reference Library 1.0.9
|
|---|
| 2 |
|
|---|
| 3 | DESCRIPTION
|
|---|
| 4 | The libmng library supports decoding, displaying, encoding, and various
|
|---|
| 5 | other manipulations of the Multiple-image Network Graphics (MNG) format
|
|---|
| 6 | image files. It uses the zlib compression library, and optionally the
|
|---|
| 7 | JPEG library by the Independant JPEG Group (IJG) and/or
|
|---|
| 8 | lcms (little cms), a color-management library by Marti Maria Saguer.
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 | I. Introduction
|
|---|
| 12 |
|
|---|
| 13 | This file describes how to use and modify the MNG reference library
|
|---|
| 14 | (known as libmng) for your own use. There are seven sections to this
|
|---|
| 15 | file: introduction, callbacks, housekeeping, reading, displaying,
|
|---|
| 16 | writing, and modification and configuration notes for various special
|
|---|
| 17 | platforms. We assume that libmng is already installed; see the
|
|---|
| 18 | INSTALL.README file for instructions on how to install libmng.
|
|---|
| 19 |
|
|---|
| 20 | Libmng was written to support and promote the MNG specification.
|
|---|
| 21 |
|
|---|
| 22 | The latest MNG specification (currently 1.0) is available at
|
|---|
| 23 | http://www.libpng.org/pub/mng/
|
|---|
| 24 |
|
|---|
| 25 | Other information about MNG can be found at the MNG home page at
|
|---|
| 26 | http://www.libpng.org/pub/mng/
|
|---|
| 27 |
|
|---|
| 28 | The latest version of libmng can be found at its own homepage at
|
|---|
| 29 | http://www.libmng.com/
|
|---|
| 30 |
|
|---|
| 31 | In most cases the library will not need to be changed.
|
|---|
| 32 | For standardization purposes the library contains both a Windows DLL
|
|---|
| 33 | and a makefile for building a shared library (SO). The library is
|
|---|
| 34 | written in C, but an interface for Borland Delphi is also available.
|
|---|
| 35 |
|
|---|
| 36 | Libmng has been designed to handle multiple sessions at one time,
|
|---|
| 37 | to be easily modifiable, to be portable to the vast majority of
|
|---|
| 38 | machines (ANSI, K&R, 32-, and 64-bit) available, and to be easy
|
|---|
| 39 | to use.
|
|---|
| 40 |
|
|---|
| 41 | Libmng uses zlib for its compression and decompression of MNG files.
|
|---|
| 42 | Further information about zlib, and the latest version of zlib, can be
|
|---|
| 43 | found at the zlib home page, <http://www.zlib.org/>.
|
|---|
| 44 | The zlib compression utility is a general purpose utility that is
|
|---|
| 45 | useful for more than MNG/PNG files, and can be used without libmng.
|
|---|
| 46 | See the documentation delivered with zlib for more details.
|
|---|
| 47 |
|
|---|
| 48 | Libmng optionally uses the JPEG library by the Independant JPEG Group
|
|---|
| 49 | (IJG). This library is used for the JNG sub-format, which is part of
|
|---|
| 50 | the MNG specification, and allows for inclusion of JPEG decoded and
|
|---|
| 51 | thus highly compressed (photographic) images.
|
|---|
| 52 | Further information about the IJG JPEG library and the latest sources
|
|---|
| 53 | can be found at <http://www.ijg.org/>.
|
|---|
| 54 |
|
|---|
| 55 | Libmng can also optionally use the lcms (little CMS) library by
|
|---|
| 56 | Marti Maria Saguer. This library provides an excellent color-management
|
|---|
| 57 | system (CMS), which gives libmng the ability to provide full
|
|---|
| 58 | color-correction for images with the proper color-information encoded.
|
|---|
| 59 | Further information and the latest sources can be found at
|
|---|
| 60 | <http://www.littlecms.com/>.
|
|---|
| 61 |
|
|---|
| 62 | Libmng is thread safe, provided the threads are using different
|
|---|
| 63 | handles as returned by the initialization call.
|
|---|
| 64 | Each thread should have its own handle and thus its own image.
|
|---|
| 65 | Libmng does not protect itself against two threads using the
|
|---|
| 66 | same instance of a handle.
|
|---|
| 67 |
|
|---|
| 68 | The libmng.h header file is the single reference needed for programming
|
|---|
| 69 | with libmng:
|
|---|
| 70 |
|
|---|
| 71 | #include <libmng.h>
|
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 | II. Callbacks
|
|---|
| 75 |
|
|---|
| 76 | Libmng makes extensive use of callback functions. This is meant to
|
|---|
| 77 | keep the library as platform-independant and flexible as possible.
|
|---|
| 78 | Actually, the first call you will make to the library, already contains
|
|---|
| 79 | three parameters you can use to provide callback entry-points.
|
|---|
| 80 |
|
|---|
| 81 | Most functions must return a mng_bool (boolean). Returning MNG_FALSE
|
|---|
| 82 | indicates the library the callback failed in some way and the library
|
|---|
| 83 | will immediately return from whatever it was doing back to the
|
|---|
| 84 | application. Returning MNG_TRUE indicates there were no problems and
|
|---|
| 85 | processing can continue.
|
|---|
| 86 |
|
|---|
| 87 | Let's step through each of the possible callbacks. The sections on
|
|---|
| 88 | reading, displaying and writing will also explain which callbacks are
|
|---|
| 89 | needed when and where.
|
|---|
| 90 |
|
|---|
| 91 | - mng_ptr mng_memalloc (mng_size_t iLen)
|
|---|
| 92 |
|
|---|
| 93 | A very basic function which the library uses to allocate a memory-block
|
|---|
| 94 | with the given size. A typical implementation would be:
|
|---|
| 95 |
|
|---|
| 96 | mng_ptr my_alloc (mng_size_t iLen) {
|
|---|
| 97 | return calloc (1, iSize);
|
|---|
| 98 | }
|
|---|
| 99 |
|
|---|
| 100 | Note that the library requires you to zero-out the memory-block!!!
|
|---|
| 101 |
|
|---|
| 102 | - void mng_memfree (mng_ptr pPtr,
|
|---|
| 103 | mng_size_t iLen)
|
|---|
| 104 |
|
|---|
| 105 | Counterpart of the previous function. Typically:
|
|---|
| 106 |
|
|---|
| 107 | void my_free (mng_ptr pPtr, mng_size_t iLen) {
|
|---|
| 108 | free (pPtr);
|
|---|
| 109 | }
|
|---|
| 110 |
|
|---|
| 111 | - mng_bool mng_openstream (mng_handle hHandle)
|
|---|
| 112 | - mng_bool mng_closestream (mng_handle hHandle)
|
|---|
| 113 |
|
|---|
| 114 | These are called by the library just before it starts to process
|
|---|
| 115 | (either read or write) a file and just after the processing stops.
|
|---|
| 116 | This is the recommended place to do I/O initialization & finalization.
|
|---|
| 117 | Whether you do or not, is up to you. The library does not put any
|
|---|
| 118 | meaning into the calls. They are simply provided for your convenience.
|
|---|
| 119 |
|
|---|
| 120 | - mng_bool mng_readdata (mng_handle hHandle,
|
|---|
| 121 | mng_ptr pBuf,
|
|---|
| 122 | mng_uint32 iBuflen,
|
|---|
| 123 | mng_uint32p pRead)
|
|---|
| 124 |
|
|---|
| 125 | This function is called when the library needs some more input while
|
|---|
| 126 | reading an image. The reading process supports two modes:
|
|---|
| 127 | Suspension-mode (SMOD) and non-suspension-mode (NSMOD).
|
|---|
| 128 | See mng_set_suspensionmode() for a more detailed description.
|
|---|
| 129 |
|
|---|
| 130 | In NSMOD, the library requires you to return exactly the amount of bytes
|
|---|
| 131 | requested (= iBuflen). Any lesser amount indicates the input file
|
|---|
| 132 | is exhausted and the library will return a MNG_UNEXPECTEDEOF errorcode.
|
|---|
| 133 |
|
|---|
| 134 | In SMOD, you may return a smaller amount of bytes than requested.
|
|---|
| 135 | This tells the library it should temporarily wait for more input to
|
|---|
| 136 | arrive. The lib will return with MNG_NEEDMOREDATA, and will expect a
|
|---|
| 137 | call to mng_read_resume() or mng_display_resume() next, as soon as
|
|---|
| 138 | more input-data has arrived.
|
|---|
| 139 |
|
|---|
| 140 | For NSMOD this function could be as simple as:
|
|---|
| 141 |
|
|---|
| 142 | mng_bool my_read (mng_handle hHandle,
|
|---|
| 143 | mng_ptr pBuf,
|
|---|
| 144 | mng_uint32 iBuflen,
|
|---|
| 145 | mng_uint32p pRead) {
|
|---|
| 146 | *pRead = fread (pBuf, 1, iBuflen, myfile);
|
|---|
| 147 | return MNG_TRUE;
|
|---|
| 148 | }
|
|---|
| 149 |
|
|---|
| 150 | - mng_bool mng_writedata (mng_handle hHandle,
|
|---|
| 151 | mng_ptr pBuf,
|
|---|
| 152 | mng_uint32 iBuflen,
|
|---|
| 153 | mng_uint32p pWritten)
|
|---|
| 154 |
|
|---|
| 155 | This function is called during the mng_write() function to actually
|
|---|
| 156 | output data to the file. There is no suspension-mode during write,
|
|---|
| 157 | so the application must return the exact number of bytes the library
|
|---|
| 158 | requests to be written.
|
|---|
| 159 |
|
|---|
| 160 | A typical implementation could be:
|
|---|
| 161 |
|
|---|
| 162 | mng_bool my_write (mng_handle hHandle,
|
|---|
| 163 | mng_ptr pBuf,
|
|---|
| 164 | mng_uint32 iBuflen,
|
|---|
| 165 | mng_uint32p pWritten) {
|
|---|
| 166 | *pWritten = fwrite (pBuf, 1, iBuflen, myfile);
|
|---|
| 167 | return MNG_TRUE;
|
|---|
| 168 | }
|
|---|
| 169 |
|
|---|
| 170 | - mng_bool mng_errorproc (mng_handle hHandle,
|
|---|
| 171 | mng_int32 iErrorcode,
|
|---|
| 172 | mng_int8 iSeverity,
|
|---|
| 173 | mng_chunkid iChunkname,
|
|---|
| 174 | mng_uint32 iChunkseq,
|
|---|
| 175 | mng_int32 iExtra1,
|
|---|
| 176 | mng_int32 iExtra2,
|
|---|
| 177 | mng_pchar zErrortext)
|
|---|
| 178 |
|
|---|
| 179 | This function is called whenever an error is detected inside the
|
|---|
| 180 | library. This may be caused by invalid input, callbacks indicating
|
|---|
| 181 | failure, or wrongfully calling functions out of place.
|
|---|
| 182 |
|
|---|
| 183 | If you do not provide this callback the library will still return
|
|---|
| 184 | an errorcode from the called function, and the mng_getlasterror()
|
|---|
| 185 | function can be used to retrieve the other parameters.
|
|---|
| 186 |
|
|---|
| 187 | This function is currently only provided for convenience, but may
|
|---|
| 188 | at some point be used to indicate certain errors may be acceptable,
|
|---|
| 189 | and processing should continue.
|
|---|
| 190 |
|
|---|
| 191 | - mng_bool mng_traceproc (mng_handle hHandle,
|
|---|
| 192 | mng_int32 iFuncnr,
|
|---|
| 193 | mng_int32 iFuncseq,
|
|---|
| 194 | mng_pchar zFuncname)
|
|---|
| 195 |
|
|---|
| 196 | This function is provided to allow a functional analysis of the
|
|---|
| 197 | library. This may be useful if you encounter certain errors and
|
|---|
| 198 | cannot determine what the problem is.
|
|---|
| 199 |
|
|---|
| 200 | Almost all functions inside the library will activate this
|
|---|
| 201 | callback with an appropriate function-name at the start and end
|
|---|
| 202 | of the function. Please note that large images may generate an
|
|---|
| 203 | enormous amount of calls.
|
|---|
| 204 |
|
|---|
| 205 | - mng_bool mng_processheader (mng_handle hHandle,
|
|---|
| 206 | mng_uint32 iWidth,
|
|---|
| 207 | mng_uint32 iHeight)
|
|---|
| 208 |
|
|---|
| 209 | This function is called once the header information of an input-
|
|---|
| 210 | image has been processed. At this point the image dimensions are
|
|---|
| 211 | available and also some other properties depending on the type
|
|---|
| 212 | of the image. Eg. for a MNG the frame-/layercount, playtime &
|
|---|
| 213 | simplicity fields are known.
|
|---|
| 214 |
|
|---|
| 215 | The primary purpose of this callback is to inform the application
|
|---|
| 216 | of the size of the image, and for the application to initialize
|
|---|
| 217 | the drawing canvas to be used by the library. This is also a good
|
|---|
| 218 | point to set the canvas-style. Eg. mng_set_canvasstyle().
|
|---|
| 219 |
|
|---|
| 220 | - mng_bool mng_processtext (mng_handle hHandle,
|
|---|
| 221 | mng_uint8 iType,
|
|---|
| 222 | mng_pchar zKeyword,
|
|---|
| 223 | mng_pchar zText,
|
|---|
| 224 | mng_pchar zLanguage,
|
|---|
| 225 | mng_pchar zTranslation)
|
|---|
| 226 |
|
|---|
| 227 | This callback is activated for each textual chunk in the input-
|
|---|
| 228 | image. These are tEXt, zTXt & iTXt. It may be used to retain
|
|---|
| 229 | specific comments for presentation to the user.
|
|---|
| 230 |
|
|---|
| 231 | - mng_bool mng_processsave (mng_handle hHandle)
|
|---|
| 232 | - mng_bool mng_processseek (mng_handle hHandle,
|
|---|
| 233 | mng_pchar zName)
|
|---|
| 234 |
|
|---|
| 235 | The purpose of these callbacks is to signal the processing of the
|
|---|
| 236 | SAVE & SEEK chunks in a MNG input-file. This may be used in the
|
|---|
| 237 | future to specify some special processing. At the moment these
|
|---|
| 238 | functions are only provided as a signal.
|
|---|
| 239 |
|
|---|
| 240 | - mng_ptr mng_getcanvasline (mng_handle hHandle,
|
|---|
| 241 | mng_uint32 iLinenr)
|
|---|
| 242 | - mng_ptr mng_getbkgdline (mng_handle hHandle,
|
|---|
| 243 | mng_uint32 iLinenr)
|
|---|
| 244 | - mng_ptr mng_getalphaline (mng_handle hHandle,
|
|---|
| 245 | mng_uint32 iLinenr)
|
|---|
| 246 |
|
|---|
| 247 | These callbacks are used to access the drawing canvas, background
|
|---|
| 248 | canvas and an optional separate alpha-channel canvas. The latter is
|
|---|
| 249 | used only with the MNG_CANVAS_RGB8_A8 canvas-style.
|
|---|
| 250 |
|
|---|
| 251 | If the getbkgdline() callback is not supplied the library will
|
|---|
| 252 | composite full or partially transparent pixels in the image against
|
|---|
| 253 | a specified background color. See mng_set_bgcolor() for more details.
|
|---|
| 254 | If a chosen canvas-style includes an alpha-channel, this callback
|
|---|
| 255 | is very likely not needed.
|
|---|
| 256 |
|
|---|
| 257 | The application is responsible for returning a pointer to a line of
|
|---|
| 258 | pixels, which should be in the exact format as defined by the call
|
|---|
| 259 | to mng_set_canvasstyle() and mng_set_bkgdstyle(), without gaps between
|
|---|
| 260 | the representation of each pixel.
|
|---|
| 261 |
|
|---|
| 262 | - mng_bool mng_refresh (mng_handle hHandle,
|
|---|
| 263 | mng_uint32 iX,
|
|---|
| 264 | mng_uint32 iY,
|
|---|
| 265 | mng_uint32 iWidth,
|
|---|
| 266 | mng_uint32 iHeight)
|
|---|
| 267 |
|
|---|
| 268 | This callback is called when the library has drawn a complete frame
|
|---|
| 269 | onto the drawing canvas, and it is ready to be displayed.
|
|---|
| 270 | The application is responsible for transferring the drawing canvas
|
|---|
| 271 | from memory onto the actual output device.
|
|---|
| 272 |
|
|---|
| 273 | - mng_uint32 mng_gettickcount (mng_handle hHandle)
|
|---|
| 274 |
|
|---|
| 275 | This function should return the number of milliseconds on some internal
|
|---|
| 276 | clock. The entire animation timing depends heavily on this function,
|
|---|
| 277 | 1and the number returned should be as accurate as possible.
|
|---|
| 278 |
|
|---|
| 279 | - mng_bool mng_settimer (mng_handle hHandle,
|
|---|
| 280 | mng_uint32 iMsecs)
|
|---|
| 281 |
|
|---|
| 282 | This callback is activated every time the library requires a "pause".
|
|---|
| 283 | Note that the function itself should NOT execute the wait. It should
|
|---|
| 284 | simply store the time-field and allow the library to return. Libmng
|
|---|
| 285 | will return with the MNG_NEEDTIMERWAIT code, indicating the callback
|
|---|
| 286 | was called and it is now time to execute the pause.
|
|---|
| 287 |
|
|---|
| 288 | After the indicated number of milliseconds have elapsed, the application
|
|---|
| 289 | should call mng_display_resume(), to resume the animation as planned.
|
|---|
| 290 |
|
|---|
| 291 | This method allows for both a real timer or a simple wait command in the
|
|---|
| 292 | application. Whichever method you select, both the gettickcount() and
|
|---|
| 293 | settimer() callbacks are crucial for proper animation timing.
|
|---|
| 294 |
|
|---|
| 295 | - mng_bool mng_processgamma (mng_handle hHandle,
|
|---|
| 296 | mng_uint32 iGamma)
|
|---|
| 297 | - mng_bool mng_processchroma (mng_handle hHandle,
|
|---|
| 298 | mng_uint32 iWhitepointx,
|
|---|
| 299 | mng_uint32 iWhitepointy,
|
|---|
| 300 | mng_uint32 iRedx,
|
|---|
| 301 | mng_uint32 iRedy,
|
|---|
| 302 | mng_uint32 iGreenx,
|
|---|
| 303 | mng_uint32 iGreeny,
|
|---|
| 304 | mng_uint32 iBluex,
|
|---|
| 305 | mng_uint32 iBluey)
|
|---|
| 306 | - mng_bool mng_processsrgb (mng_handle hHandle,
|
|---|
| 307 | mng_uint8 iRenderingintent)
|
|---|
| 308 | - mng_bool mng_processiccp (mng_handle hHandle,
|
|---|
| 309 | mng_uint32 iProfilesize,
|
|---|
| 310 | mng_ptr pProfile)
|
|---|
| 311 | - mng_bool mng_processarow (mng_handle hHandle,
|
|---|
| 312 | mng_uint32 iRowsamples,
|
|---|
| 313 | mng_bool bIsRGBA16,
|
|---|
| 314 | mng_ptr pRow)
|
|---|
| 315 |
|
|---|
| 316 | These callbacks are only required when you selected the MNG_APP_CMS
|
|---|
| 317 | directive during compilation of the library. See the configuration
|
|---|
| 318 | section for more details.
|
|---|
| 319 |
|
|---|
| 320 | - mng_bool mng_iteratechunk (mng_handle hHandle,
|
|---|
| 321 | mng_handle hChunk,
|
|---|
| 322 | mng_chunkid iChunkid,
|
|---|
| 323 | mng_uint32 iChunkseq)
|
|---|
| 324 |
|
|---|
| 325 | This callback is only used for the mng_iterate_chunks() function.
|
|---|
| 326 | It is called exactly once for each chunk stored.
|
|---|
| 327 |
|
|---|
| 328 |
|
|---|
| 329 | III. Housekeeping
|
|---|
| 330 |
|
|---|
| 331 |
|
|---|
| 332 | > Memory management
|
|---|
| 333 |
|
|---|
| 334 | The library can use internal memory allocation/deallocation or use
|
|---|
| 335 | provided callbacks for its memory management. The choice is made at
|
|---|
| 336 | compilation time. See the section on customization for details.
|
|---|
| 337 |
|
|---|
| 338 | If internal management has been selected, the memory callback functions
|
|---|
| 339 | need not be supplied. Even if you do supply them they will not be used.
|
|---|
| 340 | The actual code used is similar to the code discussed in the callback
|
|---|
| 341 | section:
|
|---|
| 342 |
|
|---|
| 343 | pPtr = calloc (1, iSize);
|
|---|
| 344 |
|
|---|
| 345 | free (pPtr);
|
|---|
| 346 |
|
|---|
| 347 | If your compiler does not support these functions, or you wish to monitor
|
|---|
| 348 | the library's use of memory for certain reasons, you can choose to
|
|---|
| 349 | compile the library with external memory management. In this case the
|
|---|
| 350 | memory callback functions MUST be supplied, and should function as if the
|
|---|
| 351 | above code was used.
|
|---|
| 352 |
|
|---|
| 353 |
|
|---|
| 354 | > Initialization
|
|---|
| 355 |
|
|---|
| 356 | The basic initialization of the library is short and swift:
|
|---|
| 357 |
|
|---|
| 358 | myhandle = mng_initialize (myuserdata, my_alloc,
|
|---|
| 359 | my_free, MNG_NULL);
|
|---|
| 360 | if (myhandle == MNG_NULL)
|
|---|
| 361 | /* process error */;
|
|---|
| 362 |
|
|---|
| 363 | The first field is an application-only parameter. It is saved in
|
|---|
| 364 | libmng's internal structures and available at all times through the
|
|---|
| 365 | mng_get_userdata() function. This is especially handy in callback functions
|
|---|
| 366 | if your program may be handling multiple files at the same time.
|
|---|
| 367 |
|
|---|
| 368 | The second and third field supply the library with the memory callback
|
|---|
| 369 | 1function entry-points. These are described in more detail in the callback
|
|---|
| 370 | section and the previous paragraph.
|
|---|
| 371 |
|
|---|
| 372 | The fourth and last field may be used to supply the library with the
|
|---|
| 373 | entry-point of a trace callback function. For regular use you will not
|
|---|
| 374 | need this!
|
|---|
| 375 |
|
|---|
| 376 | The function returns a handle which will be your ticket to MNG-heaven.
|
|---|
| 377 | All other functions rely on this handle. It is the single fixed unique
|
|---|
| 378 | reference-point between your application and the library.
|
|---|
| 379 |
|
|---|
| 380 | You should call the initialization function for each image you wish to
|
|---|
| 381 | process simultaneously. If you are processing images consecutively, you can
|
|---|
| 382 | reset the internal status of the library with the mng_reset() function.
|
|---|
| 383 | This function will clear all internal state variables, free any stored
|
|---|
| 384 | chunks and/or objects, etc, etc. Your callbacks and other external parameters
|
|---|
| 385 | will be retained.
|
|---|
| 386 |
|
|---|
| 387 | After you successfully received the handle it is time to set the required
|
|---|
| 388 | callbacks. The sections on reading, displaying & writing indicate which
|
|---|
| 389 | callbacks are required and which are optional.
|
|---|
| 390 | To set the callbacks simply do:
|
|---|
| 391 |
|
|---|
| 392 | myretcode = mng_setcb_xxxxxx (myhandle, my_xxxxxx);
|
|---|
| 393 | if (myretcode != MNG_NOERROR)
|
|---|
| 394 | /* process error */;
|
|---|
| 395 |
|
|---|
| 396 | Naturally you'd replace the x's with the name of the callback.
|
|---|
| 397 |
|
|---|
| 398 |
|
|---|
| 399 | > Cleanup
|
|---|
| 400 |
|
|---|
| 401 | Once you've gotten hold of that precious mng_handle, you should always,
|
|---|
| 402 | and I mean always, call the cleanup function when you're done.
|
|---|
| 403 | Just do:
|
|---|
| 404 |
|
|---|
| 405 | mng_cleanup (myhandle);
|
|---|
| 406 |
|
|---|
| 407 | And you're done. There shouldn't be an ounce of memory spilled after
|
|---|
| 408 | that call.
|
|---|
| 409 |
|
|---|
| 410 | Note that if you would like to process multiple files consecutively
|
|---|
| 411 | you do not need to do mng_cleanup() / mng_initialize() between each file
|
|---|
| 412 | but simply
|
|---|
| 413 |
|
|---|
| 414 | myretcode = mng_reset (myhandle);
|
|---|
| 415 | if (myretcode != MNG_NOERROR)
|
|---|
| 416 | /* process error */;
|
|---|
| 417 |
|
|---|
| 418 | will suffice. Saves some time and effort, that.
|
|---|
| 419 |
|
|---|
| 420 |
|
|---|
| 421 | > Error handling
|
|---|
| 422 |
|
|---|
| 423 | From the examples in the previous paragraphs you may have noticed a
|
|---|
| 424 | meticulous scheme for error handling. And yes, that's exactly what it is.
|
|---|
| 425 | Practically each call simply returns an errorcode, indicating success,
|
|---|
| 426 | eg. MNG_NOERROR or failure, anything else but MNG_NEEDMOREDATA and
|
|---|
| 427 | MNG_NEEDTIMERWAIT. These latter two will be discussed in more detail in
|
|---|
| 428 | their respective fields of interest: the reading section and displaying
|
|---|
| 429 | section respectively.
|
|---|
| 430 |
|
|---|
| 431 | It is the application's responsibility to check the returncode after
|
|---|
| 432 | each call. You can call mng_getlasterror() to receive the details of
|
|---|
| 433 | the last detected error. This even includes a discriptive error-message
|
|---|
| 434 | if you enabled that option during compilation of the library.
|
|---|
| 435 |
|
|---|
| 436 | Note that after receiving an error it is still possible to call the
|
|---|
| 437 | library, but it's also very likely that any following call will fail.
|
|---|
| 438 | The only functions deemed to work will be mng_reset() and mng_cleanup().
|
|---|
| 439 | Yes, if you abort your program after an error, you should still call
|
|---|
| 440 | mng_cleanup().
|
|---|
| 441 |
|
|---|
| 442 |
|
|---|
| 443 | IV. Reading
|
|---|
| 444 |
|
|---|
| 445 | Reading a MNG, JNG or PNG is fairly easy. It depends slightly on your
|
|---|
| 446 | ultimate goal how certain specifics are to be handled, but the basics
|
|---|
| 447 | are similar in all cases.
|
|---|
| 448 |
|
|---|
| 449 | For the read functioins to work you must have compiled the library with
|
|---|
| 450 | the MNG_READ_SUPPRT directive. The standard DLL and Shared Library
|
|---|
| 451 | have this on by default!
|
|---|
| 452 |
|
|---|
| 453 |
|
|---|
| 454 | > Setup
|
|---|
| 455 |
|
|---|
| 456 | Naturally you must have initialized the library and be the owner of
|
|---|
| 457 | a mng_handle. The following callbacks are essential:
|
|---|
| 458 |
|
|---|
| 459 | mng_openstream, mng_readdata, mng_closestream
|
|---|
| 460 |
|
|---|
| 461 | You may optionally define:
|
|---|
| 462 |
|
|---|
| 463 | mng_errorproc, mng_traceproc
|
|---|
| 464 | mng_processheader, mng_processtext
|
|---|
| 465 | mng_processsave, mng_processseek
|
|---|
| 466 |
|
|---|
| 467 | The reading bit will also fail if you are already creating or
|
|---|
| 468 | displaying a file. Seems a bit obvious, but I thought I'd mention it,
|
|---|
| 469 | just in case.
|
|---|
| 470 |
|
|---|
| 471 |
|
|---|
| 472 | > To suspend or not to suspend
|
|---|
| 473 |
|
|---|
| 474 | There is one choice you need to make before calling the read function.
|
|---|
| 475 | Are you in need of suspension-mode or not?
|
|---|
| 476 |
|
|---|
| 477 | If you're reading from a disk you most certainly do not need
|
|---|
| 478 | suspension-mode. Even the oldest and slowest of disks will be fast
|
|---|
| 479 | enough for straight reading.
|
|---|
| 480 |
|
|---|
| 481 | However, if your input comes from a really slow device, such as a
|
|---|
| 482 | dialup-line or the likes, you may opt for suspension-mode. This is done
|
|---|
| 483 | by calling
|
|---|
| 484 |
|
|---|
| 485 | myretcode = mng_set_suspensionmode (myhandle,
|
|---|
| 486 | MNG_TRUE);
|
|---|
| 487 | if (myretcode != MNG_NOERROR)
|
|---|
| 488 | /* process error */;
|
|---|
| 489 |
|
|---|
| 490 | Suspension-mode will force the library to use special buffering on the
|
|---|
| 491 | input. This allows your application to receive data of arbitrarily length
|
|---|
| 492 | and return this in the mng_readdata() callback, without disturbing the
|
|---|
| 493 | chunk processing routines of the library.
|
|---|
| 494 |
|
|---|
| 495 | Suspension-mode does require a little extra care in the main logic of the
|
|---|
| 496 | 1application. The read function may return with MNG_NEEDMOREDATA when the
|
|---|
| 497 | mng_readdata() callback returns less data then it needs to process the
|
|---|
| 498 | next chunk. This indicates the application to wait for more data to arrive
|
|---|
| 499 | and then resume processing by calling mng_read_resume().
|
|---|
| 500 |
|
|---|
| 501 |
|
|---|
| 502 | > The read HLAPI
|
|---|
| 503 |
|
|---|
| 504 | The actual reading is just plain simple. Since all I/O is done
|
|---|
| 505 | 1outside the library through the callbacks, the library can focus on
|
|---|
| 506 | its real task. Understanding, checking and labelling the input data!
|
|---|
| 507 |
|
|---|
| 508 | All you really need to do is this:
|
|---|
| 509 |
|
|---|
| 510 | myretcode = mng_read (myhandle);
|
|---|
| 511 | if (myretcode != MNG_NOERROR)
|
|---|
| 512 | /* process error */;
|
|---|
| 513 |
|
|---|
| 514 | Of course, if you're on suspension-mode the code is a little more
|
|---|
| 515 | complicated:
|
|---|
| 516 |
|
|---|
| 517 | myretcode = mng_read (myhandle);
|
|---|
| 518 |
|
|---|
| 519 | while (myretcode == MNG_NEEDMOREDATA) {
|
|---|
| 520 | /* wait for input-data to arrive */
|
|---|
| 521 | myretcode = mng_read_resume (myhandle);
|
|---|
| 522 | }
|
|---|
| 523 |
|
|---|
| 524 | if (myretcode != MNG_NOERROR)
|
|---|
| 525 | /* process error */;
|
|---|
| 526 |
|
|---|
| 527 | This is rather crude and more sophisticated programming methods may
|
|---|
| 528 | dictate another approach. Whatever method you decide on, it should
|
|---|
| 529 | act as if the above code was in its place.
|
|---|
| 530 |
|
|---|
| 531 | There is also the mng_readdisplay() function, but this is discussed
|
|---|
| 532 | in the displaying section. It functions pretty much as the mng_read()
|
|---|
| 533 | function, but also immediately starts displaying the image.
|
|---|
| 534 | mng_read_resume() should be replaced by mng_display_resume() in that
|
|---|
| 535 | case!
|
|---|
| 536 |
|
|---|
| 537 |
|
|---|
| 538 | > What happens inside
|
|---|
| 539 |
|
|---|
| 540 | What actually happens inside the library depends on the configuration
|
|---|
| 541 | options set during the compilation of the library.
|
|---|
| 542 |
|
|---|
| 543 | Basically the library will first read the 8-byte file header, to determine
|
|---|
| 544 | its validity and the type of image it is about to process. Then it will
|
|---|
| 545 | repeatedly read a 4-byte chunk-length and then the remainder of the chunk
|
|---|
| 546 | until it either reaches EOF (indicated by the mng_readdata() callback) or
|
|---|
| 547 | implicitly decides EOF as it processed the logically last chunk of the
|
|---|
| 548 | image.
|
|---|
| 549 |
|
|---|
| 550 | Applications that require strict conformity and do not allow superfluous
|
|---|
| 551 | data after the ending chunk, will need to perform this check in their
|
|---|
| 552 | mng_closestream() callback.
|
|---|
| 553 |
|
|---|
| 554 | Each chunk is then checked on CRC, after which it is handed over to the
|
|---|
| 555 | appropriate chunk processing routine. These routines will disect the
|
|---|
| 556 | chunk, check the validity of its contents, check its position with respect
|
|---|
| 557 | to other chunks, etc, etc.
|
|---|
| 558 |
|
|---|
| 559 | If everything checks out, the chunk is further processed as follows:
|
|---|
| 560 |
|
|---|
| 561 | If display support has been selected during compilation, certain pre-display
|
|---|
| 562 | initialization will take place.
|
|---|
| 563 |
|
|---|
| 564 | If chunk-storage support has been selected during compilation, the chunks
|
|---|
| 565 | data may be stored in a special internal structure and held for future
|
|---|
| 566 | reference.
|
|---|
| 567 |
|
|---|
| 568 |
|
|---|
| 569 | > Storing and accessing chunks
|
|---|
| 570 |
|
|---|
| 571 | One of the compilation options activates support for chunk storage.
|
|---|
| 572 | This option may be useful if you want to examine an image. The directive
|
|---|
| 573 | is MNG_STORE_CHUNKS. You must also turn on the MNG_ACCESS_CHUNKS
|
|---|
| 574 | directive.
|
|---|
| 575 |
|
|---|
| 576 | The actual storage facility can be turned on or off with the
|
|---|
| 577 | mng_set_storechunks() function. If set to MNG_TRUE, chunks will be
|
|---|
| 578 | stored as they are read.
|
|---|
| 579 |
|
|---|
| 580 | At any point you can then call the mng_iterate_chunks() function
|
|---|
| 581 | to iterate through the current list of chunks. This function requires
|
|---|
| 582 | a callback which is called for each chunk and receives a specific
|
|---|
| 583 | chunk-handle. This chunk-handle can be used to call the appropriate
|
|---|
| 584 | mng_getchunk_xxxx() function, to access the chunks properties.
|
|---|
| 585 |
|
|---|
| 586 | A typical implementation may look like this:
|
|---|
| 587 |
|
|---|
| 588 | mng_bool my_iteratechunk (mng_handle hHandle,
|
|---|
| 589 | mng_handle hChunk,
|
|---|
| 590 | mng_chunkid iChunkid,
|
|---|
| 591 | mng_uint32 iChunkseq) {
|
|---|
| 592 | switch (iChunkid) {
|
|---|
| 593 | case MNG_UINT_MHDR : { /* process MHDR */;
|
|---|
| 594 | break; }
|
|---|
| 595 | case MNG_UINT_FRAM : { /* process FRAM */;
|
|---|
| 596 | break; }
|
|---|
| 597 |
|
|---|
| 598 | ...etc...
|
|---|
| 599 |
|
|---|
| 600 | case MNG_UINT_HUH : { /* unknown chunk */;
|
|---|
| 601 | break; }
|
|---|
| 602 | default : { /* duh; forgot one */; }
|
|---|
| 603 | }
|
|---|
| 604 |
|
|---|
| 605 | return MNG_TRUE; /* keep'm coming */
|
|---|
| 606 | }
|
|---|
| 607 |
|
|---|
| 608 | To get to the actual chunk fields of lets say a SHOW chunk you would do:
|
|---|
| 609 |
|
|---|
| 610 | mng_bool isempty;
|
|---|
| 611 | mng_uint16 firstid, lastid;
|
|---|
| 612 | mng_uint8 showmode;
|
|---|
| 613 |
|
|---|
| 614 | myretcode mng_getchunk_show (hHandle, hChunk,
|
|---|
| 615 | isempty, firstid,
|
|---|
| 616 | lastid, showmode);
|
|---|
| 617 | if (myretcode != MNG_NOERROR)
|
|---|
| 618 | /* process error */;
|
|---|
| 619 |
|
|---|
| 620 |
|
|---|
| 621 | V. Displaying
|
|---|
| 622 |
|
|---|
| 623 |
|
|---|
| 624 | > Setup
|
|---|
| 625 |
|
|---|
| 626 | Assuming you have initialized the library and are the owner of
|
|---|
| 627 | a mng_handle. The following callbacks are essential:
|
|---|
| 628 |
|
|---|
| 629 | mng_getcanvasline, mng_refresh
|
|---|
| 630 | mng_gettickcount, mng_settimer
|
|---|
| 631 |
|
|---|
| 632 | If you wish to use an application supplied background you must supply:
|
|---|
| 633 |
|
|---|
| 634 | mng_getbkgdline
|
|---|
| 635 |
|
|---|
| 636 | If you wish to use the MNG_CANVAS_RGB8_A8 canvas style you must supply:
|
|---|
| 637 |
|
|---|
| 638 | mng_getalphaline
|
|---|
| 639 |
|
|---|
| 640 | You may optionally define:
|
|---|
| 641 |
|
|---|
| 642 | mng_errorproc, mng_traceproc
|
|---|
| 643 | mng_processheader, mng_processtext
|
|---|
| 644 | mng_processsave, mng_processseek
|
|---|
| 645 |
|
|---|
| 646 | Note that the mng_processheader() callback is optional but will
|
|---|
| 647 | be quite significant for proper operation!
|
|---|
| 648 |
|
|---|
| 649 | Displaying an image will fail if you are creating a file or already
|
|---|
| 650 | displaying one. Yes, you can't display it twice!
|
|---|
| 651 |
|
|---|
| 652 |
|
|---|
| 653 | > A word on canvas styles
|
|---|
| 654 |
|
|---|
| 655 | The canvas style describes how your drawing canvas is made up.
|
|---|
| 656 | You must set this before the library actually starts drawing, so
|
|---|
| 657 | the mng_processheader() callback is a pretty good place for it.
|
|---|
| 658 |
|
|---|
| 659 | Currently only 8-bit RGB canvas styles are supported, either with
|
|---|
| 660 | or without an alpha channel.
|
|---|
| 661 |
|
|---|
| 662 | If you like to do alpha composition yourself you can select one of
|
|---|
| 663 | the canvas styles that include an alpha channel. You can even have
|
|---|
| 664 | a separate alpha canvas by selecting the MNG_CANVAS_RGB8_A8 style.
|
|---|
| 665 |
|
|---|
| 666 | All styles require a compact model. Eg. MNG_CANVAS_BGR8 requires
|
|---|
| 667 | your canvas lines in bgrbgrbgr... storage, where each letter
|
|---|
| 668 | represents an 8-bit value of the corresponding color, and each
|
|---|
| 669 | threesome makes up the values of one(1) pixel.
|
|---|
| 670 |
|
|---|
| 671 | The library processes a line at a time, so the canvas lines do not
|
|---|
| 672 | actually need to be consecutive in memory.
|
|---|
| 673 |
|
|---|
| 674 |
|
|---|
| 675 | > Alpha composition and application backgrounds
|
|---|
| 676 |
|
|---|
| 677 | All Network Graphics can be partially transparent. This requires
|
|---|
| 678 | special processing if you need to display an image against some
|
|---|
| 679 | background. Note that the MNG header (MHDR chunk) contains a
|
|---|
| 680 | simplicity field indicating whether transparency information in
|
|---|
| 681 | the file is critical or not. This only applies to embedded images,
|
|---|
| 682 | which means the full image-frame of the MNG may still contain fully
|
|---|
| 683 | transparent pixels!
|
|---|
| 684 |
|
|---|
| 685 | Depending on your needs you can supply a single background color,
|
|---|
| 686 | a background canvas or tell the library to return the alpha-channel
|
|---|
| 687 | and do alpha composition yourself.
|
|---|
| 688 |
|
|---|
| 689 | This is different from the BACK chunk in a MNG, or the bKGD chunk
|
|---|
| 690 | in an (embedded) PNG or JNG. The BACK chunk indicates an optional or
|
|---|
| 691 | mandatory background color and/or image. The bKGD chunk only indicates
|
|---|
| 692 | an optional background color. These chunks indicate the Authors
|
|---|
| 693 | preferences. They may be absent in which case you need to supply
|
|---|
| 694 | some sort of background yourself.
|
|---|
| 695 |
|
|---|
| 696 | > Composing against a background color
|
|---|
| 697 |
|
|---|
| 698 | This is the easiest method. Call the mng_set_bgcolor() function to
|
|---|
| 699 | set the values of the red, green and blue component of your preferred
|
|---|
| 700 | background color.
|
|---|
| 701 |
|
|---|
| 702 | Use one of the canvas styles that do not have an alpha-channel, and
|
|---|
| 703 | which matches your output requirements.
|
|---|
| 704 |
|
|---|
| 705 | > Composing against a background canvas
|
|---|
| 706 |
|
|---|
| 707 | This is somewhat more complicated. You will need to set the
|
|---|
| 708 | mng_getbkgdline() callback. This will be called whenever the library
|
|---|
| 709 | needs to compose a partially transparent line.
|
|---|
| 710 |
|
|---|
| 711 | This canvas must hold the background against which the image should
|
|---|
| 712 | be composed. Its size must match exactly with the image dimensions
|
|---|
| 713 | and thus the drawing canvas!
|
|---|
| 714 |
|
|---|
| 715 | Use one of the canvas styles that do not have an alpha-channel, and
|
|---|
| 716 | which matches your output requirements. The canvas style of the
|
|---|
| 717 | background canvas may even differ from the drawing canvas. The library's
|
|---|
| 718 | composing will still function properly.
|
|---|
| 719 |
|
|---|
| 720 | > Composing within the application
|
|---|
| 721 |
|
|---|
| 722 | If you have the option in your application to draw a (partially)
|
|---|
| 723 | transparent canvas to the output device, this option is preferred.
|
|---|
| 724 |
|
|---|
| 725 | Select one of the canvas styles that do have an alpha-channel.
|
|---|
| 726 | The library will now supply the appropriate alpha information,
|
|---|
| 727 | allowing the application to compose the image as it sees fit.
|
|---|
| 728 |
|
|---|
| 729 |
|
|---|
| 730 | > Color information and CMS
|
|---|
| 731 |
|
|---|
| 732 | Network Graphics may, and usually will, contain color-correction
|
|---|
| 733 | information. This information is intended to compensate for the
|
|---|
| 734 | difference in recording and display devices used.
|
|---|
| 735 |
|
|---|
| 736 | This document does not address the specifics of color-management.
|
|---|
| 737 | See the PNG specification for a more detailed description.
|
|---|
| 738 |
|
|---|
| 739 | > Using little cms by Marti Maria Saguer
|
|---|
| 740 |
|
|---|
| 741 | This is the easiest method, providing you can compile the lcms package.
|
|---|
| 742 | Select the MNG_FULL_CMS directive during compilation, and sit back and
|
|---|
| 743 | relax. The library will take care of all color-correction for you.
|
|---|
| 744 |
|
|---|
| 745 | > Using an OS- or application-supplied CMS
|
|---|
| 746 |
|
|---|
| 747 | If you are so lucky to have access to CMS functionality from within
|
|---|
| 748 | your application, you may instruct the library to leave color-correction
|
|---|
| 749 | to you.
|
|---|
| 750 |
|
|---|
| 751 | Select the MNG_APP_CMS directive during compilation of the library.
|
|---|
| 752 | You MUST also set the following callbacks:
|
|---|
| 753 |
|
|---|
| 754 | mng_processgamma, mng_processchroma,
|
|---|
| 755 | mng_processsrgb, mng_processiccp and
|
|---|
| 756 | mng_processarow
|
|---|
| 757 |
|
|---|
| 758 | The last callback is called when the library needs you to correct
|
|---|
| 759 | an arbitrary line of pixels. The other callbacks are called when
|
|---|
| 760 | the corresponding color-information is encountered in the file.
|
|---|
| 761 | You must store this information somewhere for use in the
|
|---|
| 762 | mng_processarow() callback.
|
|---|
| 763 |
|
|---|
| 764 | > Using gamma-only correction
|
|---|
| 765 |
|
|---|
| 766 | This isn't a preferred method, but it's better than no correction
|
|---|
| 767 | at all. Gamma-only correction will at least compensate for
|
|---|
| 768 | gamma-differences between the original recorder and your output device.
|
|---|
| 769 |
|
|---|
| 770 | Select the MNG_GAMMA_ONLY directive during compilation
|
|---|
| 771 | of the library. Your compiler MUST support fp operations.
|
|---|
| 772 |
|
|---|
| 773 | > No color correction
|
|---|
| 774 |
|
|---|
| 775 | Ouch. This is really bad. This is the least preferred method,
|
|---|
| 776 | but may be necessary if your system cannot use lcms, doesn't
|
|---|
| 777 | have its own CMS, and does not allow fp operations, ruling out
|
|---|
| 778 | the gamma-only option.
|
|---|
| 779 |
|
|---|
| 780 | Select the MNG_NO_CMS directive during compilation.
|
|---|
| 781 | Images will definitely not be displayed as seen by the Author!!!
|
|---|
| 782 |
|
|---|
| 783 |
|
|---|
| 784 | > Animations and timing
|
|---|
| 785 |
|
|---|
| 786 | Animations require some form of timing support. The library relies
|
|---|
| 787 | on two callbacks for this purpose. The mng_gettickcount() and
|
|---|
| 788 | mng_settimer() callbacks. mng_gettickcount() is used to determine
|
|---|
| 789 | the passing of time in milliseconds since the beginning of the
|
|---|
| 790 | animation. This is also used to compensate during suspension-mode
|
|---|
| 791 | if you are using the mng_readdisplay() function to read & display
|
|---|
| 792 | the file simultaneously.
|
|---|
| 793 |
|
|---|
| 794 | The callback may return an arbitrary number of milliseconds, but
|
|---|
| 795 | this number must increase proportionaly between calls. Most modern
|
|---|
| 796 | systems will have some tickcount() function which derives its
|
|---|
| 797 | input from an internal clock. The value returned from this function
|
|---|
| 798 | is more than adequate for libmng.
|
|---|
| 799 |
|
|---|
| 800 | The mng_settimer() callback is called when the library determines
|
|---|
| 801 | a little "pause" is required before rendering another frame of the
|
|---|
| 802 | animation. The pause interval is also expressed in milliseconds.
|
|---|
| 803 | Your application should store this value and return immediately.
|
|---|
| 804 | The library will then make appropriate arrangements to store its
|
|---|
| 805 | internal state and returns to your application with the
|
|---|
| 806 | MNG_NEEDTIMERWAIT code.
|
|---|
| 807 |
|
|---|
| 808 | At that point you should suspend processing and wait the given
|
|---|
| 809 | interval. Please use your OS features for this. Do not engage some
|
|---|
| 810 | sort of loop. That is real bad programming practice. Most modern
|
|---|
| 811 | systems will have some timing functions. A simple wait() function
|
|---|
| 812 | may suffice, but this may prevent your applications main-task from
|
|---|
| 813 | running, and possibly prevent the actual update of your output device.
|
|---|
| 814 |
|
|---|
| 815 |
|
|---|
| 816 | > The mng_refresh() callback
|
|---|
| 817 |
|
|---|
| 818 | The mng_refresh() callback is called whenever the library has
|
|---|
| 819 | "finished" drawing a new frame onto your canvas, and just before it
|
|---|
| 820 | will call the mng_settimer() callback.
|
|---|
| 821 |
|
|---|
| 822 | This allows you to perform some actions necessary to "refresh" the
|
|---|
| 823 | canvas onto your output device. Please do NOT suspend processing
|
|---|
| 824 | inside this callback. This must be handled after the mng_settimer()
|
|---|
| 825 | callback!
|
|---|
| 826 |
|
|---|
| 827 |
|
|---|
| 828 | > Displaying while reading
|
|---|
| 829 |
|
|---|
| 830 | This method is preferred if you are reading from a slow input device
|
|---|
| 831 | (such as a dialup-line) and you wish to start displaying something
|
|---|
| 832 | as quickly as possible. This functionality is provided mainly for
|
|---|
| 833 | browser-type applications but may be appropriate for other
|
|---|
| 834 | applications as well.
|
|---|
| 835 |
|
|---|
| 836 | The method is usually used in unison with the suspension-mode of
|
|---|
| 837 | the read module. A typical implementation would look like this:
|
|---|
| 838 |
|
|---|
| 839 | /* initiale library and set required callbacks */
|
|---|
| 840 |
|
|---|
| 841 | /* activate suspension-mode */
|
|---|
| 842 | myretcode = mng_set_suspensionmode (myhandle,
|
|---|
| 843 | MNG_TRUE);
|
|---|
| 844 | if (myretcode != MNG_NOERROR)
|
|---|
| 845 | /* process error */;
|
|---|
| 846 |
|
|---|
| 847 | myretcode = mng_readdisplay (myhandle);
|
|---|
| 848 |
|
|---|
| 849 | while ((myretcode == MNG_NEEDMOREDATA) ||
|
|---|
| 850 | (myretcode == MNG_NEEDTIMERWAIT)) {
|
|---|
| 851 | if (myretcode == MNG_NEEDMOREDATA)
|
|---|
| 852 | /* wait for more input-data */;
|
|---|
| 853 | else
|
|---|
| 854 | /* wait for timer interval */;
|
|---|
| 855 |
|
|---|
| 856 | myretcode = mng_display_resume (myhandle);
|
|---|
| 857 | }
|
|---|
| 858 |
|
|---|
| 859 | if (myretcode != MNG_NOERROR)
|
|---|
| 860 | /* process error */;
|
|---|
| 861 |
|
|---|
| 862 | More advanced programming methods may require a different approach,
|
|---|
| 863 | but the final result should function as in the code above.
|
|---|
| 864 |
|
|---|
| 865 |
|
|---|
| 866 | > Displaying after reading
|
|---|
| 867 |
|
|---|
| 868 | This method is used to display a file that was previously read.
|
|---|
| 869 | It is primarily meant for viewers with direct file access, such as
|
|---|
| 870 | 1a local harddisk.
|
|---|
| 871 |
|
|---|
| 872 | Once you have successfully read the file, all you need to do is:
|
|---|
| 873 |
|
|---|
| 874 | myretcode = mng_display (myhandle);
|
|---|
| 875 |
|
|---|
| 876 | while (myretcode == MNG_NEEDTIMERWAIT) {
|
|---|
| 877 | /* wait for timer interval */;
|
|---|
| 878 | myretcode = mng_display_resume (myhandle);
|
|---|
| 879 | }
|
|---|
| 880 |
|
|---|
| 881 | if (myretcode != MNG_NOERROR)
|
|---|
| 882 | /* process error */;
|
|---|
| 883 |
|
|---|
| 884 | Again, more advanced programming methods may require a different
|
|---|
| 885 | approach, but the final result should function as in the code above.
|
|---|
| 886 |
|
|---|
| 887 |
|
|---|
| 888 | > Display manipulation
|
|---|
| 889 |
|
|---|
| 890 | Several HLAPI functions are provided to allow a user to manipulate
|
|---|
| 891 | the normal flow of an animation.
|
|---|
| 892 |
|
|---|
| 893 | - mng_display_freeze (mng_handle hHandle)
|
|---|
| 894 |
|
|---|
| 895 | This will "freeze" the animation in place.
|
|---|
| 896 |
|
|---|
| 897 | - mng_display_resume (mng_handle hHandle)
|
|---|
| 898 |
|
|---|
| 899 | This function can be used to resume a frozen animation, or to force
|
|---|
| 900 | the library to advance the animation to the next frame.
|
|---|
| 901 |
|
|---|
| 902 | - mng_display_reset (mng_handle hHandle)
|
|---|
| 903 |
|
|---|
| 904 | This function will "reset" the animation into its pristine state.
|
|---|
| 905 | Calling mng_display() afterwards will re-display the animation
|
|---|
| 906 | from the first frame.
|
|---|
| 907 |
|
|---|
| 908 | - mng_display_golayer (mng_handle hHandle,
|
|---|
| 909 | mng_uint32 iLayer)
|
|---|
| 910 | - mng_display_goframe (mng_handle hHandle,
|
|---|
| 911 | mng_uint32 iFrame)
|
|---|
| 912 | - mng_display_goplaytime (mng_handle hHandle,
|
|---|
| 913 | mng_uint32 iPlaytime)
|
|---|
| 914 |
|
|---|
| 915 | These three functions can be used to "jump" to a specific layer, frame
|
|---|
| 916 | or timeslot in the animation. You must "freeze" the animation before
|
|---|
| 917 | using any of these functions.
|
|---|
| 918 |
|
|---|
| 919 | All above functions may only be called during a timer interval!
|
|---|
| 920 | It is the applications responsibility to cleanup any resources with
|
|---|
| 921 | respect to the timer wait.
|
|---|
| 922 |
|
|---|
| 923 |
|
|---|
| 924 | VI. Writing
|
|---|
| 925 |
|
|---|
| 926 | The main focus of the library lies in its displaying capabilites.
|
|---|
| 927 | But it does offer writing support as well.
|
|---|
| 928 | You can create and write a file, or you can write a file you
|
|---|
| 929 | have previously read, providing the storage of chunks was enabled
|
|---|
| 930 | and active.
|
|---|
| 931 |
|
|---|
| 932 | For this to work you must have compiled the library with the
|
|---|
| 933 | MNG_WRITE_SUPPO1RT and MNG_ACCESS_CHUNKS directives. The standard DLL and
|
|---|
| 934 | Shared Library have this on by default!
|
|---|
| 935 |
|
|---|
| 936 |
|
|---|
| 937 | > Setup
|
|---|
| 938 |
|
|---|
| 939 | As always you must have initialized the library and be the owner of
|
|---|
| 940 | a mng_handle. The following callbacks are essential:
|
|---|
| 941 |
|
|---|
| 942 | mng_openstream, mng_writedata, mng_closestream
|
|---|
| 943 |
|
|---|
| 944 | You can optionally define:
|
|---|
| 945 |
|
|---|
| 946 | mng_errorproc, mng_traceproc
|
|---|
| 947 |
|
|---|
| 948 | The creation and writing functions will fail if you are in the middle
|
|---|
| 949 | of reading, creating or writing a file.
|
|---|
| 950 |
|
|---|
| 951 |
|
|---|
| 952 | > Creating a new file
|
|---|
| 953 |
|
|---|
| 954 | To start a new file the library must be in its initial state.
|
|---|
| 955 | First you need to tell the library your intentions:
|
|---|
| 956 |
|
|---|
| 957 | myretcode = mng_create (myhandle);
|
|---|
| 958 | if (myretcode != MNG_NOERROR)
|
|---|
| 959 | /* process error */;
|
|---|
| 960 |
|
|---|
| 961 | After that you start adding the appropriate chunks:
|
|---|
| 962 |
|
|---|
| 963 | myretcode = mng_putchunk_mhdr (myhandle, ...);
|
|---|
| 964 | if (myretcode != MNG_NOERROR)
|
|---|
| 965 | /* process error */;
|
|---|
| 966 |
|
|---|
| 967 | And so on, and so forth. Note that the library will automatically signal
|
|---|
| 968 | the logical end of the file by the ending chunk. Also the first chunk
|
|---|
| 969 | will indicate the library the filetype (eg. PNG, JNG or MNG) and force
|
|---|
| 970 | the proper signature when writing the file.
|
|---|
| 971 |
|
|---|
| 972 | The code above can be simplified, as you can always get the last errorcode
|
|---|
| 973 | by using the mng_getlasterror() function:
|
|---|
| 974 |
|
|---|
| 975 | if ( (mng_putchunk_xxxx (myhandle, ...)) or
|
|---|
| 976 | (mng_putchunk_xxxx (myhandle, ...)) or
|
|---|
| 977 | ...etc... )
|
|---|
| 978 | /* process error */;
|
|---|
| 979 |
|
|---|
| 980 | Please note that you must have a pretty good understanding of the chunk
|
|---|
| 981 | specification. Unlike the read functions, there are virtually no checks,
|
|---|
| 982 | so it is quite possible to write completely wrong files.
|
|---|
| 983 | It is a good practice to read back your file into the library to verify
|
|---|
| 984 | its integrity.
|
|---|
| 985 |
|
|---|
| 986 | Once you've got all the chunks added, all you do is:
|
|---|
| 987 |
|
|---|
| 988 | myretcode mng_write (myhandle);
|
|---|
| 989 | if (myretcode != MNG_NOERROR)
|
|---|
| 990 | /* process error */;
|
|---|
| 991 |
|
|---|
| 992 | And presto. You're done. The real work is of course carried out in
|
|---|
| 993 | your callbacks. Note that this is a single operation as opposed to
|
|---|
| 994 | the read & display functions that may return with MNG_NEEDMOREDATA
|
|---|
| 995 | and/or MNG_NEEDTIMERWAIT. The write function just does the job, and
|
|---|
| 996 | only returns after it's finished or if it encounters some
|
|---|
| 997 | unrecoverable error.
|
|---|
| 998 |
|
|---|
| 999 |
|
|---|
| 1000 | > Writing a previously read file
|
|---|
| 1001 |
|
|---|
| 1002 | If you have already successfully read a file, you can use the library to
|
|---|
| 1003 | write it out as a copy or something. You MUST have compiled the library
|
|---|
| 1004 | with the MNG_STORE_CHUNKS directive, and you must have done
|
|---|
| 1005 | mng_set_storechunks (myhandle, MNG_TRUE).
|
|---|
| 1006 |
|
|---|
| 1007 | This doesn't require the MNG_ACCESS_CHUNKS directive, unless you want
|
|---|
| 1008 | to fiddle with the chunks as well.
|
|---|
| 1009 |
|
|---|
| 1010 | Again all you need to do is:
|
|---|
| 1011 |
|
|---|
| 1012 | myretcode mng_write (myhandle);
|
|---|
| 1013 | if (myretcode != MNG_NOERROR)
|
|---|
| 1014 | /* process error */;
|
|---|
| 1015 |
|
|---|
| 1016 |
|
|---|
| 1017 | VII. Modifying/Customizing libmng:
|
|---|
| 1018 |
|
|---|
| 1019 | to do
|
|---|
| 1020 |
|
|---|
| 1021 | > Compilation directives
|
|---|
| 1022 |
|
|---|
| 1023 | to do
|
|---|
| 1024 |
|
|---|
| 1025 | > Platform dependant modification
|
|---|
| 1026 |
|
|---|
| 1027 | to do
|
|---|
| 1028 |
|
|---|
| 1029 |
|
|---|
| 1030 | References :
|
|---|
| 1031 |
|
|---|
| 1032 | libmng :
|
|---|
| 1033 | http://www.libmng.com/
|
|---|
| 1034 |
|
|---|
| 1035 | zlib :
|
|---|
| 1036 | http://www.info-zip.org/pub/infozip/zlib/
|
|---|
| 1037 |
|
|---|
| 1038 | IJG JPEG library :
|
|---|
| 1039 | http://www.ijg.org/
|
|---|
| 1040 |
|
|---|
| 1041 | lcms (little CMS) by Marti Maria Saguer :
|
|---|
| 1042 | http://www.littlecms.com/
|
|---|
| 1043 |
|
|---|
| 1044 | MNG specification:
|
|---|
| 1045 | http://www.libpng.org/pub/mng
|
|---|
| 1046 |
|
|---|
| 1047 |
|
|---|
| 1048 | In the case of any inconsistency between the MNG specification
|
|---|
| 1049 | and this library, the specification takes precedence.
|
|---|
| 1050 |
|
|---|
| 1051 |
|
|---|
| 1052 | The contributing authors would like to thank all those who helped
|
|---|
| 1053 | with testing, bug fixes, and patience. This wouldn't have been
|
|---|
| 1054 | possible without all of you!!!
|
|---|
| 1055 |
|
|---|
| 1056 |
|
|---|
| 1057 | COPYRIGHT NOTICE:
|
|---|
| 1058 |
|
|---|
| 1059 | Copyright (c) 2000,2001 Gerard Juyn
|
|---|
| 1060 |
|
|---|
| 1061 | For the purposes of this copyright and license, "Contributing Authors"
|
|---|
| 1062 | is defined as the following set of individuals:
|
|---|
| 1063 |
|
|---|
| 1064 | Gerard Juyn
|
|---|
| 1065 |
|
|---|
| 1066 | The MNG Library is supplied "AS IS". The Contributing Authors
|
|---|
| 1067 | disclaim all warranties, expressed or implied, including, without
|
|---|
| 1068 | limitation, the warranties of merchantability and of fitness for any
|
|---|
| 1069 | purpose. The Contributing Authors assume no liability for direct,
|
|---|
| 1070 | indirect, incidental, special, exemplary, or consequential damages,
|
|---|
| 1071 | which may result from the use of the MNG Library, even if advised of
|
|---|
| 1072 | the possibility of such damage.
|
|---|
| 1073 |
|
|---|
| 1074 | Permission is hereby granted to use, copy, modify, and distribute this
|
|---|
| 1075 | source code, or portions hereof, for any purpose, without fee, subject
|
|---|
| 1076 | to the following restrictions:
|
|---|
| 1077 |
|
|---|
| 1078 | 1. The origin of this source code must not be misrepresented;
|
|---|
| 1079 | you must not claim that you wrote the original software.
|
|---|
| 1080 |
|
|---|
| 1081 | 2. Altered versions must be plainly marked as such and must not be
|
|---|
| 1082 | misrepresented as being the original source.
|
|---|
| 1083 |
|
|---|
| 1084 | 3. This Copyright notice may not be removed or altered from any source
|
|---|
| 1085 | or altered source distribution.
|
|---|
| 1086 |
|
|---|
| 1087 | The Contributing Authors specifically permit, without fee, and
|
|---|
| 1088 | encourage the use of this source code as a component to supporting
|
|---|
| 1089 | the MNG and JNG file format in commercial products. If you use this
|
|---|
| 1090 | source code in a product, acknowledgment would be highly appreciated.
|
|---|
| 1091 |
|
|---|
| 1092 |
|
|---|
| 1093 | Remarks :
|
|---|
| 1094 |
|
|---|
| 1095 | Parts of this software have been adapted from the libpng library.
|
|---|
| 1096 | Although this library supports all features from the PNG specification
|
|---|
| 1097 | (as MNG descends from it) it does not require the libpng library.
|
|---|
| 1098 | It does require the zlib library and optionally the IJG JPEG library,
|
|---|
| 1099 | and/or the "little-cms" library by Marti Maria Saguer (depending on the
|
|---|
| 1100 | inclusion of support for JNG and Full-Color-Management respectively.
|
|---|
| 1101 |
|
|---|
| 1102 | This library's function is primarily to read and display MNG
|
|---|
| 1103 | animations. It is not meant as a full-featured image-editing
|
|---|
| 1104 | component! It does however offer creation and editing functionality
|
|---|
| 1105 | at the chunk level. (future modifications may include some more
|
|---|
| 1106 | support for creation and or editing)
|
|---|
| 1107 |
|
|---|