/src/FreeImage/Source/LibMNG/libmng_chunk_io.c
C | 1459 lines | 942 code | 174 blank | 343 comment | 352 complexity | 7923962c84af202d068737fdfbf91ecd MD5 | raw file
Possible License(s): LGPL-3.0, BSD-3-Clause, CPL-1.0, Unlicense, GPL-2.0, GPL-3.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, BSD-2-Clause, LGPL-2.1
- /** ************************************************************************* */
- /* * 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 == MNG_UINT_JDAA) )
- {
- iRetcode = ((mng_chunk_headerp)*ppChunk)->fCleanup (pData, *ppChunk);
- if (iRetcode) /* on error bail out */
- return iRetcode;
- *ppChunk = MNG_NULL;
- } else {
- #ifdef MNG_STORE_CHUNKS
- if (!pData->bStorechunks)
- #endif
- {
- iRetcode = ((mng_chunk_headerp)*ppChunk)->fCleanup (pData, *ppChunk);
- if (iRetcode) /* on error bail out */
- return iRetcode;
- *ppChunk = MNG_NULL;
- }
- }
- }
- #ifdef MNG_SUPPORT_DISPLAY
- if (iRawlen)
- {
- #ifdef MNG_OPTIMIZE_DISPLAYCALLS
- pData->iRawlen = iRawlen;
- pData->pRawdata = pRawdata;
- #endif
- /* display processing */
- #ifndef MNG_OPTIMIZE_DISPLAYCALLS
- if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT)
- iRetcode = mng_process_display_idat (pData, iRawlen, pRawdata);
- #ifdef MNG_INCLUDE_JNG
- else
- if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT)
- iRetcode = mng_process_display_jdat (pData, iRawlen, pRawdata);
- else
- if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAA)
- iRetcode = mng_process_display_jdaa (pData, iRawlen, pRawdata);
- #endif
- #else
- if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT)
- iRetcode = mng_process_display_idat (pData);
- #ifdef MNG_INCLUDE_JNG
- else
- if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT)
- iRetcode = mng_process_display_jdat (pData);
- else
- if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAA)
- iRetcode = mng_process_display_jdaa (pData);
- #endif
- #endif
- if (iRetcode)
- return iRetcode;
- }
- #endif /* MNG_SUPPORT_DISPLAY */
- #ifdef MNG_STORE_CHUNKS
- if ((pData->bStorechunks) && (!(*ppChunk)))
- {
- iRetcode = create_chunk_storage (pData, pHeader, iRawlen, pRawdata,
- pField, iFields, ppChunk, MNG_FALSE);
- if (iRetcode) /* on error bail out */
- return iRetcode;
- /* empty indicator ? */
- if ((!iRawlen) && (pDescr->iOffsetempty))
- *(((mng_uint8p)*ppChunk)+pDescr->iOffsetempty) = MNG_TRUE;
- }
- #endif /* MNG_STORE_CHUNKS */
- return MNG_NOERROR;
- }
- /* ************************************************************************** */
- #endif /* MNG_OPTIMIZE_CHUNKREADER */
- /* ************************************************************************** */
- #ifndef MNG_OPTIMIZE_CHUNKREADER
- READ_CHUNK (mng_read_ihdr)
- {
- #ifdef MNG_SUPPORT_TRACE
- MNG_TRACE (pData, MNG_FN_READ_IHDR, MNG_LC_START);
- #endif
- if (iRawlen != 13) /* length oke ? */
- MNG_ERROR (pData, MNG_INVALIDLENGTH);
- /* only allowed inside PNG or MNG */
- if ((pData->eSigtype != mng_it_png) && (pData->eSigtype != mng_it_mng))
- MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
- /* sequence checks */
- if ((pData->eSigtype == mng_it_png) && (pData->iChunkseq > 1))
- MNG_ERROR (pData, MNG_SEQUENCEERROR);
- #ifdef MNG_INCLUDE_JNG
- if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasIDAT) || (pData->bHasJHDR))
- #else
- if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasIDAT))
- #endif
- MNG_ERROR (pData, MNG_SEQUENCEERROR);
- pData->bHasIHDR = MNG_TRUE; /* indicate IHDR is present */
- /* and store interesting fields */
- if ((!pData->bHasDHDR) || (pData->iDeltatype == MNG_DELTATYPE_NOCHANGE))
- {
- pData->iDatawidth = mng_get_uint32 (pRawdata);
- pData->iDataheight = mng_get_uint32 (pRawdata+4);
- }
- pData->iBitdepth = *(pRawdata+8);
- pData->iColortype = *(pRawdata+9);
- pData->iCompression = *(pRawdata+10);
- pData->iFilter = *(pRawdata+11);
- pData->iInterlace = *(pRawdata+12);
- #if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
- pData->iPNGmult = 1;
- pData->iPNGdepth = pData->iBitdepth;
- #endif
- #ifdef MNG_NO_1_2_4BIT_SUPPORT
- if (pData->iBitdepth < 8)
- pData->iBitdepth = 8;
- #endif
- #ifdef MNG_NO_16BIT_SUPPORT
- if (pData->iBitdepth > 8)
- {
- pData->iBitdepth = 8;
- pData->iPNGmult = 2;
- }
- #endif
- if ((pData->iBitdepth != 8) /* parameter validity checks */
- #ifndef MNG_NO_1_2_4BIT_SUPPORT
- && (pData->iBitdepth != 1) &&
- (pData->iBitdepth != 2) &&
- (pData->iBitdepth != 4)
- #endif
- #ifndef MNG_NO_16BIT_SUPPORT
- && (pData->iBitdepth != 16)
- #endif
- )
- MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
- if ((pData->iColortype != MNG_COLORTYPE_GRAY ) &&
- (pData->iColortype != MNG_COLORTYPE_RGB ) &&
- (pData->iColortype != MNG_COLORTYPE_INDEXED) &&
- (pData->iColortype != MNG_COLORTYPE_GRAYA ) &&
- (pData->iColortype != MNG_COLORTYPE_RGBA ) )
- MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
- if ((pData->iColortype == MNG_COLORTYPE_INDEXED) && (pData->iBitdepth > 8))
- MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
- if (((pData->iColortype == MNG_COLORTYPE_RGB ) ||
- (pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
- (pData->iColortype == MNG_COLORTYPE_RGBA ) ) &&
- (pData->iBitdepth < 8 ) )
- MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
- if (pData->iCompression != MNG_COMPRESSION_DEFLATE)
- MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
- #if defined(FILTER192) || defined(FILTER193)
- if ((pData->iFilter != MNG_FILTER_ADAPTIVE ) &&
- #if defined(FILTER192) && defined(FILTER193)
- (pData->iFilter != MNG_FILTER_DIFFERING) &&
- (pData->iFilter != MNG_FILTER_NOFILTER ) )
- #else
- #ifdef FILTER192
- (pData->iFilter != MNG_FILTER_DIFFERING) )
- #else
- (pData->iFilter != MNG_FILTER_NOFILTER ) )
- #endif
- #endif
- MNG_ERROR (pData, MNG_INVALIDFILTER);
- #else
- if (pData->iFilter)
- MNG_ERROR (pData, MNG_INVALIDFILTER);
- #endif
- if ((pData->iInterlace != MNG_INTERLACE_NONE ) &&
- (pData->iInterlace != MNG_INTERLACE_ADAM7) )
- MNG_ERROR (pData, MNG_INVALIDINTERLACE);
- #ifdef MNG_SUPPORT_DISPLAY
- #ifndef MNG_NO_DELTA_PNG
- if (pData->bHasDHDR) /* check the colortype for delta-images ! */
- {
- mng_imagedatap pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
- if (pData->iColortype != pBuf->iColortype)
- {
- if ( ( (pData->iColortype != MNG_COLORTYPE_INDEXED) ||
- (pBuf->iColortype == MNG_COLORTYPE_GRAY ) ) &&
- ( (pData->iColortype != MNG_COLORTYPE_GRAY ) ||
- (pBuf->iColortype == MNG_COLORTYPE_INDEXED) ) )
- MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
- }
- }
- #endif
- #endif
- if (!pData->bHasheader) /* first chunk ? */
- {
- pData->bHasheader = MNG_TRUE; /* we've got a header */
- pData->eImagetype = mng_it_png; /* then this must be a PNG */
- pData->iWidth = pData->iDatawidth;
- pData->iHeight = pData->iDataheight;
- /* predict alpha-depth ! */
- if ((pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
- (pData->iColortype == MNG_COLORTYPE_RGBA ) )
- pData->iAlphadepth = pData->iBitdepth;
- else
- if (pData->iColortype == MNG_COLORTYPE_INDEXED)
- pData->iAlphadepth = 8; /* worst case scenario */
- else
- pData->iAlphadepth = 1; /* Possible tRNS cheap binary transparency */
- /* fits on maximum canvas ? */
- if ((pData->iWidth > pData->iMaxwidth) || (pData->iHeight > pData->iMaxheight))
- MNG_WARNING (pData, MNG_IMAGETOOLARGE);
- #if !defined(MNG_INCLUDE_MPNG_PROPOSAL) || !defined(MNG_SUPPORT_DISPLAY)
- if (pData->fProcessheader) /* inform the app ? */
- if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
- MNG_ERROR (pData, MNG_APPMISCERROR);
- #endif
- }
- if (!pData->bHasDHDR)
- pData->iImagelevel++; /* one level deeper */
- #ifdef MNG_SUPPORT_DISPLAY
- {
- mng_retcode iRetcode = mng_process_display_ihdr (pData);
- if (iRetcode) /* on error bail out */
- return iRetcode;
- }
- #endif /* MNG_SUPPORT_DISPLAY */
- #ifdef MNG_STORE_CHUNKS
- if (pData->bStorechunks)
- { /* initialize storage */
- mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
- if (iRetcode) /* on error bail out */
- return iRetcode;
- /* fill the fields */
- ((mng_ihdrp)*ppChunk)->iWidth = mng_get_uint32 (pRawdata);
- ((mng_ihdrp)*ppChunk)->iHeight = mng_get_uint32 (pRawdata+4);
- ((mng_ihdrp)*ppChunk)->iBitdepth = pData->iBitdepth;
- ((mng_ihdrp)*ppChunk)->iColortype = pData->iColortype;
- ((mng_ihdrp)*ppChunk)->iCompression = pData->iCompression;
- ((mng_ihdrp)*ppChunk)->iFilter = pData->iFilter;
- ((mng_ihdrp)*ppChunk)->iInterlace = pData->iInterlace;
- }
- #endif /* MNG_STORE_CHUNKS */
- #ifdef MNG_SUPPORT_TRACE
- MNG_TRACE (pData, MNG_FN_READ_IHDR, MNG_LC_END);
- #endif
- return MNG_NOERROR; /* done */
- }
- #endif /* MNG_OPTIMIZE_CHUNKREADER */
- /* ************************************************************************** */
- #ifndef MNG_OPTIMIZE_CHUNKREADER
- READ_CHUNK (mng_read_plte)
- {
- #if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
- mng_uint32 iX;
- mng_uint8p pRawdata2;
- #endif
- #ifdef MNG_SUPPORT_DISPLAY
- mng_uint32 iRawlen2;
- #endif
- #ifdef MNG_SUPPORT_TRACE
- MNG_TRACE (pData, MNG_FN_READ_PLTE, MNG_LC_START);
- #endif
- /* sequence checks */
- if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
- (!pData->bHasBASI) && (!pData->bHasDHDR) )
- MNG_ERROR (pData, MNG_SEQUENCEERROR);
- #ifdef MNG_INCLUDE_JNG
- if ((pData->bHasIDAT) || (pData->bHasJHDR))
- #else
- if (pData->bHasIDAT)
- #endif
- MNG_ERROR (pData, MNG_SEQUENCEERROR);
- /* multiple PLTE only inside BASI */
- if ((pData->bHasPLTE) && (!pData->bHasBASI))
- MNG_ERROR (pData, MNG_MULTIPLEERROR);
- /* length must be multiple of 3 */
- if (((iRawlen % 3) != 0) || (iRawlen > 768))
- MNG_ERROR (pData, MNG_INVALIDLENGTH);
- if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
- { /* only allowed for indexed-color or
- rgb(a)-color! */
- if ((pData->iColortype != 2) && (pData->iColortype != 3) && (pData->iColortype != 6))
- MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
- /* empty only allowed if global present */
- if ((iRawlen == 0) && (!pData->bHasglobalPLTE))
- MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
- }
- else
- {
- if (iRawlen == 0) /* cannot be empty as global! */
- MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
- }
- if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
- pData->bHasPLTE = MNG_TRUE; /* got it! */
- else
- pData->bHasglobalPLTE = MNG_TRUE;
- pData->iPLTEcount = iRawlen / 3;
- #ifdef MNG_SUPPORT_DISPLAY
- if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
- {
- mng_imagep pImage;
- mng_imagedatap pBuf;
- #ifndef MNG_NO_DELTA_PNG
- if (pData->bHasDHDR) /* processing delta-image ? */
- { /* store in object 0 !!! */
- pImage = (mng_imagep)pData->pObjzero;
- pBuf = pImage->pImgbuf;
- pBuf->bHasPLTE = MNG_TRUE; /* it's definitely got a PLTE now */
- pBuf->iPLTEcount = iRawlen / 3; /* this is the exact length */
- pRawdata2 = pRawdata; /* copy the entries */
- for (iX = 0; iX < iRawlen / 3; iX++)
- {
- pBuf->aPLTEentries[iX].iRed = *pRawdata2;
- pBuf->aPLTEentries[iX].iGreen = *(pRawdata2+1);
- pBuf->aPLTEentries[iX].iBlue = *(pRawdata2+2);
- pRawdata2 += 3;
- }
- }
- else
- #endif
- { /* get the current object */
- pImage = (mng_imagep)pData->pCurrentobj;
- if (!pImage) /* no object then dump it in obj 0 */
- pImage = (mng_imagep)pData->pObjzero;
- pBuf = pImage->pImgbuf; /* address the object buffer */
- pBuf->bHasPLTE = MNG_TRUE; /* and tell it it's got a PLTE now */
- if (!iRawlen) /* if empty, inherit from global */
- {
- pBuf->iPLTEcount = pData->iGlobalPLTEcount;
- MNG_COPY (pBuf->aPLTEentries, pData->aGlobalPLTEentries,
- sizeof (pBuf->aPLTEentries));
- if (pData->bHasglobalTRNS) /* also copy global tRNS ? */
- { /* indicate tRNS available */
- pBuf->bHasTRNS = MNG_TRUE;
- iRawlen2 = pData->iGlobalTRNSrawlen;
- pRawdata2 = (mng_uint8p)(pData->aGlobalTRNSrawdata);
- /* global length oke ? */
- if ((iRawlen2 == 0) || (iRawlen2 > pBuf->iPLTEcount))
- MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
- /* copy it */
- pBuf->iTRNScount = iRawlen2;
- MNG_COPY (pBuf->aTRNSentries, pRawdata2, iRawlen2);
- }
- }
- else
- { /* store fields for future reference */
- pBuf->iPLTEcount = iRawlen / 3;
- pRawdata2 = pRawdata;
- for (iX = 0; iX < pBuf->iPLTEcount; iX++)
- {
- pBuf->aPLTEentries[iX].iRed = *pRawdata2;
- pBuf->aPLTEentries[iX].iGreen = *(pRawdata2+1);
- pBuf->aPLTEentries[iX].iBlue = *(pRawdata2+2);
- pRawdata2 += 3;
- }
- }
- }
- }
- else /* store as global */
- {
- pData->iGlobalPLTEcount = iRawlen / 3;
- pRawdata2 = pRawdata;
- for (iX = 0; iX < pData->iGlobalPLTEcount; iX++)
- {
- pData->aGlobalPLTEentries[iX].iRed = *pRawdata2;
- pData->aGlobalPLTEentries[iX].iGreen = *(pRawdata2+1);
- pData->aGlobalPLTEentries[iX].iBlue = *(pRawdata2+2);
- pRawdata2 += 3;
- }
- { /* create an animation object */
- mng_retcode iRetcode = mng_create_ani_plte (pData, pData->iGlobalPLTEcount,
- pData->aGlobalPLTEentries);
- if (iRetcode) /* on error bail out */
- return iRetcode;
- }
- }
- #endif /* MNG_SUPPORT_DISPLAY */
- #ifdef MNG_STORE_CHUNKS
- if (pData->bStorechunks)
- { /* initialize storage */
- mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
- if (iRetcode) /* on error bail out */
- return iRetcode;
- /* store the fields */
- ((mng_pltep)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
- ((mng_pltep)*ppChunk)->iEntrycount = iRawlen / 3;
- pRawdata2 = pRawdata;
- for (iX = 0; iX < ((mng_pltep)*ppChunk)->iEntrycount; iX++)
- {
- ((mng_pltep)*ppChunk)->aEntries[iX].iRed = *pRawdata2;
- ((mng_pltep)*ppChunk)->aEntries[iX].iGreen = *(pRawdata2+1);
- ((mng_pltep)*ppChunk)->aEntries[iX].iBlue = *(pRawdata2+2);
- pRawdata2 += 3;
- }
- }
- #endif /* MNG_STORE_CHUNKS */
- #ifdef MNG_SUPPORT_TRACE
- MNG_TRACE (pData, MNG_FN_READ_PLTE, MNG_LC_END);
- #endif
- return MNG_NOERROR; /* done */
- }
- #endif /* MNG_OPTIMIZE_CHUNKREADER */
- /* *******************