1 /* ************************************************************************** */
2 /* * For conditions of distribution and use, * */
3 /* * see copyright notice in libmng.h * */
4 /* ************************************************************************** */
5 /* * * */
6 /* * project : libmng * */
7 /* * file : libmng_zlib.c copyright (c) 2000-2004 G.Juyn * */
8 /* * version : 1.0.9 * */
9 /* * * */
10 /* * purpose : ZLIB library interface (implementation) * */
11 /* * * */
12 /* * author : G.Juyn * */
13 /* * * */
14 /* * comment : implementation of the ZLIB library interface * */
15 /* * * */
16 /* * changes : 0.5.1 - 05/08/2000 - G.Juyn * */
17 /* * - changed strict-ANSI stuff * */
18 /* * 0.5.1 - 05/11/2000 - G.Juyn * */
19 /* * - filled the deflatedata routine * */
20 /* * 0.5.1 - 05/12/2000 - G.Juyn * */
21 /* * - changed trace to macro for callback error-reporting * */
22 /* * * */
23 /* * 0.5.2 - 05/20/2000 - G.Juyn * */
24 /* * - fixed for JNG alpha handling * */
25 /* * 0.5.2 - 05/24/2000 - G.Juyn * */
26 /* * - moved init of default zlib parms from here to * */
27 /* * "mng_hlapi.c" * */
28 /* * * */
29 /* * 0.5.3 - 06/16/2000 - G.Juyn * */
30 /* * - changed progressive-display processing * */
31 /* * * */
32 /* * 0.9.2 - 08/05/2000 - G.Juyn * */
33 /* * - changed file-prefixes * */
34 /* * * */
35 /* * 0.9.3 - 08/08/2000 - G.Juyn * */
36 /* * - fixed compiler-warnings from Mozilla * */
37 /* * 0.9.3 - 09/07/2000 - G.Juyn * */
38 /* * - added support for new filter_types * */
39 /* * * */
40 /* * 1.0.5 - 08/07/2002 - G.Juyn * */
41 /* * - added test-option for PNG filter method 193 (=no filter) * */
42 /* * 1.0.5 - 08/19/2002 - G.Juyn * */
43 /* * - B597134 - libmng pollutes the linker namespace * */
44 /* * 1.0.5 - 09/19/2002 - G.Juyn * */
45 /* * - added warning for too much IDAT data * */
46 /* * * */
47 /* * 1.0.6 - 07/07/2003 - G.R-P * */
48 /* * - added MNG_NO_16BIT_SUPPORT support * */
49 /* * * */
50 /* * 1.0.9 - 10/09/2004 - G.R-P * */
51 /* * - added MNG_NO_1_2_4BIT_SUPPORT support * */
52 /* * * */
53 /* ************************************************************************** */
54
55 #include "libmng.h"
56 #include "libmng_data.h"
57 #include "libmng_error.h"
58 #include "libmng_trace.h"
59 #ifdef __BORLANDC__
60 #pragma hdrstop
61 #endif
62 #include "libmng_memory.h"
63 #include "libmng_pixels.h"
64 #include "libmng_filter.h"
65 #include "libmng_zlib.h"
66
67 #if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
68 #pragma option -A /* force ANSI-C */
69 #endif
70
71 /* ************************************************************************** */
72
73 #ifdef MNG_INCLUDE_ZLIB
74
75 /* ************************************************************************** */
76
mngzlib_alloc(voidpf pData,uInt iCount,uInt iSize)77 voidpf mngzlib_alloc (voidpf pData,
78 uInt iCount,
79 uInt iSize)
80 {
81 voidpf pPtr; /* temporary space */
82
83 #ifdef MNG_INTERNAL_MEMMNGMT
84 pPtr = calloc (iCount, iSize); /* local allocation */
85 #else
86 if (((mng_datap)pData)->fMemalloc) /* callback function set ? */
87 pPtr = ((mng_datap)pData)->fMemalloc (iCount * iSize);
88 else
89 pPtr = Z_NULL; /* can't allocate! */
90 #endif
91
92 return pPtr; /* return the result */
93 }
94
95 /* ************************************************************************** */
96
mngzlib_free(voidpf pData,voidpf pAddress)97 void mngzlib_free (voidpf pData,
98 voidpf pAddress)
99 {
100 #ifdef MNG_INTERNAL_MEMMNGMT
101 free (pAddress); /* free locally */
102 #else
103 if (((mng_datap)pData)->fMemfree) /* callback set? */
104 ((mng_datap)pData)->fMemfree (pAddress, 1);
105 #endif
106 }
107
108 /* ************************************************************************** */
109
mngzlib_initialize(mng_datap pData)110 mng_retcode mngzlib_initialize (mng_datap pData)
111 {
112 #ifdef MNG_SUPPORT_TRACE
113 MNG_TRACE (pData, MNG_FN_ZLIB_INITIALIZE, MNG_LC_START);
114 #endif
115
116 #ifdef MNG_INTERNAL_MEMMNGMT
117 pData->sZlib.zalloc = Z_NULL; /* let zlib figure out memory management */
118 pData->sZlib.zfree = Z_NULL;
119 pData->sZlib.opaque = Z_NULL;
120 #else /* use user-provided callbacks */
121 pData->sZlib.zalloc = mngzlib_alloc;
122 pData->sZlib.zfree = mngzlib_free;
123 pData->sZlib.opaque = (voidpf)pData;
124 #endif
125
126 pData->bInflating = MNG_FALSE; /* not performing any action yet */
127 pData->bDeflating = MNG_FALSE;
128
129 #ifdef MNG_SUPPORT_TRACE
130 MNG_TRACE (pData, MNG_FN_ZLIB_INITIALIZE, MNG_LC_END);
131 #endif
132
133 return MNG_NOERROR; /* done */
134 }
135
136 /* ************************************************************************** */
137
mngzlib_cleanup(mng_datap pData)138 mng_retcode mngzlib_cleanup (mng_datap pData)
139 {
140 #ifdef MNG_SUPPORT_TRACE
141 MNG_TRACE (pData, MNG_FN_ZLIB_CLEANUP, MNG_LC_START);
142 #endif
143
144 if (pData->bInflating) /* force zlib cleanup */
145 mngzlib_inflatefree (pData);
146 if (pData->bDeflating)
147 mngzlib_deflatefree (pData);
148
149 #ifdef MNG_SUPPORT_TRACE
150 MNG_TRACE (pData, MNG_FN_ZLIB_CLEANUP, MNG_LC_END);
151 #endif
152
153 return MNG_NOERROR; /* done */
154 }
155
156 /* ************************************************************************** */
157
mngzlib_inflateinit(mng_datap pData)158 mng_retcode mngzlib_inflateinit (mng_datap pData)
159 {
160 int iZrslt;
161
162 #ifdef MNG_SUPPORT_TRACE
163 MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEINIT, MNG_LC_START);
164 #endif
165 /* initialize zlib structures and such */
166 iZrslt = inflateInit (&pData->sZlib);
167
168 if (iZrslt != Z_OK) /* on error bail out */
169 MNG_ERRORZ (pData, (mng_uint32)iZrslt);
170
171 pData->bInflating = MNG_TRUE; /* really inflating something now */
172 pData->sZlib.next_out = 0; /* force JIT initialization */
173
174 #ifdef MNG_SUPPORT_TRACE
175 MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEINIT, MNG_LC_END);
176 #endif
177
178 return MNG_NOERROR; /* done */
179 }
180
181 /* ************************************************************************** */
182
183 #ifdef MNG_SUPPORT_DISPLAY
mngzlib_inflaterows(mng_datap pData,mng_uint32 iInlen,mng_uint8p pIndata)184 mng_retcode mngzlib_inflaterows (mng_datap pData,
185 mng_uint32 iInlen,
186 mng_uint8p pIndata)
187 {
188 int iZrslt;
189 mng_retcode iRslt;
190 mng_ptr pSwap;
191
192 #ifdef MNG_SUPPORT_TRACE
193 MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEROWS, MNG_LC_START);
194 #endif
195
196 pData->sZlib.next_in = pIndata; /* let zlib know where to get stuff */
197 pData->sZlib.avail_in = (uInt)iInlen;
198
199 if (pData->sZlib.next_out == 0) /* initialize output variables ? */
200 { /* let zlib know where to store stuff */
201 pData->sZlib.next_out = pData->pWorkrow;
202 pData->sZlib.avail_out = (uInt)(pData->iRowsize + pData->iPixelofs);
203 #ifdef MNG_NO_1_2_4BIT_SUPPORT
204 if (pData->iPNGdepth < 8)
205 pData->sZlib.avail_out = (uInt)((pData->iPNGdepth*pData->iRowsize + 7)/8
206 + pData->iPixelofs);
207 #endif
208 #ifdef MNG_NO_16BIT_SUPPORT
209 if (pData->iPNGdepth > 8)
210 pData->sZlib.avail_out = (uInt)(2*pData->iRowsize + pData->iPixelofs);
211 #endif
212 }
213
214 do
215 { /* now inflate a row */
216 iZrslt = inflate (&pData->sZlib, Z_SYNC_FLUSH);
217 /* produced a full row ? */
218 if (((iZrslt == Z_OK) || (iZrslt == Z_STREAM_END)) &&
219 (pData->sZlib.avail_out == 0))
220 { /* image not completed yet ? */
221 if (pData->iRow < (mng_int32)pData->iDataheight)
222 {
223 #ifdef MNG_NO_1_2_4BIT_SUPPORT
224 if (pData->iPNGdepth == 1)
225 {
226 /* Inflate Workrow to 8-bit */
227 mng_int32 iX;
228 mng_uint8p pSrc = pData->pWorkrow+1;
229 mng_uint8p pDest = pSrc + pData->iRowsize - (pData->iRowsize+7)/8;
230
231 for (iX = ((pData->iRowsize+7)/8) ; iX > 0 ; iX--)
232 *pDest++ = *pSrc++;
233
234 pDest = pData->pWorkrow+1;
235 pSrc = pDest + pData->iRowsize - (pData->iRowsize+7)/8;
236 for (iX = pData->iRowsize; ;)
237 {
238 *pDest++ = (((*pSrc)>>7)&1);
239 if (iX-- <= 0)
240 break;
241 *pDest++ = (((*pSrc)>>6)&1);
242 if (iX-- <= 0)
243 break;
244 *pDest++ = (((*pSrc)>>5)&1);
245 if (iX-- <= 0)
246 break;
247 *pDest++ = (((*pSrc)>>4)&1);
248 if (iX-- <= 0)
249 break;
250 *pDest++ = (((*pSrc)>>3)&1);
251 if (iX-- <= 0)
252 break;
253 *pDest++ = (((*pSrc)>>2)&1);
254 if (iX-- <= 0)
255 break;
256 *pDest++ = (((*pSrc)>>1)&1);
257 if (iX-- <= 0)
258 break;
259 *pDest++ = (((*pSrc) )&1);
260 if (iX-- <= 0)
261 break;
262 pSrc++;
263 }
264 }
265 else if (pData->iPNGdepth == 2)
266 {
267 /* Inflate Workrow to 8-bit */
268 mng_int32 iX;
269 mng_uint8p pSrc = pData->pWorkrow+1;
270 mng_uint8p pDest = pSrc + pData->iRowsize - (2*pData->iRowsize+7)/8;
271
272 for (iX = ((2*pData->iRowsize+7)/8) ; iX > 0 ; iX--)
273 *pDest++ = *pSrc++;
274
275 pDest = pData->pWorkrow+1;
276 pSrc = pDest + pData->iRowsize - (2*pData->iRowsize+7)/8;
277 for (iX = pData->iRowsize; ;)
278 {
279 *pDest++ = (((*pSrc)>>6)&3);
280 if (iX-- <= 0)
281 break;
282 *pDest++ = (((*pSrc)>>4)&3);
283 if (iX-- <= 0)
284 break;
285 *pDest++ = (((*pSrc)>>2)&3);
286 if (iX-- <= 0)
287 break;
288 *pDest++ = (((*pSrc) )&3);
289 if (iX-- <= 0)
290 break;
291 pSrc++;
292 }
293 }
294 else if (pData->iPNGdepth == 4)
295 {
296 /* Inflate Workrow to 8-bit */
297 mng_int32 iX;
298 mng_uint8p pSrc = pData->pWorkrow+1;
299 mng_uint8p pDest = pSrc + pData->iRowsize - (4*pData->iRowsize+7)/8;
300
301 for (iX = ((4*pData->iRowsize+7)/8) ; iX > 0 ; iX--)
302 *pDest++ = *pSrc++;
303
304 pDest = pData->pWorkrow+1;
305 pSrc = pDest + pData->iRowsize - (4*pData->iRowsize+7)/8;
306 for (iX = pData->iRowsize; ;)
307 {
308 *pDest++ = (((*pSrc)>>4)&0x0f);
309 if (iX-- <= 0)
310 break;
311 *pDest++ = (((*pSrc) )&0x0f);
312 if (iX-- <= 0)
313 break;
314 pSrc++;
315 }
316 }
317 if (pData->iPNGdepth < 8 && pData->iColortype == 0)
318 {
319 /* Expand samples to 8-bit by LBR */
320 mng_int32 iX;
321 mng_uint8p pSrc = pData->pWorkrow+1;
322 mng_uint8 multiplier[]={0,255,85,0,17,0,0,0,1};
323
324 for (iX = pData->iRowsize; iX > 0; iX--)
325 *pSrc++ *= multiplier[pData->iPNGdepth];
326 }
327 #endif
328 #ifdef MNG_NO_16BIT_SUPPORT
329 if (pData->iPNGdepth > 8)
330 {
331 /* Reduce Workrow to 8-bit */
332 mng_int32 iX;
333 mng_uint8p pSrc = pData->pWorkrow+1;
334 mng_uint8p pDest = pSrc;
335
336 for (iX = pData->iRowsize; iX > 0; iX--)
337 {
338 *pDest = *pSrc;
339 pDest++;
340 pSrc+=2;
341 }
342 }
343 #endif
344
345 #ifdef FILTER192 /* has leveling info ? */
346 if (pData->iFilterofs == MNG_FILTER_DIFFERING)
347 iRslt = init_rowdiffering (pData);
348 else
349 #endif
350 iRslt = MNG_NOERROR;
351 /* filter the row if necessary */
352 if ((!iRslt) && (pData->iFilterofs < pData->iPixelofs ) &&
353 (*(pData->pWorkrow + pData->iFilterofs)) )
354 iRslt = mng_filter_a_row (pData);
355 else
356 iRslt = MNG_NOERROR;
357 /* additional leveling/differing ? */
358 if ((!iRslt) && (pData->fDifferrow))
359 {
360 iRslt = ((mng_differrow)pData->fDifferrow) (pData);
361
362 pSwap = pData->pWorkrow;
363 pData->pWorkrow = pData->pPrevrow;
364 pData->pPrevrow = pSwap; /* make sure we're processing the right data */
365 }
366
367 if (!iRslt)
368 {
369 #ifdef MNG_INCLUDE_JNG
370 if (pData->bHasJHDR) /* is JNG alpha-channel ? */
371 { /* just store in object ? */
372 if ((!iRslt) && (pData->fStorerow))
373 iRslt = ((mng_storerow)pData->fStorerow) (pData);
374 }
375 else
376 #endif /* MNG_INCLUDE_JNG */
377 { /* process this row */
378 if ((!iRslt) && (pData->fProcessrow))
379 iRslt = ((mng_processrow)pData->fProcessrow) (pData);
380 /* store in object ? */
381 if ((!iRslt) && (pData->fStorerow))
382 iRslt = ((mng_storerow)pData->fStorerow) (pData);
383 /* color correction ? */
384 if ((!iRslt) && (pData->fCorrectrow))
385 iRslt = ((mng_correctrow)pData->fCorrectrow) (pData);
386 /* slap onto canvas ? */
387 if ((!iRslt) && (pData->fDisplayrow))
388 {
389 iRslt = ((mng_displayrow)pData->fDisplayrow) (pData);
390
391 if (!iRslt) /* check progressive display refresh */
392 iRslt = mng_display_progressive_check (pData);
393
394 }
395 }
396 }
397
398 if (iRslt) /* on error bail out */
399 MNG_ERROR (pData, iRslt);
400
401 if (!pData->fDifferrow) /* swap row-pointers */
402 {
403 pSwap = pData->pWorkrow;
404 pData->pWorkrow = pData->pPrevrow;
405 pData->pPrevrow = pSwap; /* so prev points to the processed row! */
406 }
407
408 iRslt = mng_next_row (pData); /* adjust variables for next row */
409
410 if (iRslt) /* on error bail out */
411 MNG_ERROR (pData, iRslt);
412 }
413 /* let zlib know where to store next output */
414 pData->sZlib.next_out = pData->pWorkrow;
415 pData->sZlib.avail_out = (uInt)(pData->iRowsize + pData->iPixelofs);
416 #ifdef MNG_NO_1_2_4BIT_SUPPORT
417 if (pData->iPNGdepth < 8)
418 pData->sZlib.avail_out = (uInt)((pData->iPNGdepth*pData->iRowsize + 7)/8
419 + pData->iPixelofs);
420 #endif
421 #ifdef MNG_NO_16BIT_SUPPORT
422 if (pData->iPNGdepth > 8)
423 pData->sZlib.avail_out = (uInt)(2*pData->iRowsize + pData->iPixelofs);
424 #endif
425 }
426 } /* until some error or EOI
427 or all pixels received */
428 while ( (iZrslt == Z_OK) && (pData->sZlib.avail_in > 0) &&
429 ( (pData->iRow < (mng_int32)pData->iDataheight) ||
430 ( (pData->iPass >= 0) && (pData->iPass < 7) ) ) );
431 /* on error bail out */
432 if ((iZrslt != Z_OK) && (iZrslt != Z_STREAM_END))
433 MNG_ERRORZ (pData, (mng_uint32)iZrslt);
434 /* too much data ? */
435 if ((iZrslt == Z_OK) && (pData->sZlib.avail_in > 0))
436 MNG_WARNING (pData, MNG_TOOMUCHIDAT);
437
438 #ifdef MNG_SUPPORT_TRACE
439 MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEROWS, MNG_LC_END);
440 #endif
441
442 return MNG_NOERROR;
443 }
444 #endif /* MNG_SUPPORT_DISPLAY */
445
446 /* ************************************************************************** */
447
mngzlib_inflatedata(mng_datap pData,mng_uint32 iInlen,mng_uint8p pIndata)448 mng_retcode mngzlib_inflatedata (mng_datap pData,
449 mng_uint32 iInlen,
450 mng_uint8p pIndata)
451 {
452 int iZrslt;
453
454 #ifdef MNG_SUPPORT_TRACE
455 MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEDATA, MNG_LC_START);
456 #endif
457 /* let zlib know where to get stuff */
458 pData->sZlib.next_in = pIndata;
459 pData->sZlib.avail_in = (uInt)iInlen;
460 /* now inflate the data in one go! */
461 iZrslt = inflate (&pData->sZlib, Z_FINISH);
462 /* not enough room in output-buffer ? */
463 if ((iZrslt == Z_BUF_ERROR) || (pData->sZlib.avail_in > 0))
464 return MNG_BUFOVERFLOW;
465 /* on error bail out */
466 if ((iZrslt != Z_OK) && (iZrslt != Z_STREAM_END))
467 MNG_ERRORZ (pData, (mng_uint32)iZrslt);
468
469 #ifdef MNG_SUPPORT_TRACE
470 MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEDATA, MNG_LC_END);
471 #endif
472
473 return MNG_NOERROR;
474 }
475
476 /* ************************************************************************** */
477
mngzlib_inflatefree(mng_datap pData)478 mng_retcode mngzlib_inflatefree (mng_datap pData)
479 {
480 int iZrslt;
481
482 #ifdef MNG_SUPPORT_TRACE
483 MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEFREE, MNG_LC_START);
484 #endif
485
486 pData->bInflating = MNG_FALSE; /* stopped it */
487
488 iZrslt = inflateEnd (&pData->sZlib); /* let zlib cleanup its own stuff */
489
490 if (iZrslt != Z_OK) /* on error bail out */
491 MNG_ERRORZ (pData, (mng_uint32)iZrslt);
492
493 #ifdef MNG_SUPPORT_TRACE
494 MNG_TRACE (pData, MNG_FN_ZLIB_INFLATEFREE, MNG_LC_END);
495 #endif
496
497 return MNG_NOERROR; /* done */
498 }
499
500 /* ************************************************************************** */
501
mngzlib_deflateinit(mng_datap pData)502 mng_retcode mngzlib_deflateinit (mng_datap pData)
503 {
504 int iZrslt;
505
506 #ifdef MNG_SUPPORT_TRACE
507 MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEINIT, MNG_LC_START);
508 #endif
509 /* initialize zlib structures and such */
510 iZrslt = deflateInit2 (&pData->sZlib, pData->iZlevel, pData->iZmethod,
511 pData->iZwindowbits, pData->iZmemlevel,
512 pData->iZstrategy);
513
514 if (iZrslt != Z_OK) /* on error bail out */
515 MNG_ERRORZ (pData, (mng_uint32)iZrslt);
516
517 pData->bDeflating = MNG_TRUE; /* really deflating something now */
518
519 #ifdef MNG_SUPPORT_TRACE
520 MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEINIT, MNG_LC_END);
521 #endif
522
523 return MNG_NOERROR; /* done */
524 }
525
526 /* ************************************************************************** */
527
mngzlib_deflaterows(mng_datap pData,mng_uint32 iInlen,mng_uint8p pIndata)528 mng_retcode mngzlib_deflaterows (mng_datap pData,
529 mng_uint32 iInlen,
530 mng_uint8p pIndata)
531 {
532 #ifdef MNG_SUPPORT_TRACE
533 MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEROWS, MNG_LC_START);
534 #endif
535
536
537
538
539 #ifdef MNG_SUPPORT_TRACE
540 MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEROWS, MNG_LC_END);
541 #endif
542
543 return MNG_NOERROR;
544 }
545
546 /* ************************************************************************** */
547
mngzlib_deflatedata(mng_datap pData,mng_uint32 iInlen,mng_uint8p pIndata)548 mng_retcode mngzlib_deflatedata (mng_datap pData,
549 mng_uint32 iInlen,
550 mng_uint8p pIndata)
551 {
552 int iZrslt;
553
554 #ifdef MNG_SUPPORT_TRACE
555 MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEDATA, MNG_LC_START);
556 #endif
557
558 pData->sZlib.next_in = pIndata; /* let zlib know where to get stuff */
559 pData->sZlib.avail_in = (uInt)iInlen;
560 /* now deflate the data in one go! */
561 iZrslt = deflate (&pData->sZlib, Z_FINISH);
562 /* not enough room in output-buffer ? */
563 if ((iZrslt == Z_BUF_ERROR) || (pData->sZlib.avail_in > 0))
564 return MNG_BUFOVERFLOW;
565 /* on error bail out */
566 if ((iZrslt != Z_OK) && (iZrslt != Z_STREAM_END))
567 MNG_ERRORZ (pData, (mng_uint32)iZrslt);
568
569 #ifdef MNG_SUPPORT_TRACE
570 MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEDATA, MNG_LC_END);
571 #endif
572
573 return MNG_NOERROR;
574 }
575
576 /* ************************************************************************** */
577
mngzlib_deflatefree(mng_datap pData)578 mng_retcode mngzlib_deflatefree (mng_datap pData)
579 {
580 int iZrslt;
581
582 #ifdef MNG_SUPPORT_TRACE
583 MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEFREE, MNG_LC_START);
584 #endif
585
586 iZrslt = deflateEnd (&pData->sZlib); /* let zlib cleanup its own stuff */
587
588 if (iZrslt != Z_OK) /* on error bail out */
589 MNG_ERRORZ (pData, (mng_uint32)iZrslt);
590
591 pData->bDeflating = MNG_FALSE; /* stopped it */
592
593 #ifdef MNG_SUPPORT_TRACE
594 MNG_TRACE (pData, MNG_FN_ZLIB_DEFLATEFREE, MNG_LC_END);
595 #endif
596
597 return MNG_NOERROR; /* done */
598 }
599
600 /* ************************************************************************** */
601
602 #endif /* MNG_INCLUDE_ZLIB */
603
604 /* ************************************************************************** */
605 /* * end of file * */
606 /* ************************************************************************** */
607
608