/src/FreeImage/Source/LibMNG/libmng_zlib.c
C | 607 lines | 415 code | 98 blank | 94 comment | 106 complexity | 066d6e2e2ce002795c885d61d9e4b499 MD5 | raw file
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 77voidpf 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 97void 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 110mng_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 138mng_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 158mng_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 184mng_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 448mng_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 478mng_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 502mng_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 528mng_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 548mng_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 578mng_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