/src/FreeImage/Source/LibMNG/libmng_chunk_io.c
https://bitbucket.org/cabalistic/ogredeps/ · C · 1459 lines · 942 code · 174 blank · 343 comment · 352 complexity · 7923962c84af202d068737fdfbf91ecd MD5 · raw file
Large files are truncated click here to view the full file
- /** ************************************************************************* */
- /* * For conditions of distribution and use, * */
- /* * see copyright notice in libmng.h * */
- /* ************************************************************************** */
- /* * * */
- /* * project : libmng * */
- /* * file : libmng_chunk_io.c copyright (c) 2000-2007 G.Juyn * */
- /* * version : 1.0.10 * */
- /* * * */
- /* * purpose : Chunk I/O routines (implementation) * */
- /* * * */
- /* * author : G.Juyn * */
- /* * * */
- /* * comment : implementation of chunk input/output routines * */
- /* * * */
- /* * changes : 0.5.1 - 05/01/2000 - G.Juyn * */
- /* * - cleaned up left-over teststuff in the BACK chunk routine * */
- /* * 0.5.1 - 05/04/2000 - G.Juyn * */
- /* * - changed CRC initialization to use dynamic structure * */
- /* * (wasn't thread-safe the old way !) * */
- /* * 0.5.1 - 05/06/2000 - G.Juyn * */
- /* * - filled in many missing sequence&length checks * */
- /* * - filled in many missing chunk-store snippets * */
- /* * 0.5.1 - 05/08/2000 - G.Juyn * */
- /* * - added checks for running animations * */
- /* * - filled some write routines * */
- /* * - changed strict-ANSI stuff * */
- /* * 0.5.1 - 05/10/2000 - G.Juyn * */
- /* * - filled some more write routines * */
- /* * 0.5.1 - 05/11/2000 - G.Juyn * */
- /* * - filled remaining write routines * */
- /* * - fixed read_pplt with regard to deltatype * */
- /* * - added callback error-reporting support * */
- /* * - added pre-draft48 support (short MHDR, frame_mode, LOOP) * */
- /* * 0.5.1 - 05/12/2000 - G.Juyn * */
- /* * - changed trace to macro for callback error-reporting * */
- /* * - fixed chunk-storage bit in several routines * */
- /* * 0.5.1 - 05/13/2000 - G.Juyn * */
- /* * - added eMNGma hack (will be removed in 1.0.0 !!!) * */
- /* * - added TERM animation object pointer (easier reference) * */
- /* * - supplemented the SAVE & SEEK display processing * */
- /* * * */
- /* * 0.5.2 - 05/18/2000 - G.Juyn * */
- /* * - B004 - fixed problem with MNG_SUPPORT_WRITE not defined * */
- /* * also for MNG_SUPPORT_WRITE without MNG_INCLUDE_JNG * */
- /* * 0.5.2 - 05/19/2000 - G.Juyn * */
- /* * - cleaned up some code regarding mixed support * */
- /* * 0.5.2 - 05/20/2000 - G.Juyn * */
- /* * - implemented JNG support * */
- /* * 0.5.2 - 05/24/2000 - G.Juyn * */
- /* * - added support for global color-chunks in animation * */
- /* * - added support for global PLTE,tRNS,bKGD in animation * */
- /* * - added support for SAVE & SEEK in animation * */
- /* * 0.5.2 - 05/29/2000 - G.Juyn * */
- /* * - changed ani_create calls not returning object pointer * */
- /* * - create ani objects always (not just inside TERM/LOOP) * */
- /* * 0.5.2 - 05/30/2000 - G.Juyn * */
- /* * - added support for delta-image processing * */
- /* * 0.5.2 - 05/31/2000 - G.Juyn * */
- /* * - fixed up punctuation (contributed by Tim Rowley) * */
- /* * 0.5.2 - 06/02/2000 - G.Juyn * */
- /* * - changed SWAP_ENDIAN to BIGENDIAN_SUPPORTED * */
- /* * 0.5.2 - 06/03/2000 - G.Juyn * */
- /* * - fixed makeup for Linux gcc compile * */
- /* * * */
- /* * 0.5.3 - 06/12/2000 - G.Juyn * */
- /* * - added processing of color-info on delta-image * */
- /* * 0.5.3 - 06/13/2000 - G.Juyn * */
- /* * - fixed handling of empty SAVE chunk * */
- /* * 0.5.3 - 06/17/2000 - G.Juyn * */
- /* * - changed to support delta-images * */
- /* * - added extra checks for delta-images * */
- /* * 0.5.3 - 06/20/2000 - G.Juyn * */
- /* * - fixed possible trouble if IEND display-process got * */
- /* * broken up * */
- /* * 0.5.3 - 06/21/2000 - G.Juyn * */
- /* * - added processing of PLTE & tRNS for delta-images * */
- /* * - added administration of imagelevel parameter * */
- /* * 0.5.3 - 06/22/2000 - G.Juyn * */
- /* * - implemented support for PPLT chunk * */
- /* * 0.5.3 - 06/26/2000 - G.Juyn * */
- /* * - added precaution against faulty iCCP chunks from PS * */
- /* * 0.5.3 - 06/29/2000 - G.Juyn * */
- /* * - fixed some 64-bit warnings * */
- /* * * */
- /* * 0.9.1 - 07/14/2000 - G.Juyn * */
- /* * - changed pre-draft48 frame_mode=3 to frame_mode=1 * */
- /* * 0.9.1 - 07/16/2000 - G.Juyn * */
- /* * - fixed storage of images during mng_read() * */
- /* * - fixed support for mng_display() after mng_read() * */
- /* * 0.9.1 - 07/19/2000 - G.Juyn * */
- /* * - fixed several chunk-writing routines * */
- /* * 0.9.1 - 07/24/2000 - G.Juyn * */
- /* * - fixed reading of still-images * */
- /* * * */
- /* * 0.9.2 - 08/05/2000 - G.Juyn * */
- /* * - changed file-prefixes * */
- /* * * */
- /* * 0.9.3 - 08/07/2000 - G.Juyn * */
- /* * - B111300 - fixup for improved portability * */
- /* * 0.9.3 - 08/08/2000 - G.Juyn * */
- /* * - fixed compiler-warnings from Mozilla * */
- /* * 0.9.3 - 08/09/2000 - G.Juyn * */
- /* * - added check for simplicity-bits in MHDR * */
- /* * 0.9.3 - 08/12/2000 - G.Juyn * */
- /* * - fixed check for simplicity-bits in MHDR (JNG) * */
- /* * 0.9.3 - 08/12/2000 - G.Juyn * */
- /* * - added workaround for faulty PhotoShop iCCP chunk * */
- /* * 0.9.3 - 08/22/2000 - G.Juyn * */
- /* * - fixed write-code for zTXt & iTXt * */
- /* * - fixed read-code for iTXt * */
- /* * 0.9.3 - 08/26/2000 - G.Juyn * */
- /* * - added MAGN chunk * */
- /* * 0.9.3 - 09/07/2000 - G.Juyn * */
- /* * - added support for new filter_types * */
- /* * 0.9.3 - 09/10/2000 - G.Juyn * */
- /* * - fixed DEFI behavior * */
- /* * 0.9.3 - 10/02/2000 - G.Juyn * */
- /* * - fixed simplicity-check in compliance with draft 81/0.98a * */
- /* * 0.9.3 - 10/10/2000 - G.Juyn * */
- /* * - added support for alpha-depth prediction * */
- /* * 0.9.3 - 10/11/2000 - G.Juyn * */
- /* * - added support for nEED * */
- /* * 0.9.3 - 10/16/2000 - G.Juyn * */
- /* * - added support for JDAA * */
- /* * 0.9.3 - 10/17/2000 - G.Juyn * */
- /* * - fixed support for MAGN * */
- /* * - implemented nEED "xxxx" (where "xxxx" is a chunkid) * */
- /* * - added callback to process non-critical unknown chunks * */
- /* * - fixed support for bKGD * */
- /* * 0.9.3 - 10/23/2000 - G.Juyn * */
- /* * - fixed bug in empty PLTE handling * */
- /* * * */
- /* * 0.9.4 - 11/20/2000 - G.Juyn * */
- /* * - changed IHDR filter_method check for PNGs * */
- /* * 0.9.4 - 1/18/2001 - G.Juyn * */
- /* * - added errorchecking for MAGN methods * */
- /* * - removed test filter-methods 1 & 65 * */
- /* * * */
- /* * 0.9.5 - 1/25/2001 - G.Juyn * */
- /* * - fixed some small compiler warnings (thanks Nikki) * */
- /* * * */
- /* * 1.0.2 - 05/05/2000 - G.Juyn * */
- /* * - B421427 - writes wrong format in bKGD and tRNS * */
- /* * 1.0.2 - 06/20/2000 - G.Juyn * */
- /* * - B434583 - compiler-warning if MNG_STORE_CHUNKS undefined * */
- /* * * */
- /* * 1.0.5 - 07/08/2002 - G.Juyn * */
- /* * - B578572 - removed eMNGma hack (thanks Dimitri!) * */
- /* * 1.0.5 - 08/07/2002 - G.Juyn * */
- /* * - added test-option for PNG filter method 193 (=no filter) * */
- /* * 1.0.5 - 08/15/2002 - G.Juyn * */
- /* * - completed PROM support * */
- /* * 1.0.5 - 08/19/2002 - G.Juyn * */
- /* * - B597134 - libmng pollutes the linker namespace * */
- /* * 1.0.5 - 09/07/2002 - G.Juyn * */
- /* * - fixed reading of FRAM with just frame_mode and name * */
- /* * 1.0.5 - 09/13/2002 - G.Juyn * */
- /* * - fixed read/write of MAGN chunk * */
- /* * 1.0.5 - 09/14/2002 - G.Juyn * */
- /* * - added event handling for dynamic MNG * */
- /* * 1.0.5 - 09/15/2002 - G.Juyn * */
- /* * - fixed LOOP iteration=0 special case * */
- /* * 1.0.5 - 09/19/2002 - G.Juyn * */
- /* * - misplaced TERM is now treated as warning * */
- /* * 1.0.5 - 09/20/2002 - G.Juyn * */
- /* * - added support for PAST * */
- /* * 1.0.5 - 10/03/2002 - G.Juyn * */
- /* * - fixed chunk-storage for evNT chunk * */
- /* * 1.0.5 - 10/07/2002 - G.Juyn * */
- /* * - fixed DISC support * */
- /* * - added another fix for misplaced TERM chunk * */
- /* * 1.0.5 - 10/17/2002 - G.Juyn * */
- /* * - fixed initializtion of pIds in dISC read routine * */
- /* * 1.0.5 - 11/06/2002 - G.Juyn * */
- /* * - added support for nEED "MNG 1.1" * */
- /* * - added support for nEED "CACHEOFF" * */
- /* * * */
- /* * 1.0.6 - 05/25/2003 - G.R-P * */
- /* * - added MNG_SKIPCHUNK_cHNK footprint optimizations * */
- /* * 1.0.6 - 06/02/2003 - G.R-P * */
- /* * - removed some redundant checks for iRawlen==0 * */
- /* * 1.0.6 - 06/22/2003 - G.R-P * */
- /* * - added MNG_NO_16BIT_SUPPORT, MNG_NO_DELTA_PNG reductions * */
- /* * - optionally use zlib's crc32 function instead of * */
- /* * local mng_update_crc * */
- /* * 1.0.6 - 07/14/2003 - G.R-P * */
- /* * - added MNG_NO_LOOP_SIGNALS_SUPPORTED conditional * */
- /* * 1.0.6 - 07/29/2003 - G.R-P * */
- /* * - added conditionals around PAST chunk support * */
- /* * 1.0.6 - 08/17/2003 - G.R-P * */
- /* * - added conditionals around non-VLC chunk support * */
- /* * * */
- /* * 1.0.7 - 10/29/2003 - G.R-P * */
- /* * - revised JDAA and JDAT readers to avoid compiler bug * */
- /* * 1.0.7 - 01/25/2004 - J.S * */
- /* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */
- /* * 1.0.7 - 01/27/2004 - J.S * */
- /* * - fixed inclusion of IJNG chunk for non-JNG use * */
- /* * 1.0.7 - 02/26/2004 - G.Juyn * */
- /* * - fixed bug in chunk-storage of SHOW chunk (from == to) * */
- /* * * */
- /* * 1.0.8 - 04/02/2004 - G.Juyn * */
- /* * - added CRC existence & checking flags * */
- /* * 1.0.8 - 07/07/2004 - G.R-P * */
- /* * - change worst-case iAlphadepth to 1 for standalone PNGs * */
- /* * * */
- /* * 1.0.9 - 09/28/2004 - G.R-P * */
- /* * - improved handling of cheap transparency when 16-bit * */
- /* * support is disabled * */
- /* * 1.0.9 - 10/04/2004 - G.Juyn * */
- /* * - fixed bug in writing sBIT for indexed color * */
- /* * 1.0.9 - 10/10/2004 - G.R-P. * */
- /* * - added MNG_NO_1_2_4BIT_SUPPORT * */
- /* * 1.0.9 - 12/05/2004 - G.Juyn * */
- /* * - added conditional MNG_OPTIMIZE_CHUNKINITFREE * */
- /* * 1.0.9 - 12/06/2004 - G.Juyn * */
- /* * - added conditional MNG_OPTIMIZE_CHUNKASSIGN * */
- /* * 1.0.9 - 12/07/2004 - G.Juyn * */
- /* * - added conditional MNG_OPTIMIZE_CHUNKREADER * */
- /* * 1.0.9 - 12/11/2004 - G.Juyn * */
- /* * - added conditional MNG_OPTIMIZE_DISPLAYCALLS * */
- /* * 1.0.9 - 12/20/2004 - G.Juyn * */
- /* * - cleaned up macro-invocations (thanks to D. Airlie) * */
- /* * 1.0.9 - 01/17/2005 - G.Juyn * */
- /* * - fixed problem with global PLTE/tRNS * */
- /* * * */
- /* * 1.0.10 - 02/07/2005 - G.Juyn * */
- /* * - fixed display routines called twice for FULL_MNG * */
- /* * support in mozlibmngconf.h * */
- /* * 1.0.10 - 12/04/2005 - G.R-P. * */
- /* * - #ifdef out use of mng_inflate_buffer when it is not * */
- /* * available. * */
- /* * 1.0.10 - 04/08/2007 - G.Juyn * */
- /* * - added support for mPNG proposal * */
- /* * 1.0.10 - 04/12/2007 - G.Juyn * */
- /* * - added support for ANG proposal * */
- /* * 1.0.10 - 05/02/2007 - G.Juyn * */
- /* * - fixed inflate_buffer for extreme compression ratios * */
- /* * * */
- /* ************************************************************************** */
- #include "libmng.h"
- #include "libmng_data.h"
- #include "libmng_error.h"
- #include "libmng_trace.h"
- #ifdef __BORLANDC__
- #pragma hdrstop
- #endif
- #include "libmng_objects.h"
- #include "libmng_object_prc.h"
- #include "libmng_chunks.h"
- #ifdef MNG_CHECK_BAD_ICCP
- #include "libmng_chunk_prc.h"
- #endif
- #include "libmng_memory.h"
- #include "libmng_display.h"
- #include "libmng_zlib.h"
- #include "libmng_pixels.h"
- #include "libmng_chunk_io.h"
- #if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
- #pragma option -A /* force ANSI-C */
- #endif
- /* ************************************************************************** */
- /* * * */
- /* * CRC - Cyclic Redundancy Check * */
- /* * * */
- /* * The code below is taken directly from the sample provided with the * */
- /* * PNG specification. * */
- /* * (it is only adapted to the library's internal data-definitions) * */
- /* * * */
- /* ************************************************************************** */
- /* Make the table for a fast CRC. */
- #ifndef MNG_USE_ZLIB_CRC
- MNG_LOCAL void make_crc_table (mng_datap pData)
- {
- mng_uint32 iC;
- mng_int32 iN, iK;
- for (iN = 0; iN < 256; iN++)
- {
- iC = (mng_uint32) iN;
- for (iK = 0; iK < 8; iK++)
- {
- if (iC & 1)
- iC = 0xedb88320U ^ (iC >> 1);
- else
- iC = iC >> 1;
- }
- pData->aCRCtable [iN] = iC;
- }
- pData->bCRCcomputed = MNG_TRUE;
- }
- #endif
- /* Update a running CRC with the bytes buf[0..len-1]--the CRC
- should be initialized to all 1's, and the transmitted value
- is the 1's complement of the final running CRC (see the
- crc() routine below). */
- MNG_LOCAL mng_uint32 update_crc (mng_datap pData,
- mng_uint32 iCrc,
- mng_uint8p pBuf,
- mng_int32 iLen)
- {
- #ifdef MNG_USE_ZLIB_CRC
- return crc32 (iCrc, pBuf, iLen);
- #else
- mng_uint32 iC = iCrc;
- mng_int32 iN;
- if (!pData->bCRCcomputed)
- make_crc_table (pData);
- for (iN = 0; iN < iLen; iN++)
- iC = pData->aCRCtable [(iC ^ pBuf [iN]) & 0xff] ^ (iC >> 8);
- return iC;
- #endif
- }
- /* Return the CRC of the bytes buf[0..len-1]. */
- mng_uint32 mng_crc (mng_datap pData,
- mng_uint8p pBuf,
- mng_int32 iLen)
- {
- #ifdef MNG_USE_ZLIB_CRC
- return update_crc (pData, 0, pBuf, iLen);
- #else
- return update_crc (pData, 0xffffffffU, pBuf, iLen) ^ 0xffffffffU;
- #endif
- }
- /* ************************************************************************** */
- /* * * */
- /* * Routines for swapping byte-order from and to graphic files * */
- /* * (This code is adapted from the libpng package) * */
- /* * * */
- /* ************************************************************************** */
- #ifndef MNG_BIGENDIAN_SUPPORTED
- /* ************************************************************************** */
- mng_uint32 mng_get_uint32 (mng_uint8p pBuf)
- {
- mng_uint32 i = ((mng_uint32)(*pBuf) << 24) +
- ((mng_uint32)(*(pBuf + 1)) << 16) +
- ((mng_uint32)(*(pBuf + 2)) << 8) +
- (mng_uint32)(*(pBuf + 3));
- return (i);
- }
- /* ************************************************************************** */
- mng_int32 mng_get_int32 (mng_uint8p pBuf)
- {
- mng_int32 i = ((mng_int32)(*pBuf) << 24) +
- ((mng_int32)(*(pBuf + 1)) << 16) +
- ((mng_int32)(*(pBuf + 2)) << 8) +
- (mng_int32)(*(pBuf + 3));
- return (i);
- }
- /* ************************************************************************** */
- mng_uint16 mng_get_uint16 (mng_uint8p pBuf)
- {
- mng_uint16 i = (mng_uint16)(((mng_uint16)(*pBuf) << 8) +
- (mng_uint16)(*(pBuf + 1)));
- return (i);
- }
- /* ************************************************************************** */
- void mng_put_uint32 (mng_uint8p pBuf,
- mng_uint32 i)
- {
- *pBuf = (mng_uint8)((i >> 24) & 0xff);
- *(pBuf+1) = (mng_uint8)((i >> 16) & 0xff);
- *(pBuf+2) = (mng_uint8)((i >> 8) & 0xff);
- *(pBuf+3) = (mng_uint8)(i & 0xff);
- }
- /* ************************************************************************** */
- void mng_put_int32 (mng_uint8p pBuf,
- mng_int32 i)
- {
- *pBuf = (mng_uint8)((i >> 24) & 0xff);
- *(pBuf+1) = (mng_uint8)((i >> 16) & 0xff);
- *(pBuf+2) = (mng_uint8)((i >> 8) & 0xff);
- *(pBuf+3) = (mng_uint8)(i & 0xff);
- }
- /* ************************************************************************** */
- void mng_put_uint16 (mng_uint8p pBuf,
- mng_uint16 i)
- {
- *pBuf = (mng_uint8)((i >> 8) & 0xff);
- *(pBuf+1) = (mng_uint8)(i & 0xff);
- }
- /* ************************************************************************** */
- #endif /* !MNG_BIGENDIAN_SUPPORTED */
- /* ************************************************************************** */
- /* * * */
- /* * Helper routines to simplify chunk-data extraction * */
- /* * * */
- /* ************************************************************************** */
- #ifdef MNG_INCLUDE_READ_PROCS
- /* ************************************************************************** */
- #ifndef MNG_OPTIMIZE_CHUNKREADER
- MNG_LOCAL mng_uint8p find_null (mng_uint8p pIn)
- {
- mng_uint8p pOut = pIn;
- while (*pOut) /* the read_graphic routine has made sure there's */
- pOut++; /* always at least 1 zero-byte in the buffer */
- return pOut;
- }
- #endif
- /* ************************************************************************** */
- #if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || \
- !defined(MNG_SKIPCHUNK_iTXt) || defined(MNG_INCLUDE_MPNG_PROPOSAL) || \
- defined(MNG_INCLUDE_ANG_PROPOSAL)
- mng_retcode mng_inflate_buffer (mng_datap pData,
- mng_uint8p pInbuf,
- mng_uint32 iInsize,
- mng_uint8p *pOutbuf,
- mng_uint32 *iOutsize,
- mng_uint32 *iRealsize)
- {
- mng_retcode iRetcode = MNG_NOERROR;
- #ifdef MNG_SUPPORT_TRACE
- MNG_TRACE (pData, MNG_FN_INFLATE_BUFFER, MNG_LC_START);
- #endif
- if (iInsize) /* anything to do ? */
- {
- *iOutsize = iInsize * 3; /* estimate uncompressed size */
- /* and allocate a temporary buffer */
- MNG_ALLOC (pData, *pOutbuf, *iOutsize);
- do
- {
- mngzlib_inflateinit (pData); /* initialize zlib */
- /* let zlib know where to store the output */
- pData->sZlib.next_out = *pOutbuf;
- /* "size - 1" so we've got space for the
- zero-termination of a possible string */
- pData->sZlib.avail_out = *iOutsize - 1;
- /* ok; let's inflate... */
- iRetcode = mngzlib_inflatedata (pData, iInsize, pInbuf);
- /* determine actual output size */
- *iRealsize = (mng_uint32)pData->sZlib.total_out;
- mngzlib_inflatefree (pData); /* zlib's done */
- if (iRetcode == MNG_BUFOVERFLOW) /* not enough space ? */
- { /* then get some more */
- MNG_FREEX (pData, *pOutbuf, *iOutsize);
- *iOutsize = *iOutsize + *iOutsize;
- MNG_ALLOC (pData, *pOutbuf, *iOutsize);
- }
- } /* repeat if we didn't have enough space */
- while ((iRetcode == MNG_BUFOVERFLOW) &&
- (*iOutsize < 200 * iInsize));
- if (!iRetcode) /* if oke ? */
- *((*pOutbuf) + *iRealsize) = 0; /* then put terminator zero */
- }
- else
- {
- *pOutbuf = 0; /* nothing to do; then there's no output */
- *iOutsize = 0;
- *iRealsize = 0;
- }
- #ifdef MNG_SUPPORT_TRACE
- MNG_TRACE (pData, MNG_FN_INFLATE_BUFFER, MNG_LC_END);
- #endif
- return iRetcode;
- }
- #endif
- /* ************************************************************************** */
- #endif /* MNG_INCLUDE_READ_PROCS */
- /* ************************************************************************** */
- /* * * */
- /* * Helper routines to simplify chunk writing * */
- /* * * */
- /* ************************************************************************** */
- #ifdef MNG_INCLUDE_WRITE_PROCS
- /* ************************************************************************** */
- #if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || !defined(MNG_SKIPCHUNK_iTXt)
- MNG_LOCAL mng_retcode deflate_buffer (mng_datap pData,
- mng_uint8p pInbuf,
- mng_uint32 iInsize,
- mng_uint8p *pOutbuf,
- mng_uint32 *iOutsize,
- mng_uint32 *iRealsize)
- {
- mng_retcode iRetcode = MNG_NOERROR;
- #ifdef MNG_SUPPORT_TRACE
- MNG_TRACE (pData, MNG_FN_DEFLATE_BUFFER, MNG_LC_START);
- #endif
- if (iInsize) /* anything to do ? */
- {
- *iOutsize = (iInsize * 5) >> 2; /* estimate compressed size */
- /* and allocate a temporary buffer */
- MNG_ALLOC (pData, *pOutbuf, *iOutsize);
- do
- {
- mngzlib_deflateinit (pData); /* initialize zlib */
- /* let zlib know where to store the output */
- pData->sZlib.next_out = *pOutbuf;
- pData->sZlib.avail_out = *iOutsize;
- /* ok; let's deflate... */
- iRetcode = mngzlib_deflatedata (pData, iInsize, pInbuf);
- /* determine actual output size */
- *iRealsize = pData->sZlib.total_out;
- mngzlib_deflatefree (pData); /* zlib's done */
- if (iRetcode == MNG_BUFOVERFLOW) /* not enough space ? */
- { /* then get some more */
- MNG_FREEX (pData, *pOutbuf, *iOutsize);
- *iOutsize = *iOutsize + (iInsize >> 1);
- MNG_ALLOC (pData, *pOutbuf, *iOutsize);
- }
- } /* repeat if we didn't have enough space */
- while (iRetcode == MNG_BUFOVERFLOW);
- }
- else
- {
- *pOutbuf = 0; /* nothing to do; then there's no output */
- *iOutsize = 0;
- *iRealsize = 0;
- }
- #ifdef MNG_SUPPORT_TRACE
- MNG_TRACE (pData, MNG_FN_DEFLATE_BUFFER, MNG_LC_END);
- #endif
- return iRetcode;
- }
- #endif
- /* ************************************************************************** */
- MNG_LOCAL mng_retcode write_raw_chunk (mng_datap pData,
- mng_chunkid iChunkname,
- mng_uint32 iRawlen,
- mng_uint8p pRawdata)
- {
- mng_uint32 iCrc;
- mng_uint32 iWritten;
- #ifdef MNG_SUPPORT_TRACE
- MNG_TRACE (pData, MNG_FN_WRITE_RAW_CHUNK, MNG_LC_START);
- #endif
- /* temporary buffer ? */
- if ((pRawdata != 0) && (pRawdata != pData->pWritebuf+8))
- { /* store length & chunktype in default buffer */
- mng_put_uint32 (pData->pWritebuf, iRawlen);
- mng_put_uint32 (pData->pWritebuf+4, (mng_uint32)iChunkname);
- if (pData->iCrcmode & MNG_CRC_OUTPUT)
- {
- if ((pData->iCrcmode & MNG_CRC_OUTPUT) == MNG_CRC_OUTPUT_GENERATE)
- { /* calculate the crc */
- iCrc = update_crc (pData, 0xffffffffL, pData->pWritebuf+4, 4);
- iCrc = update_crc (pData, iCrc, pRawdata, iRawlen) ^ 0xffffffffL;
- } else {
- iCrc = 0; /* dummy crc */
- } /* store in default buffer */
- mng_put_uint32 (pData->pWritebuf+8, iCrc);
- }
- /* write the length & chunktype */
- if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, 8, &iWritten))
- MNG_ERROR (pData, MNG_APPIOERROR);
- if (iWritten != 8) /* disk full ? */
- MNG_ERROR (pData, MNG_OUTPUTERROR);
- /* write the temporary buffer */
- if (!pData->fWritedata ((mng_handle)pData, pRawdata, iRawlen, &iWritten))
- MNG_ERROR (pData, MNG_APPIOERROR);
- if (iWritten != iRawlen) /* disk full ? */
- MNG_ERROR (pData, MNG_OUTPUTERROR);
- if (pData->iCrcmode & MNG_CRC_OUTPUT)
- { /* write the crc */
- if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf+8, 4, &iWritten))
- MNG_ERROR (pData, MNG_APPIOERROR);
- if (iWritten != 4) /* disk full ? */
- MNG_ERROR (pData, MNG_OUTPUTERROR);
- }
- }
- else
- { /* prefix with length & chunktype */
- mng_put_uint32 (pData->pWritebuf, iRawlen);
- mng_put_uint32 (pData->pWritebuf+4, (mng_uint32)iChunkname);
- if (pData->iCrcmode & MNG_CRC_OUTPUT)
- {
- if ((pData->iCrcmode & MNG_CRC_OUTPUT) == MNG_CRC_OUTPUT_GENERATE)
- /* calculate the crc */
- iCrc = mng_crc (pData, pData->pWritebuf+4, iRawlen + 4);
- else
- iCrc = 0; /* dummy crc */
- /* add it to the buffer */
- mng_put_uint32 (pData->pWritebuf + iRawlen + 8, iCrc);
- /* write it in a single pass */
- if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, iRawlen + 12, &iWritten))
- MNG_ERROR (pData, MNG_APPIOERROR);
- if (iWritten != iRawlen + 12) /* disk full ? */
- MNG_ERROR (pData, MNG_OUTPUTERROR);
- } else {
- if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, iRawlen + 8, &iWritten))
- MNG_ERROR (pData, MNG_APPIOERROR);
- if (iWritten != iRawlen + 8) /* disk full ? */
- MNG_ERROR (pData, MNG_OUTPUTERROR);
- }
- }
- #ifdef MNG_SUPPORT_TRACE
- MNG_TRACE (pData, MNG_FN_WRITE_RAW_CHUNK, MNG_LC_END);
- #endif
- return MNG_NOERROR;
- }
- /* ************************************************************************** */
- /* B004 */
- #endif /* MNG_INCLUDE_WRITE_PROCS */
- /* B004 */
- /* ************************************************************************** */
- /* * * */
- /* * chunk read functions * */
- /* * * */
- /* ************************************************************************** */
- #ifdef MNG_INCLUDE_READ_PROCS
- /* ************************************************************************** */
- #ifdef MNG_OPTIMIZE_CHUNKREADER
- /* ************************************************************************** */
- MNG_LOCAL mng_retcode create_chunk_storage (mng_datap pData,
- mng_chunkp pHeader,
- mng_uint32 iRawlen,
- mng_uint8p pRawdata,
- mng_field_descp pField,
- mng_uint16 iFields,
- mng_chunkp* ppChunk,
- mng_bool bWorkcopy)
- {
- mng_field_descp pTempfield = pField;
- mng_uint16 iFieldcount = iFields;
- mng_uint8p pTempdata = pRawdata;
- mng_uint32 iTemplen = iRawlen;
- mng_uint16 iLastgroup = 0;
- mng_uint8p pChunkdata;
- mng_uint32 iDatalen;
- mng_uint8 iColortype;
- mng_bool bProcess;
- /* initialize storage */
- mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
- if (iRetcode) /* on error bail out */
- return iRetcode;
- if (((mng_chunk_headerp)(*ppChunk))->iChunkname == MNG_UINT_HUH)
- ((mng_chunk_headerp)(*ppChunk))->iChunkname = pData->iChunkname;
- if ((!bWorkcopy) ||
- ((((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_IDAT) &&
- (((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_JDAT) &&
- (((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_JDAA) ))
- {
- pChunkdata = (mng_uint8p)(*ppChunk);
- #ifdef MNG_INCLUDE_JNG /* determine current colortype */
- if (pData->bHasJHDR)
- iColortype = (mng_uint8)(pData->iJHDRcolortype - 8);
- else
- #endif /* MNG_INCLUDE_JNG */
- if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
- iColortype = pData->iColortype;
- else
- iColortype = 6;
- if (iTemplen) /* not empty ? */
- { /* then go fill the fields */
- while ((iFieldcount) && (iTemplen))
- {
- if (pTempfield->iOffsetchunk)
- {
- if (pTempfield->iFlags & MNG_FIELD_PUTIMGTYPE)
- {
- *(pChunkdata+pTempfield->iOffsetchunk) = iColortype;
- bProcess = MNG_FALSE;
- }
- else
- if (pTempfield->iFlags & MNG_FIELD_IFIMGTYPES)
- bProcess = (mng_bool)(((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE0) && (iColortype == 0)) ||
- ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE2) && (iColortype == 2)) ||
- ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE3) && (iColortype == 3)) ||
- ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE4) && (iColortype == 4)) ||
- ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE6) && (iColortype == 6)) );
- else
- bProcess = MNG_TRUE;
- if (bProcess)
- {
- iLastgroup = (mng_uint16)(pTempfield->iFlags & MNG_FIELD_GROUPMASK);
- /* numeric field ? */
- if (pTempfield->iFlags & MNG_FIELD_INT)
- {
- if (iTemplen < pTempfield->iLengthmax)
- MNG_ERROR (pData, MNG_INVALIDLENGTH);
- switch (pTempfield->iLengthmax)
- {
- case 1 : { mng_uint8 iNum = *pTempdata;
- if (((mng_uint16)iNum < pTempfield->iMinvalue) ||
- ((mng_uint16)iNum > pTempfield->iMaxvalue) )
- MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
- *(pChunkdata+pTempfield->iOffsetchunk) = iNum;
- break; }
- case 2 : { mng_uint16 iNum = mng_get_uint16 (pTempdata);
- if ((iNum < pTempfield->iMinvalue) || (iNum > pTempfield->iMaxvalue))
- MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
- *((mng_uint16p)(pChunkdata+pTempfield->iOffsetchunk)) = iNum;
- break; }
- case 4 : { mng_uint32 iNum = mng_get_uint32 (pTempdata);
- if ((iNum < pTempfield->iMinvalue) ||
- ((pTempfield->iFlags & MNG_FIELD_NOHIGHBIT) && (iNum & 0x80000000)) )
- MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
- *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunk)) = iNum;
- break; }
- }
- pTempdata += pTempfield->iLengthmax;
- iTemplen -= pTempfield->iLengthmax;
- } else { /* not numeric so it's a bunch of bytes */
- if (!pTempfield->iOffsetchunklen) /* big fat NONO */
- MNG_ERROR (pData, MNG_INTERNALERROR);
- /* with terminating 0 ? */
- if (pTempfield->iFlags & MNG_FIELD_TERMINATOR)
- {
- mng_uint8p pWork = pTempdata;
- while (*pWork) /* find the zero */
- pWork++;
- iDatalen = (mng_uint32)(pWork - pTempdata);
- } else { /* no terminator, so everything that's left ! */
- iDatalen = iTemplen;
- }
- if ((pTempfield->iLengthmax) && (iDatalen > pTempfield->iLengthmax))
- MNG_ERROR (pData, MNG_INVALIDLENGTH);
- #if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || \
- !defined(MNG_SKIPCHUNK_iTXt) || defined(MNG_INCLUDE_MPNG_PROPOSAL) || \
- defined(MNG_INCLUDE_ANG_PROPOSAL)
- /* needs decompression ? */
- if (pTempfield->iFlags & MNG_FIELD_DEFLATED)
- {
- mng_uint8p pBuf = 0;
- mng_uint32 iBufsize = 0;
- mng_uint32 iRealsize;
- mng_ptr pWork;
- iRetcode = mng_inflate_buffer (pData, pTempdata, iDatalen,
- &pBuf, &iBufsize, &iRealsize);
- #ifdef MNG_CHECK_BAD_ICCP /* Check for bad iCCP chunk */
- if ((iRetcode) && (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_iCCP))
- {
- *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk)) = MNG_NULL;
- *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iDatalen;
- }
- else
- #endif
- {
- if (iRetcode)
- return iRetcode;
- #if defined(MNG_INCLUDE_MPNG_PROPOSAL) || defined(MNG_INCLUDE_ANG_PROPOSAL)
- if ( (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_mpNG) ||
- (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_adAT) )
- {
- MNG_ALLOC (pData, pWork, iRealsize);
- }
- else
- {
- #endif
- /* don't forget to generate null terminator */
- MNG_ALLOC (pData, pWork, iRealsize+1);
- #if defined(MNG_INCLUDE_MPNG_PROPOSAL) || defined(MNG_INCLUDE_ANG_PROPOSAL)
- }
- #endif
- MNG_COPY (pWork, pBuf, iRealsize);
- *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk)) = pWork;
- *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iRealsize;
- }
- if (pBuf) /* free the temporary buffer */
- MNG_FREEX (pData, pBuf, iBufsize);
- } else
- #endif
- { /* no decompression, so just copy */
- mng_ptr pWork;
- /* don't forget to generate null terminator */
- MNG_ALLOC (pData, pWork, iDatalen+1);
- MNG_COPY (pWork, pTempdata, iDatalen);
- *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk)) = pWork;
- *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iDatalen;
- }
- if (pTempfield->iFlags & MNG_FIELD_TERMINATOR)
- iDatalen++; /* skip the terminating zero as well !!! */
- iTemplen -= iDatalen;
- pTempdata += iDatalen;
- }
- /* need to set an indicator ? */
- if (pTempfield->iOffsetchunkind)
- *((mng_uint8p)(pChunkdata+pTempfield->iOffsetchunkind)) = MNG_TRUE;
- }
- }
- if (pTempfield->pSpecialfunc) /* special function required ? */
- {
- iRetcode = pTempfield->pSpecialfunc(pData, *ppChunk, &iTemplen, &pTempdata);
- if (iRetcode) /* on error bail out */
- return iRetcode;
- }
- pTempfield++; /* Neeeeeeexxxtt */
- iFieldcount--;
- }
- if (iTemplen) /* extra data ??? */
- MNG_ERROR (pData, MNG_INVALIDLENGTH);
- while (iFieldcount) /* not enough data ??? */
- {
- if (pTempfield->iFlags & MNG_FIELD_IFIMGTYPES)
- bProcess = (mng_bool)(((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE0) && (iColortype == 0)) ||
- ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE2) && (iColortype == 2)) ||
- ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE3) && (iColortype == 3)) ||
- ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE4) && (iColortype == 4)) ||
- ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE6) && (iColortype == 6)) );
- else
- bProcess = MNG_TRUE;
- if (bProcess)
- {
- if (!(pTempfield->iFlags & MNG_FIELD_OPTIONAL))
- MNG_ERROR (pData, MNG_INVALIDLENGTH);
- if ((pTempfield->iFlags & MNG_FIELD_GROUPMASK) &&
- ((mng_uint16)(pTempfield->iFlags & MNG_FIELD_GROUPMASK) == iLastgroup))
- MNG_ERROR (pData, MNG_INVALIDLENGTH);
- }
- pTempfield++;
- iFieldcount--;
- }
- }
- }
- return MNG_NOERROR;
- }
- /* ************************************************************************** */
- READ_CHUNK (mng_read_general)
- {
- mng_retcode iRetcode = MNG_NOERROR;
- mng_chunk_descp pDescr = ((mng_chunk_headerp)pHeader)->pChunkdescr;
- mng_field_descp pField;
- mng_uint16 iFields;
- if (!pDescr) /* this is a bad booboo !!! */
- MNG_ERROR (pData, MNG_INTERNALERROR);
- pField = pDescr->pFielddesc;
- iFields = pDescr->iFielddesc;
- /* check chunk against signature */
- if ((pDescr->eImgtype == mng_it_mng) && (pData->eSigtype != mng_it_mng))
- MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
- if ((pDescr->eImgtype == mng_it_jng) && (pData->eSigtype == mng_it_png))
- MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
- /* empties allowed ? */
- if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTY)))
- MNG_ERROR (pData, MNG_INVALIDLENGTH);
- if ((pData->eImagetype != mng_it_mng) || (!(pDescr->iAllowed & MNG_DESCR_GLOBAL)))
- { /* *a* header required ? */
- if ((pDescr->iMusthaves & MNG_DESCR_GenHDR) &&
- #ifdef MNG_INCLUDE_JNG
- (!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
- #else
- (!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR))
- #endif
- MNG_ERROR (pData, MNG_SEQUENCEERROR);
- #ifdef MNG_INCLUDE_JNG
- if ((pDescr->iMusthaves & MNG_DESCR_JngHDR) &&
- (!pData->bHasDHDR) && (!pData->bHasJHDR))
- MNG_ERROR (pData, MNG_SEQUENCEERROR);
- #endif
- }
- /* specific chunk pre-requisite ? */
- if (((pDescr->iMusthaves & MNG_DESCR_IHDR) && (!pData->bHasIHDR)) ||
- #ifdef MNG_INCLUDE_JNG
- ((pDescr->iMusthaves & MNG_DESCR_JHDR) && (!pData->bHasJHDR)) ||
- #endif
- ((pDescr->iMusthaves & MNG_DESCR_DHDR) && (!pData->bHasDHDR)) ||
- ((pDescr->iMusthaves & MNG_DESCR_LOOP) && (!pData->bHasLOOP)) ||
- ((pDescr->iMusthaves & MNG_DESCR_PLTE) && (!pData->bHasPLTE)) ||
- ((pDescr->iMusthaves & MNG_DESCR_MHDR) && (!pData->bHasMHDR)) ||
- ((pDescr->iMusthaves & MNG_DESCR_SAVE) && (!pData->bHasSAVE)) )
- MNG_ERROR (pData, MNG_SEQUENCEERROR);
- /* specific chunk undesired ? */
- if (((pDescr->iMustNOThaves & MNG_DESCR_NOIHDR) && (pData->bHasIHDR)) ||
- ((pDescr->iMustNOThaves & MNG_DESCR_NOBASI) && (pData->bHasBASI)) ||
- ((pDescr->iMustNOThaves & MNG_DESCR_NODHDR) && (pData->bHasDHDR)) ||
- ((pDescr->iMustNOThaves & MNG_DESCR_NOIDAT) && (pData->bHasIDAT)) ||
- ((pDescr->iMustNOThaves & MNG_DESCR_NOPLTE) && (pData->bHasPLTE)) ||
- #ifdef MNG_INCLUDE_JNG
- ((pDescr->iMustNOThaves & MNG_DESCR_NOJHDR) && (pData->bHasJHDR)) ||
- ((pDescr->iMustNOThaves & MNG_DESCR_NOJDAT) && (pData->bHasJDAT)) ||
- ((pDescr->iMustNOThaves & MNG_DESCR_NOJDAA) && (pData->bHasJDAA)) ||
- ((pDescr->iMustNOThaves & MNG_DESCR_NOJSEP) && (pData->bHasJSEP)) ||
- #endif
- ((pDescr->iMustNOThaves & MNG_DESCR_NOMHDR) && (pData->bHasMHDR)) ||
- ((pDescr->iMustNOThaves & MNG_DESCR_NOLOOP) && (pData->bHasLOOP)) ||
- ((pDescr->iMustNOThaves & MNG_DESCR_NOTERM) && (pData->bHasTERM)) ||
- ((pDescr->iMustNOThaves & MNG_DESCR_NOSAVE) && (pData->bHasSAVE)) )
- MNG_ERROR (pData, MNG_SEQUENCEERROR);
- if (pData->eSigtype == mng_it_mng) /* check global and embedded empty chunks */
- {
- #ifdef MNG_INCLUDE_JNG
- if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
- #else
- if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
- #endif
- {
- if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTYEMBED)))
- MNG_ERROR (pData, MNG_INVALIDLENGTH);
- } else {
- if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTYGLOBAL)))
- MNG_ERROR (pData, MNG_INVALIDLENGTH);
- }
- }
- if (pDescr->pSpecialfunc) /* need special processing ? */
- {
- iRetcode = create_chunk_storage (pData, pHeader, iRawlen, pRawdata,
- pField, iFields, ppChunk, MNG_TRUE);
- if (iRetcode) /* on error bail out */
- return iRetcode;
- /* empty indicator ? */
- if ((!iRawlen) && (pDescr->iOffsetempty))
- *(((mng_uint8p)*ppChunk)+pDescr->iOffsetempty) = MNG_TRUE;
- iRetcode = pDescr->pSpecialfunc(pData, *ppChunk);
- if (iRetcode) /* on error bail out */
- return iRetcode;
- if ((((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT) ||
- (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT) ||
- (((mng_chunk_headerp)pHeader)->iChunkname == M…