PageRenderTime 54ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/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
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
  1. /** ************************************************************************* */
  2. /* * For conditions of distribution and use, * */
  3. /* * see copyright notice in libmng.h * */
  4. /* ************************************************************************** */
  5. /* * * */
  6. /* * project : libmng * */
  7. /* * file : libmng_chunk_io.c copyright (c) 2000-2007 G.Juyn * */
  8. /* * version : 1.0.10 * */
  9. /* * * */
  10. /* * purpose : Chunk I/O routines (implementation) * */
  11. /* * * */
  12. /* * author : G.Juyn * */
  13. /* * * */
  14. /* * comment : implementation of chunk input/output routines * */
  15. /* * * */
  16. /* * changes : 0.5.1 - 05/01/2000 - G.Juyn * */
  17. /* * - cleaned up left-over teststuff in the BACK chunk routine * */
  18. /* * 0.5.1 - 05/04/2000 - G.Juyn * */
  19. /* * - changed CRC initialization to use dynamic structure * */
  20. /* * (wasn't thread-safe the old way !) * */
  21. /* * 0.5.1 - 05/06/2000 - G.Juyn * */
  22. /* * - filled in many missing sequence&length checks * */
  23. /* * - filled in many missing chunk-store snippets * */
  24. /* * 0.5.1 - 05/08/2000 - G.Juyn * */
  25. /* * - added checks for running animations * */
  26. /* * - filled some write routines * */
  27. /* * - changed strict-ANSI stuff * */
  28. /* * 0.5.1 - 05/10/2000 - G.Juyn * */
  29. /* * - filled some more write routines * */
  30. /* * 0.5.1 - 05/11/2000 - G.Juyn * */
  31. /* * - filled remaining write routines * */
  32. /* * - fixed read_pplt with regard to deltatype * */
  33. /* * - added callback error-reporting support * */
  34. /* * - added pre-draft48 support (short MHDR, frame_mode, LOOP) * */
  35. /* * 0.5.1 - 05/12/2000 - G.Juyn * */
  36. /* * - changed trace to macro for callback error-reporting * */
  37. /* * - fixed chunk-storage bit in several routines * */
  38. /* * 0.5.1 - 05/13/2000 - G.Juyn * */
  39. /* * - added eMNGma hack (will be removed in 1.0.0 !!!) * */
  40. /* * - added TERM animation object pointer (easier reference) * */
  41. /* * - supplemented the SAVE & SEEK display processing * */
  42. /* * * */
  43. /* * 0.5.2 - 05/18/2000 - G.Juyn * */
  44. /* * - B004 - fixed problem with MNG_SUPPORT_WRITE not defined * */
  45. /* * also for MNG_SUPPORT_WRITE without MNG_INCLUDE_JNG * */
  46. /* * 0.5.2 - 05/19/2000 - G.Juyn * */
  47. /* * - cleaned up some code regarding mixed support * */
  48. /* * 0.5.2 - 05/20/2000 - G.Juyn * */
  49. /* * - implemented JNG support * */
  50. /* * 0.5.2 - 05/24/2000 - G.Juyn * */
  51. /* * - added support for global color-chunks in animation * */
  52. /* * - added support for global PLTE,tRNS,bKGD in animation * */
  53. /* * - added support for SAVE & SEEK in animation * */
  54. /* * 0.5.2 - 05/29/2000 - G.Juyn * */
  55. /* * - changed ani_create calls not returning object pointer * */
  56. /* * - create ani objects always (not just inside TERM/LOOP) * */
  57. /* * 0.5.2 - 05/30/2000 - G.Juyn * */
  58. /* * - added support for delta-image processing * */
  59. /* * 0.5.2 - 05/31/2000 - G.Juyn * */
  60. /* * - fixed up punctuation (contributed by Tim Rowley) * */
  61. /* * 0.5.2 - 06/02/2000 - G.Juyn * */
  62. /* * - changed SWAP_ENDIAN to BIGENDIAN_SUPPORTED * */
  63. /* * 0.5.2 - 06/03/2000 - G.Juyn * */
  64. /* * - fixed makeup for Linux gcc compile * */
  65. /* * * */
  66. /* * 0.5.3 - 06/12/2000 - G.Juyn * */
  67. /* * - added processing of color-info on delta-image * */
  68. /* * 0.5.3 - 06/13/2000 - G.Juyn * */
  69. /* * - fixed handling of empty SAVE chunk * */
  70. /* * 0.5.3 - 06/17/2000 - G.Juyn * */
  71. /* * - changed to support delta-images * */
  72. /* * - added extra checks for delta-images * */
  73. /* * 0.5.3 - 06/20/2000 - G.Juyn * */
  74. /* * - fixed possible trouble if IEND display-process got * */
  75. /* * broken up * */
  76. /* * 0.5.3 - 06/21/2000 - G.Juyn * */
  77. /* * - added processing of PLTE & tRNS for delta-images * */
  78. /* * - added administration of imagelevel parameter * */
  79. /* * 0.5.3 - 06/22/2000 - G.Juyn * */
  80. /* * - implemented support for PPLT chunk * */
  81. /* * 0.5.3 - 06/26/2000 - G.Juyn * */
  82. /* * - added precaution against faulty iCCP chunks from PS * */
  83. /* * 0.5.3 - 06/29/2000 - G.Juyn * */
  84. /* * - fixed some 64-bit warnings * */
  85. /* * * */
  86. /* * 0.9.1 - 07/14/2000 - G.Juyn * */
  87. /* * - changed pre-draft48 frame_mode=3 to frame_mode=1 * */
  88. /* * 0.9.1 - 07/16/2000 - G.Juyn * */
  89. /* * - fixed storage of images during mng_read() * */
  90. /* * - fixed support for mng_display() after mng_read() * */
  91. /* * 0.9.1 - 07/19/2000 - G.Juyn * */
  92. /* * - fixed several chunk-writing routines * */
  93. /* * 0.9.1 - 07/24/2000 - G.Juyn * */
  94. /* * - fixed reading of still-images * */
  95. /* * * */
  96. /* * 0.9.2 - 08/05/2000 - G.Juyn * */
  97. /* * - changed file-prefixes * */
  98. /* * * */
  99. /* * 0.9.3 - 08/07/2000 - G.Juyn * */
  100. /* * - B111300 - fixup for improved portability * */
  101. /* * 0.9.3 - 08/08/2000 - G.Juyn * */
  102. /* * - fixed compiler-warnings from Mozilla * */
  103. /* * 0.9.3 - 08/09/2000 - G.Juyn * */
  104. /* * - added check for simplicity-bits in MHDR * */
  105. /* * 0.9.3 - 08/12/2000 - G.Juyn * */
  106. /* * - fixed check for simplicity-bits in MHDR (JNG) * */
  107. /* * 0.9.3 - 08/12/2000 - G.Juyn * */
  108. /* * - added workaround for faulty PhotoShop iCCP chunk * */
  109. /* * 0.9.3 - 08/22/2000 - G.Juyn * */
  110. /* * - fixed write-code for zTXt & iTXt * */
  111. /* * - fixed read-code for iTXt * */
  112. /* * 0.9.3 - 08/26/2000 - G.Juyn * */
  113. /* * - added MAGN chunk * */
  114. /* * 0.9.3 - 09/07/2000 - G.Juyn * */
  115. /* * - added support for new filter_types * */
  116. /* * 0.9.3 - 09/10/2000 - G.Juyn * */
  117. /* * - fixed DEFI behavior * */
  118. /* * 0.9.3 - 10/02/2000 - G.Juyn * */
  119. /* * - fixed simplicity-check in compliance with draft 81/0.98a * */
  120. /* * 0.9.3 - 10/10/2000 - G.Juyn * */
  121. /* * - added support for alpha-depth prediction * */
  122. /* * 0.9.3 - 10/11/2000 - G.Juyn * */
  123. /* * - added support for nEED * */
  124. /* * 0.9.3 - 10/16/2000 - G.Juyn * */
  125. /* * - added support for JDAA * */
  126. /* * 0.9.3 - 10/17/2000 - G.Juyn * */
  127. /* * - fixed support for MAGN * */
  128. /* * - implemented nEED "xxxx" (where "xxxx" is a chunkid) * */
  129. /* * - added callback to process non-critical unknown chunks * */
  130. /* * - fixed support for bKGD * */
  131. /* * 0.9.3 - 10/23/2000 - G.Juyn * */
  132. /* * - fixed bug in empty PLTE handling * */
  133. /* * * */
  134. /* * 0.9.4 - 11/20/2000 - G.Juyn * */
  135. /* * - changed IHDR filter_method check for PNGs * */
  136. /* * 0.9.4 - 1/18/2001 - G.Juyn * */
  137. /* * - added errorchecking for MAGN methods * */
  138. /* * - removed test filter-methods 1 & 65 * */
  139. /* * * */
  140. /* * 0.9.5 - 1/25/2001 - G.Juyn * */
  141. /* * - fixed some small compiler warnings (thanks Nikki) * */
  142. /* * * */
  143. /* * 1.0.2 - 05/05/2000 - G.Juyn * */
  144. /* * - B421427 - writes wrong format in bKGD and tRNS * */
  145. /* * 1.0.2 - 06/20/2000 - G.Juyn * */
  146. /* * - B434583 - compiler-warning if MNG_STORE_CHUNKS undefined * */
  147. /* * * */
  148. /* * 1.0.5 - 07/08/2002 - G.Juyn * */
  149. /* * - B578572 - removed eMNGma hack (thanks Dimitri!) * */
  150. /* * 1.0.5 - 08/07/2002 - G.Juyn * */
  151. /* * - added test-option for PNG filter method 193 (=no filter) * */
  152. /* * 1.0.5 - 08/15/2002 - G.Juyn * */
  153. /* * - completed PROM support * */
  154. /* * 1.0.5 - 08/19/2002 - G.Juyn * */
  155. /* * - B597134 - libmng pollutes the linker namespace * */
  156. /* * 1.0.5 - 09/07/2002 - G.Juyn * */
  157. /* * - fixed reading of FRAM with just frame_mode and name * */
  158. /* * 1.0.5 - 09/13/2002 - G.Juyn * */
  159. /* * - fixed read/write of MAGN chunk * */
  160. /* * 1.0.5 - 09/14/2002 - G.Juyn * */
  161. /* * - added event handling for dynamic MNG * */
  162. /* * 1.0.5 - 09/15/2002 - G.Juyn * */
  163. /* * - fixed LOOP iteration=0 special case * */
  164. /* * 1.0.5 - 09/19/2002 - G.Juyn * */
  165. /* * - misplaced TERM is now treated as warning * */
  166. /* * 1.0.5 - 09/20/2002 - G.Juyn * */
  167. /* * - added support for PAST * */
  168. /* * 1.0.5 - 10/03/2002 - G.Juyn * */
  169. /* * - fixed chunk-storage for evNT chunk * */
  170. /* * 1.0.5 - 10/07/2002 - G.Juyn * */
  171. /* * - fixed DISC support * */
  172. /* * - added another fix for misplaced TERM chunk * */
  173. /* * 1.0.5 - 10/17/2002 - G.Juyn * */
  174. /* * - fixed initializtion of pIds in dISC read routine * */
  175. /* * 1.0.5 - 11/06/2002 - G.Juyn * */
  176. /* * - added support for nEED "MNG 1.1" * */
  177. /* * - added support for nEED "CACHEOFF" * */
  178. /* * * */
  179. /* * 1.0.6 - 05/25/2003 - G.R-P * */
  180. /* * - added MNG_SKIPCHUNK_cHNK footprint optimizations * */
  181. /* * 1.0.6 - 06/02/2003 - G.R-P * */
  182. /* * - removed some redundant checks for iRawlen==0 * */
  183. /* * 1.0.6 - 06/22/2003 - G.R-P * */
  184. /* * - added MNG_NO_16BIT_SUPPORT, MNG_NO_DELTA_PNG reductions * */
  185. /* * - optionally use zlib's crc32 function instead of * */
  186. /* * local mng_update_crc * */
  187. /* * 1.0.6 - 07/14/2003 - G.R-P * */
  188. /* * - added MNG_NO_LOOP_SIGNALS_SUPPORTED conditional * */
  189. /* * 1.0.6 - 07/29/2003 - G.R-P * */
  190. /* * - added conditionals around PAST chunk support * */
  191. /* * 1.0.6 - 08/17/2003 - G.R-P * */
  192. /* * - added conditionals around non-VLC chunk support * */
  193. /* * * */
  194. /* * 1.0.7 - 10/29/2003 - G.R-P * */
  195. /* * - revised JDAA and JDAT readers to avoid compiler bug * */
  196. /* * 1.0.7 - 01/25/2004 - J.S * */
  197. /* * - added premultiplied alpha canvas' for RGBA, ARGB, ABGR * */
  198. /* * 1.0.7 - 01/27/2004 - J.S * */
  199. /* * - fixed inclusion of IJNG chunk for non-JNG use * */
  200. /* * 1.0.7 - 02/26/2004 - G.Juyn * */
  201. /* * - fixed bug in chunk-storage of SHOW chunk (from == to) * */
  202. /* * * */
  203. /* * 1.0.8 - 04/02/2004 - G.Juyn * */
  204. /* * - added CRC existence & checking flags * */
  205. /* * 1.0.8 - 07/07/2004 - G.R-P * */
  206. /* * - change worst-case iAlphadepth to 1 for standalone PNGs * */
  207. /* * * */
  208. /* * 1.0.9 - 09/28/2004 - G.R-P * */
  209. /* * - improved handling of cheap transparency when 16-bit * */
  210. /* * support is disabled * */
  211. /* * 1.0.9 - 10/04/2004 - G.Juyn * */
  212. /* * - fixed bug in writing sBIT for indexed color * */
  213. /* * 1.0.9 - 10/10/2004 - G.R-P. * */
  214. /* * - added MNG_NO_1_2_4BIT_SUPPORT * */
  215. /* * 1.0.9 - 12/05/2004 - G.Juyn * */
  216. /* * - added conditional MNG_OPTIMIZE_CHUNKINITFREE * */
  217. /* * 1.0.9 - 12/06/2004 - G.Juyn * */
  218. /* * - added conditional MNG_OPTIMIZE_CHUNKASSIGN * */
  219. /* * 1.0.9 - 12/07/2004 - G.Juyn * */
  220. /* * - added conditional MNG_OPTIMIZE_CHUNKREADER * */
  221. /* * 1.0.9 - 12/11/2004 - G.Juyn * */
  222. /* * - added conditional MNG_OPTIMIZE_DISPLAYCALLS * */
  223. /* * 1.0.9 - 12/20/2004 - G.Juyn * */
  224. /* * - cleaned up macro-invocations (thanks to D. Airlie) * */
  225. /* * 1.0.9 - 01/17/2005 - G.Juyn * */
  226. /* * - fixed problem with global PLTE/tRNS * */
  227. /* * * */
  228. /* * 1.0.10 - 02/07/2005 - G.Juyn * */
  229. /* * - fixed display routines called twice for FULL_MNG * */
  230. /* * support in mozlibmngconf.h * */
  231. /* * 1.0.10 - 12/04/2005 - G.R-P. * */
  232. /* * - #ifdef out use of mng_inflate_buffer when it is not * */
  233. /* * available. * */
  234. /* * 1.0.10 - 04/08/2007 - G.Juyn * */
  235. /* * - added support for mPNG proposal * */
  236. /* * 1.0.10 - 04/12/2007 - G.Juyn * */
  237. /* * - added support for ANG proposal * */
  238. /* * 1.0.10 - 05/02/2007 - G.Juyn * */
  239. /* * - fixed inflate_buffer for extreme compression ratios * */
  240. /* * * */
  241. /* ************************************************************************** */
  242. #include "libmng.h"
  243. #include "libmng_data.h"
  244. #include "libmng_error.h"
  245. #include "libmng_trace.h"
  246. #ifdef __BORLANDC__
  247. #pragma hdrstop
  248. #endif
  249. #include "libmng_objects.h"
  250. #include "libmng_object_prc.h"
  251. #include "libmng_chunks.h"
  252. #ifdef MNG_CHECK_BAD_ICCP
  253. #include "libmng_chunk_prc.h"
  254. #endif
  255. #include "libmng_memory.h"
  256. #include "libmng_display.h"
  257. #include "libmng_zlib.h"
  258. #include "libmng_pixels.h"
  259. #include "libmng_chunk_io.h"
  260. #if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
  261. #pragma option -A /* force ANSI-C */
  262. #endif
  263. /* ************************************************************************** */
  264. /* * * */
  265. /* * CRC - Cyclic Redundancy Check * */
  266. /* * * */
  267. /* * The code below is taken directly from the sample provided with the * */
  268. /* * PNG specification. * */
  269. /* * (it is only adapted to the library's internal data-definitions) * */
  270. /* * * */
  271. /* ************************************************************************** */
  272. /* Make the table for a fast CRC. */
  273. #ifndef MNG_USE_ZLIB_CRC
  274. MNG_LOCAL void make_crc_table (mng_datap pData)
  275. {
  276. mng_uint32 iC;
  277. mng_int32 iN, iK;
  278. for (iN = 0; iN < 256; iN++)
  279. {
  280. iC = (mng_uint32) iN;
  281. for (iK = 0; iK < 8; iK++)
  282. {
  283. if (iC & 1)
  284. iC = 0xedb88320U ^ (iC >> 1);
  285. else
  286. iC = iC >> 1;
  287. }
  288. pData->aCRCtable [iN] = iC;
  289. }
  290. pData->bCRCcomputed = MNG_TRUE;
  291. }
  292. #endif
  293. /* Update a running CRC with the bytes buf[0..len-1]--the CRC
  294. should be initialized to all 1's, and the transmitted value
  295. is the 1's complement of the final running CRC (see the
  296. crc() routine below). */
  297. MNG_LOCAL mng_uint32 update_crc (mng_datap pData,
  298. mng_uint32 iCrc,
  299. mng_uint8p pBuf,
  300. mng_int32 iLen)
  301. {
  302. #ifdef MNG_USE_ZLIB_CRC
  303. return crc32 (iCrc, pBuf, iLen);
  304. #else
  305. mng_uint32 iC = iCrc;
  306. mng_int32 iN;
  307. if (!pData->bCRCcomputed)
  308. make_crc_table (pData);
  309. for (iN = 0; iN < iLen; iN++)
  310. iC = pData->aCRCtable [(iC ^ pBuf [iN]) & 0xff] ^ (iC >> 8);
  311. return iC;
  312. #endif
  313. }
  314. /* Return the CRC of the bytes buf[0..len-1]. */
  315. mng_uint32 mng_crc (mng_datap pData,
  316. mng_uint8p pBuf,
  317. mng_int32 iLen)
  318. {
  319. #ifdef MNG_USE_ZLIB_CRC
  320. return update_crc (pData, 0, pBuf, iLen);
  321. #else
  322. return update_crc (pData, 0xffffffffU, pBuf, iLen) ^ 0xffffffffU;
  323. #endif
  324. }
  325. /* ************************************************************************** */
  326. /* * * */
  327. /* * Routines for swapping byte-order from and to graphic files * */
  328. /* * (This code is adapted from the libpng package) * */
  329. /* * * */
  330. /* ************************************************************************** */
  331. #ifndef MNG_BIGENDIAN_SUPPORTED
  332. /* ************************************************************************** */
  333. mng_uint32 mng_get_uint32 (mng_uint8p pBuf)
  334. {
  335. mng_uint32 i = ((mng_uint32)(*pBuf) << 24) +
  336. ((mng_uint32)(*(pBuf + 1)) << 16) +
  337. ((mng_uint32)(*(pBuf + 2)) << 8) +
  338. (mng_uint32)(*(pBuf + 3));
  339. return (i);
  340. }
  341. /* ************************************************************************** */
  342. mng_int32 mng_get_int32 (mng_uint8p pBuf)
  343. {
  344. mng_int32 i = ((mng_int32)(*pBuf) << 24) +
  345. ((mng_int32)(*(pBuf + 1)) << 16) +
  346. ((mng_int32)(*(pBuf + 2)) << 8) +
  347. (mng_int32)(*(pBuf + 3));
  348. return (i);
  349. }
  350. /* ************************************************************************** */
  351. mng_uint16 mng_get_uint16 (mng_uint8p pBuf)
  352. {
  353. mng_uint16 i = (mng_uint16)(((mng_uint16)(*pBuf) << 8) +
  354. (mng_uint16)(*(pBuf + 1)));
  355. return (i);
  356. }
  357. /* ************************************************************************** */
  358. void mng_put_uint32 (mng_uint8p pBuf,
  359. mng_uint32 i)
  360. {
  361. *pBuf = (mng_uint8)((i >> 24) & 0xff);
  362. *(pBuf+1) = (mng_uint8)((i >> 16) & 0xff);
  363. *(pBuf+2) = (mng_uint8)((i >> 8) & 0xff);
  364. *(pBuf+3) = (mng_uint8)(i & 0xff);
  365. }
  366. /* ************************************************************************** */
  367. void mng_put_int32 (mng_uint8p pBuf,
  368. mng_int32 i)
  369. {
  370. *pBuf = (mng_uint8)((i >> 24) & 0xff);
  371. *(pBuf+1) = (mng_uint8)((i >> 16) & 0xff);
  372. *(pBuf+2) = (mng_uint8)((i >> 8) & 0xff);
  373. *(pBuf+3) = (mng_uint8)(i & 0xff);
  374. }
  375. /* ************************************************************************** */
  376. void mng_put_uint16 (mng_uint8p pBuf,
  377. mng_uint16 i)
  378. {
  379. *pBuf = (mng_uint8)((i >> 8) & 0xff);
  380. *(pBuf+1) = (mng_uint8)(i & 0xff);
  381. }
  382. /* ************************************************************************** */
  383. #endif /* !MNG_BIGENDIAN_SUPPORTED */
  384. /* ************************************************************************** */
  385. /* * * */
  386. /* * Helper routines to simplify chunk-data extraction * */
  387. /* * * */
  388. /* ************************************************************************** */
  389. #ifdef MNG_INCLUDE_READ_PROCS
  390. /* ************************************************************************** */
  391. #ifndef MNG_OPTIMIZE_CHUNKREADER
  392. MNG_LOCAL mng_uint8p find_null (mng_uint8p pIn)
  393. {
  394. mng_uint8p pOut = pIn;
  395. while (*pOut) /* the read_graphic routine has made sure there's */
  396. pOut++; /* always at least 1 zero-byte in the buffer */
  397. return pOut;
  398. }
  399. #endif
  400. /* ************************************************************************** */
  401. #if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || \
  402. !defined(MNG_SKIPCHUNK_iTXt) || defined(MNG_INCLUDE_MPNG_PROPOSAL) || \
  403. defined(MNG_INCLUDE_ANG_PROPOSAL)
  404. mng_retcode mng_inflate_buffer (mng_datap pData,
  405. mng_uint8p pInbuf,
  406. mng_uint32 iInsize,
  407. mng_uint8p *pOutbuf,
  408. mng_uint32 *iOutsize,
  409. mng_uint32 *iRealsize)
  410. {
  411. mng_retcode iRetcode = MNG_NOERROR;
  412. #ifdef MNG_SUPPORT_TRACE
  413. MNG_TRACE (pData, MNG_FN_INFLATE_BUFFER, MNG_LC_START);
  414. #endif
  415. if (iInsize) /* anything to do ? */
  416. {
  417. *iOutsize = iInsize * 3; /* estimate uncompressed size */
  418. /* and allocate a temporary buffer */
  419. MNG_ALLOC (pData, *pOutbuf, *iOutsize);
  420. do
  421. {
  422. mngzlib_inflateinit (pData); /* initialize zlib */
  423. /* let zlib know where to store the output */
  424. pData->sZlib.next_out = *pOutbuf;
  425. /* "size - 1" so we've got space for the
  426. zero-termination of a possible string */
  427. pData->sZlib.avail_out = *iOutsize - 1;
  428. /* ok; let's inflate... */
  429. iRetcode = mngzlib_inflatedata (pData, iInsize, pInbuf);
  430. /* determine actual output size */
  431. *iRealsize = (mng_uint32)pData->sZlib.total_out;
  432. mngzlib_inflatefree (pData); /* zlib's done */
  433. if (iRetcode == MNG_BUFOVERFLOW) /* not enough space ? */
  434. { /* then get some more */
  435. MNG_FREEX (pData, *pOutbuf, *iOutsize);
  436. *iOutsize = *iOutsize + *iOutsize;
  437. MNG_ALLOC (pData, *pOutbuf, *iOutsize);
  438. }
  439. } /* repeat if we didn't have enough space */
  440. while ((iRetcode == MNG_BUFOVERFLOW) &&
  441. (*iOutsize < 200 * iInsize));
  442. if (!iRetcode) /* if oke ? */
  443. *((*pOutbuf) + *iRealsize) = 0; /* then put terminator zero */
  444. }
  445. else
  446. {
  447. *pOutbuf = 0; /* nothing to do; then there's no output */
  448. *iOutsize = 0;
  449. *iRealsize = 0;
  450. }
  451. #ifdef MNG_SUPPORT_TRACE
  452. MNG_TRACE (pData, MNG_FN_INFLATE_BUFFER, MNG_LC_END);
  453. #endif
  454. return iRetcode;
  455. }
  456. #endif
  457. /* ************************************************************************** */
  458. #endif /* MNG_INCLUDE_READ_PROCS */
  459. /* ************************************************************************** */
  460. /* * * */
  461. /* * Helper routines to simplify chunk writing * */
  462. /* * * */
  463. /* ************************************************************************** */
  464. #ifdef MNG_INCLUDE_WRITE_PROCS
  465. /* ************************************************************************** */
  466. #if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || !defined(MNG_SKIPCHUNK_iTXt)
  467. MNG_LOCAL mng_retcode deflate_buffer (mng_datap pData,
  468. mng_uint8p pInbuf,
  469. mng_uint32 iInsize,
  470. mng_uint8p *pOutbuf,
  471. mng_uint32 *iOutsize,
  472. mng_uint32 *iRealsize)
  473. {
  474. mng_retcode iRetcode = MNG_NOERROR;
  475. #ifdef MNG_SUPPORT_TRACE
  476. MNG_TRACE (pData, MNG_FN_DEFLATE_BUFFER, MNG_LC_START);
  477. #endif
  478. if (iInsize) /* anything to do ? */
  479. {
  480. *iOutsize = (iInsize * 5) >> 2; /* estimate compressed size */
  481. /* and allocate a temporary buffer */
  482. MNG_ALLOC (pData, *pOutbuf, *iOutsize);
  483. do
  484. {
  485. mngzlib_deflateinit (pData); /* initialize zlib */
  486. /* let zlib know where to store the output */
  487. pData->sZlib.next_out = *pOutbuf;
  488. pData->sZlib.avail_out = *iOutsize;
  489. /* ok; let's deflate... */
  490. iRetcode = mngzlib_deflatedata (pData, iInsize, pInbuf);
  491. /* determine actual output size */
  492. *iRealsize = pData->sZlib.total_out;
  493. mngzlib_deflatefree (pData); /* zlib's done */
  494. if (iRetcode == MNG_BUFOVERFLOW) /* not enough space ? */
  495. { /* then get some more */
  496. MNG_FREEX (pData, *pOutbuf, *iOutsize);
  497. *iOutsize = *iOutsize + (iInsize >> 1);
  498. MNG_ALLOC (pData, *pOutbuf, *iOutsize);
  499. }
  500. } /* repeat if we didn't have enough space */
  501. while (iRetcode == MNG_BUFOVERFLOW);
  502. }
  503. else
  504. {
  505. *pOutbuf = 0; /* nothing to do; then there's no output */
  506. *iOutsize = 0;
  507. *iRealsize = 0;
  508. }
  509. #ifdef MNG_SUPPORT_TRACE
  510. MNG_TRACE (pData, MNG_FN_DEFLATE_BUFFER, MNG_LC_END);
  511. #endif
  512. return iRetcode;
  513. }
  514. #endif
  515. /* ************************************************************************** */
  516. MNG_LOCAL mng_retcode write_raw_chunk (mng_datap pData,
  517. mng_chunkid iChunkname,
  518. mng_uint32 iRawlen,
  519. mng_uint8p pRawdata)
  520. {
  521. mng_uint32 iCrc;
  522. mng_uint32 iWritten;
  523. #ifdef MNG_SUPPORT_TRACE
  524. MNG_TRACE (pData, MNG_FN_WRITE_RAW_CHUNK, MNG_LC_START);
  525. #endif
  526. /* temporary buffer ? */
  527. if ((pRawdata != 0) && (pRawdata != pData->pWritebuf+8))
  528. { /* store length & chunktype in default buffer */
  529. mng_put_uint32 (pData->pWritebuf, iRawlen);
  530. mng_put_uint32 (pData->pWritebuf+4, (mng_uint32)iChunkname);
  531. if (pData->iCrcmode & MNG_CRC_OUTPUT)
  532. {
  533. if ((pData->iCrcmode & MNG_CRC_OUTPUT) == MNG_CRC_OUTPUT_GENERATE)
  534. { /* calculate the crc */
  535. iCrc = update_crc (pData, 0xffffffffL, pData->pWritebuf+4, 4);
  536. iCrc = update_crc (pData, iCrc, pRawdata, iRawlen) ^ 0xffffffffL;
  537. } else {
  538. iCrc = 0; /* dummy crc */
  539. } /* store in default buffer */
  540. mng_put_uint32 (pData->pWritebuf+8, iCrc);
  541. }
  542. /* write the length & chunktype */
  543. if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, 8, &iWritten))
  544. MNG_ERROR (pData, MNG_APPIOERROR);
  545. if (iWritten != 8) /* disk full ? */
  546. MNG_ERROR (pData, MNG_OUTPUTERROR);
  547. /* write the temporary buffer */
  548. if (!pData->fWritedata ((mng_handle)pData, pRawdata, iRawlen, &iWritten))
  549. MNG_ERROR (pData, MNG_APPIOERROR);
  550. if (iWritten != iRawlen) /* disk full ? */
  551. MNG_ERROR (pData, MNG_OUTPUTERROR);
  552. if (pData->iCrcmode & MNG_CRC_OUTPUT)
  553. { /* write the crc */
  554. if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf+8, 4, &iWritten))
  555. MNG_ERROR (pData, MNG_APPIOERROR);
  556. if (iWritten != 4) /* disk full ? */
  557. MNG_ERROR (pData, MNG_OUTPUTERROR);
  558. }
  559. }
  560. else
  561. { /* prefix with length & chunktype */
  562. mng_put_uint32 (pData->pWritebuf, iRawlen);
  563. mng_put_uint32 (pData->pWritebuf+4, (mng_uint32)iChunkname);
  564. if (pData->iCrcmode & MNG_CRC_OUTPUT)
  565. {
  566. if ((pData->iCrcmode & MNG_CRC_OUTPUT) == MNG_CRC_OUTPUT_GENERATE)
  567. /* calculate the crc */
  568. iCrc = mng_crc (pData, pData->pWritebuf+4, iRawlen + 4);
  569. else
  570. iCrc = 0; /* dummy crc */
  571. /* add it to the buffer */
  572. mng_put_uint32 (pData->pWritebuf + iRawlen + 8, iCrc);
  573. /* write it in a single pass */
  574. if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, iRawlen + 12, &iWritten))
  575. MNG_ERROR (pData, MNG_APPIOERROR);
  576. if (iWritten != iRawlen + 12) /* disk full ? */
  577. MNG_ERROR (pData, MNG_OUTPUTERROR);
  578. } else {
  579. if (!pData->fWritedata ((mng_handle)pData, pData->pWritebuf, iRawlen + 8, &iWritten))
  580. MNG_ERROR (pData, MNG_APPIOERROR);
  581. if (iWritten != iRawlen + 8) /* disk full ? */
  582. MNG_ERROR (pData, MNG_OUTPUTERROR);
  583. }
  584. }
  585. #ifdef MNG_SUPPORT_TRACE
  586. MNG_TRACE (pData, MNG_FN_WRITE_RAW_CHUNK, MNG_LC_END);
  587. #endif
  588. return MNG_NOERROR;
  589. }
  590. /* ************************************************************************** */
  591. /* B004 */
  592. #endif /* MNG_INCLUDE_WRITE_PROCS */
  593. /* B004 */
  594. /* ************************************************************************** */
  595. /* * * */
  596. /* * chunk read functions * */
  597. /* * * */
  598. /* ************************************************************************** */
  599. #ifdef MNG_INCLUDE_READ_PROCS
  600. /* ************************************************************************** */
  601. #ifdef MNG_OPTIMIZE_CHUNKREADER
  602. /* ************************************************************************** */
  603. MNG_LOCAL mng_retcode create_chunk_storage (mng_datap pData,
  604. mng_chunkp pHeader,
  605. mng_uint32 iRawlen,
  606. mng_uint8p pRawdata,
  607. mng_field_descp pField,
  608. mng_uint16 iFields,
  609. mng_chunkp* ppChunk,
  610. mng_bool bWorkcopy)
  611. {
  612. mng_field_descp pTempfield = pField;
  613. mng_uint16 iFieldcount = iFields;
  614. mng_uint8p pTempdata = pRawdata;
  615. mng_uint32 iTemplen = iRawlen;
  616. mng_uint16 iLastgroup = 0;
  617. mng_uint8p pChunkdata;
  618. mng_uint32 iDatalen;
  619. mng_uint8 iColortype;
  620. mng_bool bProcess;
  621. /* initialize storage */
  622. mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
  623. if (iRetcode) /* on error bail out */
  624. return iRetcode;
  625. if (((mng_chunk_headerp)(*ppChunk))->iChunkname == MNG_UINT_HUH)
  626. ((mng_chunk_headerp)(*ppChunk))->iChunkname = pData->iChunkname;
  627. if ((!bWorkcopy) ||
  628. ((((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_IDAT) &&
  629. (((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_JDAT) &&
  630. (((mng_chunk_headerp)pHeader)->iChunkname != MNG_UINT_JDAA) ))
  631. {
  632. pChunkdata = (mng_uint8p)(*ppChunk);
  633. #ifdef MNG_INCLUDE_JNG /* determine current colortype */
  634. if (pData->bHasJHDR)
  635. iColortype = (mng_uint8)(pData->iJHDRcolortype - 8);
  636. else
  637. #endif /* MNG_INCLUDE_JNG */
  638. if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
  639. iColortype = pData->iColortype;
  640. else
  641. iColortype = 6;
  642. if (iTemplen) /* not empty ? */
  643. { /* then go fill the fields */
  644. while ((iFieldcount) && (iTemplen))
  645. {
  646. if (pTempfield->iOffsetchunk)
  647. {
  648. if (pTempfield->iFlags & MNG_FIELD_PUTIMGTYPE)
  649. {
  650. *(pChunkdata+pTempfield->iOffsetchunk) = iColortype;
  651. bProcess = MNG_FALSE;
  652. }
  653. else
  654. if (pTempfield->iFlags & MNG_FIELD_IFIMGTYPES)
  655. bProcess = (mng_bool)(((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE0) && (iColortype == 0)) ||
  656. ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE2) && (iColortype == 2)) ||
  657. ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE3) && (iColortype == 3)) ||
  658. ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE4) && (iColortype == 4)) ||
  659. ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE6) && (iColortype == 6)) );
  660. else
  661. bProcess = MNG_TRUE;
  662. if (bProcess)
  663. {
  664. iLastgroup = (mng_uint16)(pTempfield->iFlags & MNG_FIELD_GROUPMASK);
  665. /* numeric field ? */
  666. if (pTempfield->iFlags & MNG_FIELD_INT)
  667. {
  668. if (iTemplen < pTempfield->iLengthmax)
  669. MNG_ERROR (pData, MNG_INVALIDLENGTH);
  670. switch (pTempfield->iLengthmax)
  671. {
  672. case 1 : { mng_uint8 iNum = *pTempdata;
  673. if (((mng_uint16)iNum < pTempfield->iMinvalue) ||
  674. ((mng_uint16)iNum > pTempfield->iMaxvalue) )
  675. MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
  676. *(pChunkdata+pTempfield->iOffsetchunk) = iNum;
  677. break; }
  678. case 2 : { mng_uint16 iNum = mng_get_uint16 (pTempdata);
  679. if ((iNum < pTempfield->iMinvalue) || (iNum > pTempfield->iMaxvalue))
  680. MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
  681. *((mng_uint16p)(pChunkdata+pTempfield->iOffsetchunk)) = iNum;
  682. break; }
  683. case 4 : { mng_uint32 iNum = mng_get_uint32 (pTempdata);
  684. if ((iNum < pTempfield->iMinvalue) ||
  685. ((pTempfield->iFlags & MNG_FIELD_NOHIGHBIT) && (iNum & 0x80000000)) )
  686. MNG_ERROR (pData, MNG_INVALIDFIELDVAL);
  687. *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunk)) = iNum;
  688. break; }
  689. }
  690. pTempdata += pTempfield->iLengthmax;
  691. iTemplen -= pTempfield->iLengthmax;
  692. } else { /* not numeric so it's a bunch of bytes */
  693. if (!pTempfield->iOffsetchunklen) /* big fat NONO */
  694. MNG_ERROR (pData, MNG_INTERNALERROR);
  695. /* with terminating 0 ? */
  696. if (pTempfield->iFlags & MNG_FIELD_TERMINATOR)
  697. {
  698. mng_uint8p pWork = pTempdata;
  699. while (*pWork) /* find the zero */
  700. pWork++;
  701. iDatalen = (mng_uint32)(pWork - pTempdata);
  702. } else { /* no terminator, so everything that's left ! */
  703. iDatalen = iTemplen;
  704. }
  705. if ((pTempfield->iLengthmax) && (iDatalen > pTempfield->iLengthmax))
  706. MNG_ERROR (pData, MNG_INVALIDLENGTH);
  707. #if !defined(MNG_SKIPCHUNK_iCCP) || !defined(MNG_SKIPCHUNK_zTXt) || \
  708. !defined(MNG_SKIPCHUNK_iTXt) || defined(MNG_INCLUDE_MPNG_PROPOSAL) || \
  709. defined(MNG_INCLUDE_ANG_PROPOSAL)
  710. /* needs decompression ? */
  711. if (pTempfield->iFlags & MNG_FIELD_DEFLATED)
  712. {
  713. mng_uint8p pBuf = 0;
  714. mng_uint32 iBufsize = 0;
  715. mng_uint32 iRealsize;
  716. mng_ptr pWork;
  717. iRetcode = mng_inflate_buffer (pData, pTempdata, iDatalen,
  718. &pBuf, &iBufsize, &iRealsize);
  719. #ifdef MNG_CHECK_BAD_ICCP /* Check for bad iCCP chunk */
  720. if ((iRetcode) && (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_iCCP))
  721. {
  722. *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk)) = MNG_NULL;
  723. *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iDatalen;
  724. }
  725. else
  726. #endif
  727. {
  728. if (iRetcode)
  729. return iRetcode;
  730. #if defined(MNG_INCLUDE_MPNG_PROPOSAL) || defined(MNG_INCLUDE_ANG_PROPOSAL)
  731. if ( (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_mpNG) ||
  732. (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_adAT) )
  733. {
  734. MNG_ALLOC (pData, pWork, iRealsize);
  735. }
  736. else
  737. {
  738. #endif
  739. /* don't forget to generate null terminator */
  740. MNG_ALLOC (pData, pWork, iRealsize+1);
  741. #if defined(MNG_INCLUDE_MPNG_PROPOSAL) || defined(MNG_INCLUDE_ANG_PROPOSAL)
  742. }
  743. #endif
  744. MNG_COPY (pWork, pBuf, iRealsize);
  745. *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk)) = pWork;
  746. *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iRealsize;
  747. }
  748. if (pBuf) /* free the temporary buffer */
  749. MNG_FREEX (pData, pBuf, iBufsize);
  750. } else
  751. #endif
  752. { /* no decompression, so just copy */
  753. mng_ptr pWork;
  754. /* don't forget to generate null terminator */
  755. MNG_ALLOC (pData, pWork, iDatalen+1);
  756. MNG_COPY (pWork, pTempdata, iDatalen);
  757. *((mng_ptr *)(pChunkdata+pTempfield->iOffsetchunk)) = pWork;
  758. *((mng_uint32p)(pChunkdata+pTempfield->iOffsetchunklen)) = iDatalen;
  759. }
  760. if (pTempfield->iFlags & MNG_FIELD_TERMINATOR)
  761. iDatalen++; /* skip the terminating zero as well !!! */
  762. iTemplen -= iDatalen;
  763. pTempdata += iDatalen;
  764. }
  765. /* need to set an indicator ? */
  766. if (pTempfield->iOffsetchunkind)
  767. *((mng_uint8p)(pChunkdata+pTempfield->iOffsetchunkind)) = MNG_TRUE;
  768. }
  769. }
  770. if (pTempfield->pSpecialfunc) /* special function required ? */
  771. {
  772. iRetcode = pTempfield->pSpecialfunc(pData, *ppChunk, &iTemplen, &pTempdata);
  773. if (iRetcode) /* on error bail out */
  774. return iRetcode;
  775. }
  776. pTempfield++; /* Neeeeeeexxxtt */
  777. iFieldcount--;
  778. }
  779. if (iTemplen) /* extra data ??? */
  780. MNG_ERROR (pData, MNG_INVALIDLENGTH);
  781. while (iFieldcount) /* not enough data ??? */
  782. {
  783. if (pTempfield->iFlags & MNG_FIELD_IFIMGTYPES)
  784. bProcess = (mng_bool)(((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE0) && (iColortype == 0)) ||
  785. ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE2) && (iColortype == 2)) ||
  786. ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE3) && (iColortype == 3)) ||
  787. ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE4) && (iColortype == 4)) ||
  788. ((pTempfield->iFlags & MNG_FIELD_IFIMGTYPE6) && (iColortype == 6)) );
  789. else
  790. bProcess = MNG_TRUE;
  791. if (bProcess)
  792. {
  793. if (!(pTempfield->iFlags & MNG_FIELD_OPTIONAL))
  794. MNG_ERROR (pData, MNG_INVALIDLENGTH);
  795. if ((pTempfield->iFlags & MNG_FIELD_GROUPMASK) &&
  796. ((mng_uint16)(pTempfield->iFlags & MNG_FIELD_GROUPMASK) == iLastgroup))
  797. MNG_ERROR (pData, MNG_INVALIDLENGTH);
  798. }
  799. pTempfield++;
  800. iFieldcount--;
  801. }
  802. }
  803. }
  804. return MNG_NOERROR;
  805. }
  806. /* ************************************************************************** */
  807. READ_CHUNK (mng_read_general)
  808. {
  809. mng_retcode iRetcode = MNG_NOERROR;
  810. mng_chunk_descp pDescr = ((mng_chunk_headerp)pHeader)->pChunkdescr;
  811. mng_field_descp pField;
  812. mng_uint16 iFields;
  813. if (!pDescr) /* this is a bad booboo !!! */
  814. MNG_ERROR (pData, MNG_INTERNALERROR);
  815. pField = pDescr->pFielddesc;
  816. iFields = pDescr->iFielddesc;
  817. /* check chunk against signature */
  818. if ((pDescr->eImgtype == mng_it_mng) && (pData->eSigtype != mng_it_mng))
  819. MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
  820. if ((pDescr->eImgtype == mng_it_jng) && (pData->eSigtype == mng_it_png))
  821. MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
  822. /* empties allowed ? */
  823. if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTY)))
  824. MNG_ERROR (pData, MNG_INVALIDLENGTH);
  825. if ((pData->eImagetype != mng_it_mng) || (!(pDescr->iAllowed & MNG_DESCR_GLOBAL)))
  826. { /* *a* header required ? */
  827. if ((pDescr->iMusthaves & MNG_DESCR_GenHDR) &&
  828. #ifdef MNG_INCLUDE_JNG
  829. (!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR) && (!pData->bHasJHDR))
  830. #else
  831. (!pData->bHasIHDR) && (!pData->bHasBASI) && (!pData->bHasDHDR))
  832. #endif
  833. MNG_ERROR (pData, MNG_SEQUENCEERROR);
  834. #ifdef MNG_INCLUDE_JNG
  835. if ((pDescr->iMusthaves & MNG_DESCR_JngHDR) &&
  836. (!pData->bHasDHDR) && (!pData->bHasJHDR))
  837. MNG_ERROR (pData, MNG_SEQUENCEERROR);
  838. #endif
  839. }
  840. /* specific chunk pre-requisite ? */
  841. if (((pDescr->iMusthaves & MNG_DESCR_IHDR) && (!pData->bHasIHDR)) ||
  842. #ifdef MNG_INCLUDE_JNG
  843. ((pDescr->iMusthaves & MNG_DESCR_JHDR) && (!pData->bHasJHDR)) ||
  844. #endif
  845. ((pDescr->iMusthaves & MNG_DESCR_DHDR) && (!pData->bHasDHDR)) ||
  846. ((pDescr->iMusthaves & MNG_DESCR_LOOP) && (!pData->bHasLOOP)) ||
  847. ((pDescr->iMusthaves & MNG_DESCR_PLTE) && (!pData->bHasPLTE)) ||
  848. ((pDescr->iMusthaves & MNG_DESCR_MHDR) && (!pData->bHasMHDR)) ||
  849. ((pDescr->iMusthaves & MNG_DESCR_SAVE) && (!pData->bHasSAVE)) )
  850. MNG_ERROR (pData, MNG_SEQUENCEERROR);
  851. /* specific chunk undesired ? */
  852. if (((pDescr->iMustNOThaves & MNG_DESCR_NOIHDR) && (pData->bHasIHDR)) ||
  853. ((pDescr->iMustNOThaves & MNG_DESCR_NOBASI) && (pData->bHasBASI)) ||
  854. ((pDescr->iMustNOThaves & MNG_DESCR_NODHDR) && (pData->bHasDHDR)) ||
  855. ((pDescr->iMustNOThaves & MNG_DESCR_NOIDAT) && (pData->bHasIDAT)) ||
  856. ((pDescr->iMustNOThaves & MNG_DESCR_NOPLTE) && (pData->bHasPLTE)) ||
  857. #ifdef MNG_INCLUDE_JNG
  858. ((pDescr->iMustNOThaves & MNG_DESCR_NOJHDR) && (pData->bHasJHDR)) ||
  859. ((pDescr->iMustNOThaves & MNG_DESCR_NOJDAT) && (pData->bHasJDAT)) ||
  860. ((pDescr->iMustNOThaves & MNG_DESCR_NOJDAA) && (pData->bHasJDAA)) ||
  861. ((pDescr->iMustNOThaves & MNG_DESCR_NOJSEP) && (pData->bHasJSEP)) ||
  862. #endif
  863. ((pDescr->iMustNOThaves & MNG_DESCR_NOMHDR) && (pData->bHasMHDR)) ||
  864. ((pDescr->iMustNOThaves & MNG_DESCR_NOLOOP) && (pData->bHasLOOP)) ||
  865. ((pDescr->iMustNOThaves & MNG_DESCR_NOTERM) && (pData->bHasTERM)) ||
  866. ((pDescr->iMustNOThaves & MNG_DESCR_NOSAVE) && (pData->bHasSAVE)) )
  867. MNG_ERROR (pData, MNG_SEQUENCEERROR);
  868. if (pData->eSigtype == mng_it_mng) /* check global and embedded empty chunks */
  869. {
  870. #ifdef MNG_INCLUDE_JNG
  871. if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR) || (pData->bHasJHDR))
  872. #else
  873. if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
  874. #endif
  875. {
  876. if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTYEMBED)))
  877. MNG_ERROR (pData, MNG_INVALIDLENGTH);
  878. } else {
  879. if ((iRawlen == 0) && (!(pDescr->iAllowed & MNG_DESCR_EMPTYGLOBAL)))
  880. MNG_ERROR (pData, MNG_INVALIDLENGTH);
  881. }
  882. }
  883. if (pDescr->pSpecialfunc) /* need special processing ? */
  884. {
  885. iRetcode = create_chunk_storage (pData, pHeader, iRawlen, pRawdata,
  886. pField, iFields, ppChunk, MNG_TRUE);
  887. if (iRetcode) /* on error bail out */
  888. return iRetcode;
  889. /* empty indicator ? */
  890. if ((!iRawlen) && (pDescr->iOffsetempty))
  891. *(((mng_uint8p)*ppChunk)+pDescr->iOffsetempty) = MNG_TRUE;
  892. iRetcode = pDescr->pSpecialfunc(pData, *ppChunk);
  893. if (iRetcode) /* on error bail out */
  894. return iRetcode;
  895. if ((((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT) ||
  896. (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT) ||
  897. (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAA) )
  898. {
  899. iRetcode = ((mng_chunk_headerp)*ppChunk)->fCleanup (pData, *ppChunk);
  900. if (iRetcode) /* on error bail out */
  901. return iRetcode;
  902. *ppChunk = MNG_NULL;
  903. } else {
  904. #ifdef MNG_STORE_CHUNKS
  905. if (!pData->bStorechunks)
  906. #endif
  907. {
  908. iRetcode = ((mng_chunk_headerp)*ppChunk)->fCleanup (pData, *ppChunk);
  909. if (iRetcode) /* on error bail out */
  910. return iRetcode;
  911. *ppChunk = MNG_NULL;
  912. }
  913. }
  914. }
  915. #ifdef MNG_SUPPORT_DISPLAY
  916. if (iRawlen)
  917. {
  918. #ifdef MNG_OPTIMIZE_DISPLAYCALLS
  919. pData->iRawlen = iRawlen;
  920. pData->pRawdata = pRawdata;
  921. #endif
  922. /* display processing */
  923. #ifndef MNG_OPTIMIZE_DISPLAYCALLS
  924. if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT)
  925. iRetcode = mng_process_display_idat (pData, iRawlen, pRawdata);
  926. #ifdef MNG_INCLUDE_JNG
  927. else
  928. if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT)
  929. iRetcode = mng_process_display_jdat (pData, iRawlen, pRawdata);
  930. else
  931. if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAA)
  932. iRetcode = mng_process_display_jdaa (pData, iRawlen, pRawdata);
  933. #endif
  934. #else
  935. if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_IDAT)
  936. iRetcode = mng_process_display_idat (pData);
  937. #ifdef MNG_INCLUDE_JNG
  938. else
  939. if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAT)
  940. iRetcode = mng_process_display_jdat (pData);
  941. else
  942. if (((mng_chunk_headerp)pHeader)->iChunkname == MNG_UINT_JDAA)
  943. iRetcode = mng_process_display_jdaa (pData);
  944. #endif
  945. #endif
  946. if (iRetcode)
  947. return iRetcode;
  948. }
  949. #endif /* MNG_SUPPORT_DISPLAY */
  950. #ifdef MNG_STORE_CHUNKS
  951. if ((pData->bStorechunks) && (!(*ppChunk)))
  952. {
  953. iRetcode = create_chunk_storage (pData, pHeader, iRawlen, pRawdata,
  954. pField, iFields, ppChunk, MNG_FALSE);
  955. if (iRetcode) /* on error bail out */
  956. return iRetcode;
  957. /* empty indicator ? */
  958. if ((!iRawlen) && (pDescr->iOffsetempty))
  959. *(((mng_uint8p)*ppChunk)+pDescr->iOffsetempty) = MNG_TRUE;
  960. }
  961. #endif /* MNG_STORE_CHUNKS */
  962. return MNG_NOERROR;
  963. }
  964. /* ************************************************************************** */
  965. #endif /* MNG_OPTIMIZE_CHUNKREADER */
  966. /* ************************************************************************** */
  967. #ifndef MNG_OPTIMIZE_CHUNKREADER
  968. READ_CHUNK (mng_read_ihdr)
  969. {
  970. #ifdef MNG_SUPPORT_TRACE
  971. MNG_TRACE (pData, MNG_FN_READ_IHDR, MNG_LC_START);
  972. #endif
  973. if (iRawlen != 13) /* length oke ? */
  974. MNG_ERROR (pData, MNG_INVALIDLENGTH);
  975. /* only allowed inside PNG or MNG */
  976. if ((pData->eSigtype != mng_it_png) && (pData->eSigtype != mng_it_mng))
  977. MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
  978. /* sequence checks */
  979. if ((pData->eSigtype == mng_it_png) && (pData->iChunkseq > 1))
  980. MNG_ERROR (pData, MNG_SEQUENCEERROR);
  981. #ifdef MNG_INCLUDE_JNG
  982. if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasIDAT) || (pData->bHasJHDR))
  983. #else
  984. if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasIDAT))
  985. #endif
  986. MNG_ERROR (pData, MNG_SEQUENCEERROR);
  987. pData->bHasIHDR = MNG_TRUE; /* indicate IHDR is present */
  988. /* and store interesting fields */
  989. if ((!pData->bHasDHDR) || (pData->iDeltatype == MNG_DELTATYPE_NOCHANGE))
  990. {
  991. pData->iDatawidth = mng_get_uint32 (pRawdata);
  992. pData->iDataheight = mng_get_uint32 (pRawdata+4);
  993. }
  994. pData->iBitdepth = *(pRawdata+8);
  995. pData->iColortype = *(pRawdata+9);
  996. pData->iCompression = *(pRawdata+10);
  997. pData->iFilter = *(pRawdata+11);
  998. pData->iInterlace = *(pRawdata+12);
  999. #if defined(MNG_NO_1_2_4BIT_SUPPORT) || defined(MNG_NO_16BIT_SUPPORT)
  1000. pData->iPNGmult = 1;
  1001. pData->iPNGdepth = pData->iBitdepth;
  1002. #endif
  1003. #ifdef MNG_NO_1_2_4BIT_SUPPORT
  1004. if (pData->iBitdepth < 8)
  1005. pData->iBitdepth = 8;
  1006. #endif
  1007. #ifdef MNG_NO_16BIT_SUPPORT
  1008. if (pData->iBitdepth > 8)
  1009. {
  1010. pData->iBitdepth = 8;
  1011. pData->iPNGmult = 2;
  1012. }
  1013. #endif
  1014. if ((pData->iBitdepth != 8) /* parameter validity checks */
  1015. #ifndef MNG_NO_1_2_4BIT_SUPPORT
  1016. && (pData->iBitdepth != 1) &&
  1017. (pData->iBitdepth != 2) &&
  1018. (pData->iBitdepth != 4)
  1019. #endif
  1020. #ifndef MNG_NO_16BIT_SUPPORT
  1021. && (pData->iBitdepth != 16)
  1022. #endif
  1023. )
  1024. MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
  1025. if ((pData->iColortype != MNG_COLORTYPE_GRAY ) &&
  1026. (pData->iColortype != MNG_COLORTYPE_RGB ) &&
  1027. (pData->iColortype != MNG_COLORTYPE_INDEXED) &&
  1028. (pData->iColortype != MNG_COLORTYPE_GRAYA ) &&
  1029. (pData->iColortype != MNG_COLORTYPE_RGBA ) )
  1030. MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
  1031. if ((pData->iColortype == MNG_COLORTYPE_INDEXED) && (pData->iBitdepth > 8))
  1032. MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
  1033. if (((pData->iColortype == MNG_COLORTYPE_RGB ) ||
  1034. (pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
  1035. (pData->iColortype == MNG_COLORTYPE_RGBA ) ) &&
  1036. (pData->iBitdepth < 8 ) )
  1037. MNG_ERROR (pData, MNG_INVALIDBITDEPTH);
  1038. if (pData->iCompression != MNG_COMPRESSION_DEFLATE)
  1039. MNG_ERROR (pData, MNG_INVALIDCOMPRESS);
  1040. #if defined(FILTER192) || defined(FILTER193)
  1041. if ((pData->iFilter != MNG_FILTER_ADAPTIVE ) &&
  1042. #if defined(FILTER192) && defined(FILTER193)
  1043. (pData->iFilter != MNG_FILTER_DIFFERING) &&
  1044. (pData->iFilter != MNG_FILTER_NOFILTER ) )
  1045. #else
  1046. #ifdef FILTER192
  1047. (pData->iFilter != MNG_FILTER_DIFFERING) )
  1048. #else
  1049. (pData->iFilter != MNG_FILTER_NOFILTER ) )
  1050. #endif
  1051. #endif
  1052. MNG_ERROR (pData, MNG_INVALIDFILTER);
  1053. #else
  1054. if (pData->iFilter)
  1055. MNG_ERROR (pData, MNG_INVALIDFILTER);
  1056. #endif
  1057. if ((pData->iInterlace != MNG_INTERLACE_NONE ) &&
  1058. (pData->iInterlace != MNG_INTERLACE_ADAM7) )
  1059. MNG_ERROR (pData, MNG_INVALIDINTERLACE);
  1060. #ifdef MNG_SUPPORT_DISPLAY
  1061. #ifndef MNG_NO_DELTA_PNG
  1062. if (pData->bHasDHDR) /* check the colortype for delta-images ! */
  1063. {
  1064. mng_imagedatap pBuf = ((mng_imagep)pData->pObjzero)->pImgbuf;
  1065. if (pData->iColortype != pBuf->iColortype)
  1066. {
  1067. if ( ( (pData->iColortype != MNG_COLORTYPE_INDEXED) ||
  1068. (pBuf->iColortype == MNG_COLORTYPE_GRAY ) ) &&
  1069. ( (pData->iColortype != MNG_COLORTYPE_GRAY ) ||
  1070. (pBuf->iColortype == MNG_COLORTYPE_INDEXED) ) )
  1071. MNG_ERROR (pData, MNG_INVALIDCOLORTYPE);
  1072. }
  1073. }
  1074. #endif
  1075. #endif
  1076. if (!pData->bHasheader) /* first chunk ? */
  1077. {
  1078. pData->bHasheader = MNG_TRUE; /* we've got a header */
  1079. pData->eImagetype = mng_it_png; /* then this must be a PNG */
  1080. pData->iWidth = pData->iDatawidth;
  1081. pData->iHeight = pData->iDataheight;
  1082. /* predict alpha-depth ! */
  1083. if ((pData->iColortype == MNG_COLORTYPE_GRAYA ) ||
  1084. (pData->iColortype == MNG_COLORTYPE_RGBA ) )
  1085. pData->iAlphadepth = pData->iBitdepth;
  1086. else
  1087. if (pData->iColortype == MNG_COLORTYPE_INDEXED)
  1088. pData->iAlphadepth = 8; /* worst case scenario */
  1089. else
  1090. pData->iAlphadepth = 1; /* Possible tRNS cheap binary transparency */
  1091. /* fits on maximum canvas ? */
  1092. if ((pData->iWidth > pData->iMaxwidth) || (pData->iHeight > pData->iMaxheight))
  1093. MNG_WARNING (pData, MNG_IMAGETOOLARGE);
  1094. #if !defined(MNG_INCLUDE_MPNG_PROPOSAL) || !defined(MNG_SUPPORT_DISPLAY)
  1095. if (pData->fProcessheader) /* inform the app ? */
  1096. if (!pData->fProcessheader (((mng_handle)pData), pData->iWidth, pData->iHeight))
  1097. MNG_ERROR (pData, MNG_APPMISCERROR);
  1098. #endif
  1099. }
  1100. if (!pData->bHasDHDR)
  1101. pData->iImagelevel++; /* one level deeper */
  1102. #ifdef MNG_SUPPORT_DISPLAY
  1103. {
  1104. mng_retcode iRetcode = mng_process_display_ihdr (pData);
  1105. if (iRetcode) /* on error bail out */
  1106. return iRetcode;
  1107. }
  1108. #endif /* MNG_SUPPORT_DISPLAY */
  1109. #ifdef MNG_STORE_CHUNKS
  1110. if (pData->bStorechunks)
  1111. { /* initialize storage */
  1112. mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
  1113. if (iRetcode) /* on error bail out */
  1114. return iRetcode;
  1115. /* fill the fields */
  1116. ((mng_ihdrp)*ppChunk)->iWidth = mng_get_uint32 (pRawdata);
  1117. ((mng_ihdrp)*ppChunk)->iHeight = mng_get_uint32 (pRawdata+4);
  1118. ((mng_ihdrp)*ppChunk)->iBitdepth = pData->iBitdepth;
  1119. ((mng_ihdrp)*ppChunk)->iColortype = pData->iColortype;
  1120. ((mng_ihdrp)*ppChunk)->iCompression = pData->iCompression;
  1121. ((mng_ihdrp)*ppChunk)->iFilter = pData->iFilter;
  1122. ((mng_ihdrp)*ppChunk)->iInterlace = pData->iInterlace;
  1123. }
  1124. #endif /* MNG_STORE_CHUNKS */
  1125. #ifdef MNG_SUPPORT_TRACE
  1126. MNG_TRACE (pData, MNG_FN_READ_IHDR, MNG_LC_END);
  1127. #endif
  1128. return MNG_NOERROR; /* done */
  1129. }
  1130. #endif /* MNG_OPTIMIZE_CHUNKREADER */
  1131. /* ************************************************************************** */
  1132. #ifndef MNG_OPTIMIZE_CHUNKREADER
  1133. READ_CHUNK (mng_read_plte)
  1134. {
  1135. #if defined(MNG_SUPPORT_DISPLAY) || defined(MNG_STORE_CHUNKS)
  1136. mng_uint32 iX;
  1137. mng_uint8p pRawdata2;
  1138. #endif
  1139. #ifdef MNG_SUPPORT_DISPLAY
  1140. mng_uint32 iRawlen2;
  1141. #endif
  1142. #ifdef MNG_SUPPORT_TRACE
  1143. MNG_TRACE (pData, MNG_FN_READ_PLTE, MNG_LC_START);
  1144. #endif
  1145. /* sequence checks */
  1146. if ((!pData->bHasMHDR) && (!pData->bHasIHDR) &&
  1147. (!pData->bHasBASI) && (!pData->bHasDHDR) )
  1148. MNG_ERROR (pData, MNG_SEQUENCEERROR);
  1149. #ifdef MNG_INCLUDE_JNG
  1150. if ((pData->bHasIDAT) || (pData->bHasJHDR))
  1151. #else
  1152. if (pData->bHasIDAT)
  1153. #endif
  1154. MNG_ERROR (pData, MNG_SEQUENCEERROR);
  1155. /* multiple PLTE only inside BASI */
  1156. if ((pData->bHasPLTE) && (!pData->bHasBASI))
  1157. MNG_ERROR (pData, MNG_MULTIPLEERROR);
  1158. /* length must be multiple of 3 */
  1159. if (((iRawlen % 3) != 0) || (iRawlen > 768))
  1160. MNG_ERROR (pData, MNG_INVALIDLENGTH);
  1161. if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
  1162. { /* only allowed for indexed-color or
  1163. rgb(a)-color! */
  1164. if ((pData->iColortype != 2) && (pData->iColortype != 3) && (pData->iColortype != 6))
  1165. MNG_ERROR (pData, MNG_CHUNKNOTALLOWED);
  1166. /* empty only allowed if global present */
  1167. if ((iRawlen == 0) && (!pData->bHasglobalPLTE))
  1168. MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
  1169. }
  1170. else
  1171. {
  1172. if (iRawlen == 0) /* cannot be empty as global! */
  1173. MNG_ERROR (pData, MNG_CANNOTBEEMPTY);
  1174. }
  1175. if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
  1176. pData->bHasPLTE = MNG_TRUE; /* got it! */
  1177. else
  1178. pData->bHasglobalPLTE = MNG_TRUE;
  1179. pData->iPLTEcount = iRawlen / 3;
  1180. #ifdef MNG_SUPPORT_DISPLAY
  1181. if ((pData->bHasIHDR) || (pData->bHasBASI) || (pData->bHasDHDR))
  1182. {
  1183. mng_imagep pImage;
  1184. mng_imagedatap pBuf;
  1185. #ifndef MNG_NO_DELTA_PNG
  1186. if (pData->bHasDHDR) /* processing delta-image ? */
  1187. { /* store in object 0 !!! */
  1188. pImage = (mng_imagep)pData->pObjzero;
  1189. pBuf = pImage->pImgbuf;
  1190. pBuf->bHasPLTE = MNG_TRUE; /* it's definitely got a PLTE now */
  1191. pBuf->iPLTEcount = iRawlen / 3; /* this is the exact length */
  1192. pRawdata2 = pRawdata; /* copy the entries */
  1193. for (iX = 0; iX < iRawlen / 3; iX++)
  1194. {
  1195. pBuf->aPLTEentries[iX].iRed = *pRawdata2;
  1196. pBuf->aPLTEentries[iX].iGreen = *(pRawdata2+1);
  1197. pBuf->aPLTEentries[iX].iBlue = *(pRawdata2+2);
  1198. pRawdata2 += 3;
  1199. }
  1200. }
  1201. else
  1202. #endif
  1203. { /* get the current object */
  1204. pImage = (mng_imagep)pData->pCurrentobj;
  1205. if (!pImage) /* no object then dump it in obj 0 */
  1206. pImage = (mng_imagep)pData->pObjzero;
  1207. pBuf = pImage->pImgbuf; /* address the object buffer */
  1208. pBuf->bHasPLTE = MNG_TRUE; /* and tell it it's got a PLTE now */
  1209. if (!iRawlen) /* if empty, inherit from global */
  1210. {
  1211. pBuf->iPLTEcount = pData->iGlobalPLTEcount;
  1212. MNG_COPY (pBuf->aPLTEentries, pData->aGlobalPLTEentries,
  1213. sizeof (pBuf->aPLTEentries));
  1214. if (pData->bHasglobalTRNS) /* also copy global tRNS ? */
  1215. { /* indicate tRNS available */
  1216. pBuf->bHasTRNS = MNG_TRUE;
  1217. iRawlen2 = pData->iGlobalTRNSrawlen;
  1218. pRawdata2 = (mng_uint8p)(pData->aGlobalTRNSrawdata);
  1219. /* global length oke ? */
  1220. if ((iRawlen2 == 0) || (iRawlen2 > pBuf->iPLTEcount))
  1221. MNG_ERROR (pData, MNG_GLOBALLENGTHERR);
  1222. /* copy it */
  1223. pBuf->iTRNScount = iRawlen2;
  1224. MNG_COPY (pBuf->aTRNSentries, pRawdata2, iRawlen2);
  1225. }
  1226. }
  1227. else
  1228. { /* store fields for future reference */
  1229. pBuf->iPLTEcount = iRawlen / 3;
  1230. pRawdata2 = pRawdata;
  1231. for (iX = 0; iX < pBuf->iPLTEcount; iX++)
  1232. {
  1233. pBuf->aPLTEentries[iX].iRed = *pRawdata2;
  1234. pBuf->aPLTEentries[iX].iGreen = *(pRawdata2+1);
  1235. pBuf->aPLTEentries[iX].iBlue = *(pRawdata2+2);
  1236. pRawdata2 += 3;
  1237. }
  1238. }
  1239. }
  1240. }
  1241. else /* store as global */
  1242. {
  1243. pData->iGlobalPLTEcount = iRawlen / 3;
  1244. pRawdata2 = pRawdata;
  1245. for (iX = 0; iX < pData->iGlobalPLTEcount; iX++)
  1246. {
  1247. pData->aGlobalPLTEentries[iX].iRed = *pRawdata2;
  1248. pData->aGlobalPLTEentries[iX].iGreen = *(pRawdata2+1);
  1249. pData->aGlobalPLTEentries[iX].iBlue = *(pRawdata2+2);
  1250. pRawdata2 += 3;
  1251. }
  1252. { /* create an animation object */
  1253. mng_retcode iRetcode = mng_create_ani_plte (pData, pData->iGlobalPLTEcount,
  1254. pData->aGlobalPLTEentries);
  1255. if (iRetcode) /* on error bail out */
  1256. return iRetcode;
  1257. }
  1258. }
  1259. #endif /* MNG_SUPPORT_DISPLAY */
  1260. #ifdef MNG_STORE_CHUNKS
  1261. if (pData->bStorechunks)
  1262. { /* initialize storage */
  1263. mng_retcode iRetcode = ((mng_chunk_headerp)pHeader)->fCreate (pData, pHeader, ppChunk);
  1264. if (iRetcode) /* on error bail out */
  1265. return iRetcode;
  1266. /* store the fields */
  1267. ((mng_pltep)*ppChunk)->bEmpty = (mng_bool)(iRawlen == 0);
  1268. ((mng_pltep)*ppChunk)->iEntrycount = iRawlen / 3;
  1269. pRawdata2 = pRawdata;
  1270. for (iX = 0; iX < ((mng_pltep)*ppChunk)->iEntrycount; iX++)
  1271. {
  1272. ((mng_pltep)*ppChunk)->aEntries[iX].iRed = *pRawdata2;
  1273. ((mng_pltep)*ppChunk)->aEntries[iX].iGreen = *(pRawdata2+1);
  1274. ((mng_pltep)*ppChunk)->aEntries[iX].iBlue = *(pRawdata2+2);
  1275. pRawdata2 += 3;
  1276. }
  1277. }
  1278. #endif /* MNG_STORE_CHUNKS */
  1279. #ifdef MNG_SUPPORT_TRACE
  1280. MNG_TRACE (pData, MNG_FN_READ_PLTE, MNG_LC_END);
  1281. #endif
  1282. return MNG_NOERROR; /* done */
  1283. }
  1284. #endif /* MNG_OPTIMIZE_CHUNKREADER */
  1285. /* *******************