1 /* ************************************************************************** */
2 /* *             For conditions of distribution and use,                    * */
3 /* *                see copyright notice in libmng.h                        * */
4 /* ************************************************************************** */
5 /* *                                                                        * */
6 /* * project   : libmng                                                     * */
7 /* * file      : libmng_jpeg.c             copyright (c) 2000-2004 G.Juyn   * */
8 /* * version   : 1.0.9                                                      * */
9 /* *                                                                        * */
10 /* * purpose   : JPEG library interface (implementation)                    * */
11 /* *                                                                        * */
12 /* * author    : G.Juyn                                                     * */
13 /* *                                                                        * */
14 /* * comment   : implementation of the JPEG library interface               * */
15 /* *                                                                        * */
16 /* * changes   : 0.5.1 - 05/08/2000 - G.Juyn                                * */
17 /* *             - changed strict-ANSI stuff                                * */
18 /* *                                                                        * */
19 /* *             0.5.2 - 05/22/2000 - G.Juyn                                * */
20 /* *             - implemented all the JNG routines                         * */
21 /* *                                                                        * */
22 /* *             0.5.3 - 06/17/2000 - G.Juyn                                * */
23 /* *             - added tracing of JPEG calls                              * */
24 /* *             0.5.3 - 06/24/2000 - G.Juyn                                * */
25 /* *             - fixed inclusion of IJG read/write code                   * */
26 /* *             0.5.3 - 06/29/2000 - G.Juyn                                * */
27 /* *             - fixed some 64-bit warnings                               * */
28 /* *                                                                        * */
29 /* *             0.9.2 - 08/05/2000 - G.Juyn                                * */
30 /* *             - changed file-prefixes                                    * */
31 /* *                                                                        * */
32 /* *             0.9.3 - 10/16/2000 - G.Juyn                                * */
33 /* *             - added support for JDAA                                   * */
34 /* *                                                                        * */
35 /* *             1.0.1 - 04/19/2001 - G.Juyn                                * */
36 /* *             - added export of JPEG functions for DLL                   * */
37 /* *             1.0.1 - 04/22/2001 - G.Juyn                                * */
38 /* *             - fixed memory-leaks (Thanks Gregg!)                       * */
39 /* *                                                                        * */
40 /* *             1.0.4 - 06/22/2002 - G.Juyn                                * */
41 /* *             - B526138 - returned IJGSRC6B calling convention to        * */
42 /* *               default for MSVC                                         * */
43 /* *                                                                        * */
44 /* *             1.0.5 - 24/02/2003 - G.Juyn                                * */
45 /* *             - B683152 - libjpeg suspension not always honored correctly* */
46 /* *                                                                        * */
47 /* *             1.0.6 - 03/04/2003 - G.Juyn                                * */
48 /* *             - fixed some compiler-warnings                             * */
49 /* *                                                                        * */
50 /* *             1.0.8 - 08/01/2004 - G.Juyn                                * */
51 /* *             - added support for 3+byte pixelsize for JPEG's            * */
52 /* *                                                                        * */
53 /* *             1.0.9 - 12/20/2004 - G.Juyn                                * */
54 /* *             - cleaned up macro-invocations (thanks to D. Airlie)       * */
55 /* *                                                                        * */
56 /* ************************************************************************** */
57 
58 #include "libmng.h"
59 #include "libmng_data.h"
60 #include "libmng_error.h"
61 #include "libmng_trace.h"
62 #ifdef __BORLANDC__
63 #pragma hdrstop
64 #endif
65 #include "libmng_memory.h"
66 #include "libmng_pixels.h"
67 #include "libmng_jpeg.h"
68 
69 #if defined(__BORLANDC__) && defined(MNG_STRICT_ANSI)
70 #pragma option -A                      /* force ANSI-C */
71 #endif
72 
73 /* ************************************************************************** */
74 
75 #if defined(MNG_INCLUDE_JNG) && defined(MNG_INCLUDE_DISPLAY_PROCS)
76 
77 /* ************************************************************************** */
78 /* *                                                                        * */
79 /* * Local IJG callback routines (source-manager, error-manager and such)   * */
80 /* *                                                                        * */
81 /* ************************************************************************** */
82 
83 #ifdef MNG_INCLUDE_IJG6B
84 
85 /* ************************************************************************** */
86 
87 #ifdef MNG_INCLUDE_JNG_READ
88 #ifdef MNG_DEFINE_JPEG_STDCALL
mng_init_source(j_decompress_ptr cinfo)89 void MNG_DECL mng_init_source (j_decompress_ptr cinfo)
90 #else
91 void mng_init_source (j_decompress_ptr cinfo)
92 #endif
93 {
94   return;                              /* nothing needed */
95 }
96 #endif /* MNG_INCLUDE_JNG_READ */
97 
98 /* ************************************************************************** */
99 
100 #ifdef MNG_INCLUDE_JNG_READ
101 #ifdef MNG_DEFINE_JPEG_STDCALL
mng_fill_input_buffer(j_decompress_ptr cinfo)102 boolean MNG_DECL mng_fill_input_buffer (j_decompress_ptr cinfo)
103 #else
104 boolean mng_fill_input_buffer (j_decompress_ptr cinfo)
105 #endif
106 {
107   return FALSE;                        /* force IJG routine to return to caller */
108 }
109 #endif /* MNG_INCLUDE_JNG_READ */
110 
111 /* ************************************************************************** */
112 
113 #ifdef MNG_INCLUDE_JNG_READ
114 #ifdef MNG_DEFINE_JPEG_STDCALL
mng_skip_input_data(j_decompress_ptr cinfo,long num_bytes)115 void MNG_DECL mng_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
116 #else
117 void mng_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
118 #endif
119 {
120   if (num_bytes > 0)                   /* ignore fony calls */
121   {                                    /* address my generic structure */
122     mng_datap pData = (mng_datap)cinfo->client_data;
123                                        /* address source manager */
124     mngjpeg_sourcep pSrc = pData->pJPEGdinfo->src;
125                                        /* problem scenario ? */
126     if (pSrc->bytes_in_buffer < (size_t)num_bytes)
127     {                                  /* tell the boss we need to skip some data! */
128       pData->iJPEGtoskip = (mng_uint32)((size_t)num_bytes - pSrc->bytes_in_buffer);
129 
130       pSrc->bytes_in_buffer = 0;       /* let the JPEG lib suspend */
131       pSrc->next_input_byte = MNG_NULL;
132     }
133     else
134     {                                  /* simply advance in the buffer */
135       pSrc->bytes_in_buffer -= num_bytes;
136       pSrc->next_input_byte += num_bytes;
137     }
138   }
139 
140   return;
141 }
142 #endif /* MNG_INCLUDE_JNG_READ */
143 
144 /* ************************************************************************** */
145 
146 #ifdef MNG_INCLUDE_JNG_READ
147 #ifdef MNG_DEFINE_JPEG_STDCALL
mng_skip_input_data2(j_decompress_ptr cinfo,long num_bytes)148 void MNG_DECL mng_skip_input_data2 (j_decompress_ptr cinfo, long num_bytes)
149 #else
150 void mng_skip_input_data2 (j_decompress_ptr cinfo, long num_bytes)
151 #endif
152 {
153   if (num_bytes > 0)                   /* ignore fony calls */
154   {                                    /* address my generic structure */
155     mng_datap pData = (mng_datap)cinfo->client_data;
156                                        /* address source manager */
157     mngjpeg_sourcep pSrc = pData->pJPEGdinfo2->src;
158                                        /* problem scenario ? */
159     if (pSrc->bytes_in_buffer < (size_t)num_bytes)
160     {                                  /* tell the boss we need to skip some data! */
161       pData->iJPEGtoskip2 = (mng_uint32)((size_t)num_bytes - pSrc->bytes_in_buffer);
162 
163       pSrc->bytes_in_buffer = 0;       /* let the JPEG lib suspend */
164       pSrc->next_input_byte = MNG_NULL;
165     }
166     else
167     {                                  /* simply advance in the buffer */
168       pSrc->bytes_in_buffer -= num_bytes;
169       pSrc->next_input_byte += num_bytes;
170     }
171   }
172 
173   return;
174 }
175 #endif /* MNG_INCLUDE_JNG_READ */
176 
177 /* ************************************************************************** */
178 
179 #ifdef MNG_INCLUDE_JNG_READ
180 #ifdef MNG_DEFINE_JPEG_STDCALL
mng_term_source(j_decompress_ptr cinfo)181 void MNG_DECL mng_term_source (j_decompress_ptr cinfo)
182 #else
183 void mng_term_source (j_decompress_ptr cinfo)
184 #endif
185 {
186   return;                              /* nothing needed */
187 }
188 #endif /* MNG_INCLUDE_JNG_READ */
189 
190 /* ************************************************************************** */
191 
192 #ifdef MNG_USE_SETJMP
193 #ifdef MNG_DEFINE_JPEG_STDCALL
mng_error_exit(j_common_ptr cinfo)194 void MNG_DECL mng_error_exit (j_common_ptr cinfo)
195 #else
196 void mng_error_exit (j_common_ptr cinfo)
197 #endif
198 {                                      /* address my generic structure */
199   mng_datap pData = (mng_datap)cinfo->client_data;
200 
201 #ifdef MNG_ERROR_TELLTALE              /* fill the message text ??? */
202   (*cinfo->err->output_message) (cinfo);
203 #endif
204                                        /* return to the point of no return... */
205   longjmp (pData->sErrorbuf, cinfo->err->msg_code);
206 }
207 #endif /* MNG_USE_SETJMP */
208 
209 /* ************************************************************************** */
210 
211 #ifdef MNG_USE_SETJMP
212 #ifdef MNG_DEFINE_JPEG_STDCALL
mng_output_message(j_common_ptr cinfo)213 void MNG_DECL mng_output_message (j_common_ptr cinfo)
214 #else
215 void mng_output_message (j_common_ptr cinfo)
216 #endif
217 {
218   return;                              /* just do nothing ! */
219 }
220 #endif /* MNG_USE_SETJMP */
221 
222 /* ************************************************************************** */
223 
224 #endif /* MNG_INCLUDE_IJG6B */
225 
226 /* ************************************************************************** */
227 /* *                                                                        * */
228 /* * Global JPEG routines                                                   * */
229 /* *                                                                        * */
230 /* ************************************************************************** */
231 
mngjpeg_initialize(mng_datap pData)232 mng_retcode mngjpeg_initialize (mng_datap pData)
233 {
234 #ifdef MNG_SUPPORT_TRACE
235   MNG_TRACE (pData, MNG_FN_JPEG_INITIALIZE, MNG_LC_START);
236 #endif
237                                        /* allocate space for JPEG structures if necessary */
238 #ifdef MNG_INCLUDE_JNG_READ
239   if (pData->pJPEGderr   == MNG_NULL)
240     MNG_ALLOC (pData, pData->pJPEGderr,   sizeof (mngjpeg_error ));
241   if (pData->pJPEGdsrc   == MNG_NULL)
242     MNG_ALLOC (pData, pData->pJPEGdsrc,   sizeof (mngjpeg_source));
243   if (pData->pJPEGdinfo  == MNG_NULL)
244     MNG_ALLOC (pData, pData->pJPEGdinfo,  sizeof (mngjpeg_decomp));
245                                        /* enable reverse addressing */
246   pData->pJPEGdinfo->client_data  = pData;
247 
248   if (pData->pJPEGderr2  == MNG_NULL)
249     MNG_ALLOC (pData, pData->pJPEGderr2,  sizeof (mngjpeg_error ));
250   if (pData->pJPEGdsrc2  == MNG_NULL)
251     MNG_ALLOC (pData, pData->pJPEGdsrc2,  sizeof (mngjpeg_source));
252   if (pData->pJPEGdinfo2 == MNG_NULL)
253     MNG_ALLOC (pData, pData->pJPEGdinfo2, sizeof (mngjpeg_decomp));
254                                        /* enable reverse addressing */
255   pData->pJPEGdinfo2->client_data = pData;
256 #endif
257 
258 #ifdef MNG_INCLUDE_JNG_WRITE
259   if (pData->pJPEGcerr  == MNG_NULL)
260     MNG_ALLOC (pData, pData->pJPEGcerr,  sizeof (mngjpeg_error ));
261   if (pData->pJPEGcinfo == MNG_NULL)
262     MNG_ALLOC (pData, pData->pJPEGcinfo, sizeof (mngjpeg_comp  ));
263                                        /* enable reverse addressing */
264   pData->pJPEGcinfo->client_data = pData;
265 #endif
266 
267   if (pData->pJPEGbuf   == MNG_NULL)   /* initialize temporary buffers */
268   {
269     pData->iJPEGbufmax     = MNG_JPEG_MAXBUF;
270     MNG_ALLOC (pData, pData->pJPEGbuf, pData->iJPEGbufmax);
271   }
272 
273   if (pData->pJPEGbuf2  == MNG_NULL)
274   {
275     pData->iJPEGbufmax2    = MNG_JPEG_MAXBUF;
276     MNG_ALLOC (pData, pData->pJPEGbuf2, pData->iJPEGbufmax2);
277   }
278 
279   pData->pJPEGcurrent      = pData->pJPEGbuf;
280   pData->iJPEGbufremain    = 0;
281   pData->pJPEGrow          = MNG_NULL;
282   pData->iJPEGrowlen       = 0;
283   pData->iJPEGtoskip       = 0;
284 
285   pData->pJPEGcurrent2     = pData->pJPEGbuf2;
286   pData->iJPEGbufremain2   = 0;
287   pData->pJPEGrow2         = MNG_NULL;
288   pData->iJPEGrowlen2      = 0;
289   pData->iJPEGtoskip2      = 0;
290                                       /* not doing anything yet ! */
291   pData->bJPEGcompress     = MNG_FALSE;
292 
293   pData->bJPEGdecompress   = MNG_FALSE;
294   pData->bJPEGhasheader    = MNG_FALSE;
295   pData->bJPEGdecostarted  = MNG_FALSE;
296   pData->bJPEGscanstarted  = MNG_FALSE;
297   pData->bJPEGscanending   = MNG_FALSE;
298 
299   pData->bJPEGdecompress2  = MNG_FALSE;
300   pData->bJPEGhasheader2   = MNG_FALSE;
301   pData->bJPEGdecostarted2 = MNG_FALSE;
302   pData->bJPEGscanstarted2 = MNG_FALSE;
303 
304   pData->iJPEGrow          = 0;        /* zero input/output lines */
305   pData->iJPEGalpharow     = 0;
306   pData->iJPEGrgbrow       = 0;
307   pData->iJPEGdisprow      = 0;
308 
309 #ifdef MNG_SUPPORT_TRACE
310   MNG_TRACE (pData, MNG_FN_JPEG_INITIALIZE, MNG_LC_END);
311 #endif
312 
313   return MNG_NOERROR;
314 }
315 
316 /* ************************************************************************** */
317 
mngjpeg_cleanup(mng_datap pData)318 mng_retcode mngjpeg_cleanup (mng_datap pData)
319 {
320 #if defined(MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
321   mng_retcode iRetcode;
322 #endif
323 
324 #ifdef MNG_SUPPORT_TRACE
325   MNG_TRACE (pData, MNG_FN_JPEG_CLEANUP, MNG_LC_START);
326 #endif
327 
328 #ifdef MNG_INCLUDE_IJG6B
329 #ifdef MNG_USE_SETJMP
330   iRetcode = setjmp (pData->sErrorbuf);/* setup local JPEG error-recovery */
331   if (iRetcode != 0)                   /* got here from longjmp ? */
332     MNG_ERRORJ (pData, iRetcode);      /* then IJG-lib issued an error */
333 #endif
334 
335 #ifdef MNG_INCLUDE_JNG_READ            /* still decompressing something ? */
336   if (pData->bJPEGdecompress)
337     jpeg_destroy_decompress (pData->pJPEGdinfo);
338   if (pData->bJPEGdecompress2)
339     jpeg_destroy_decompress (pData->pJPEGdinfo2);
340 #endif
341 
342 #ifdef MNG_INCLUDE_JNG_WRITE
343   if (pData->bJPEGcompress)            /* still compressing something ? */
344     jpeg_destroy_compress (pData->pJPEGcinfo);
345 #endif
346 
347 #endif /* MNG_INCLUDE_IJG6B */
348                                        /* cleanup temporary buffers */
349   MNG_FREE (pData, pData->pJPEGbuf2, pData->iJPEGbufmax2);
350   MNG_FREE (pData, pData->pJPEGbuf,  pData->iJPEGbufmax);
351                                        /* cleanup space for JPEG structures */
352 #ifdef MNG_INCLUDE_JNG_WRITE
353   MNG_FREE (pData, pData->pJPEGcinfo,  sizeof (mngjpeg_comp  ));
354   MNG_FREE (pData, pData->pJPEGcerr,   sizeof (mngjpeg_error ));
355 #endif
356 
357 #ifdef MNG_INCLUDE_JNG_READ
358   MNG_FREE (pData, pData->pJPEGdinfo,  sizeof (mngjpeg_decomp));
359   MNG_FREE (pData, pData->pJPEGdsrc,   sizeof (mngjpeg_source));
360   MNG_FREE (pData, pData->pJPEGderr,   sizeof (mngjpeg_error ));
361   MNG_FREE (pData, pData->pJPEGdinfo2, sizeof (mngjpeg_decomp));
362   MNG_FREE (pData, pData->pJPEGdsrc2,  sizeof (mngjpeg_source));
363   MNG_FREE (pData, pData->pJPEGderr2,  sizeof (mngjpeg_error ));
364 #endif
365 
366   MNG_FREE (pData, pData->pJPEGrow2, pData->iJPEGrowlen2);
367   MNG_FREE (pData, pData->pJPEGrow,  pData->iJPEGrowlen);
368                                        /* whatever we were doing ... */
369                                        /* we don't anymore ... */
370   pData->bJPEGcompress     = MNG_FALSE;
371 
372   pData->bJPEGdecompress   = MNG_FALSE;
373   pData->bJPEGhasheader    = MNG_FALSE;
374   pData->bJPEGdecostarted  = MNG_FALSE;
375   pData->bJPEGscanstarted  = MNG_FALSE;
376   pData->bJPEGscanending   = MNG_FALSE;
377 
378   pData->bJPEGdecompress2  = MNG_FALSE;
379   pData->bJPEGhasheader2   = MNG_FALSE;
380   pData->bJPEGdecostarted2 = MNG_FALSE;
381   pData->bJPEGscanstarted2 = MNG_FALSE;
382 
383 #ifdef MNG_SUPPORT_TRACE
384   MNG_TRACE (pData, MNG_FN_JPEG_CLEANUP, MNG_LC_END);
385 #endif
386 
387   return MNG_NOERROR;
388 }
389 
390 /* ************************************************************************** */
391 /* *                                                                        * */
392 /* * JPEG decompression routines (JDAT)                                     * */
393 /* *                                                                        * */
394 /* ************************************************************************** */
395 
396 #ifdef MNG_INCLUDE_JNG_READ
mngjpeg_decompressinit(mng_datap pData)397 mng_retcode mngjpeg_decompressinit (mng_datap pData)
398 {
399 #if defined(MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
400   mng_retcode iRetcode;
401 #endif
402 
403 #ifdef MNG_SUPPORT_TRACE
404   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_START);
405 #endif
406 
407 #ifdef MNG_INCLUDE_IJG6B
408   /* allocate and initialize a JPEG decompression object */
409   pData->pJPEGdinfo->err = jpeg_std_error (pData->pJPEGderr);
410 
411 #ifdef MNG_USE_SETJMP                  /* setup local JPEG error-routines */
412   pData->pJPEGderr->error_exit     = mng_error_exit;
413   pData->pJPEGderr->output_message = mng_output_message;
414 
415   iRetcode = setjmp (pData->sErrorbuf);/* setup local JPEG error-recovery */
416   if (iRetcode != 0)                   /* got here from longjmp ? */
417     MNG_ERRORJ (pData, iRetcode);      /* then IJG-lib issued an error */
418 #endif /* MNG_USE_SETJMP */
419 
420   /* allocate and initialize a JPEG decompression object (continued) */
421 #ifdef MNG_SUPPORT_TRACE
422   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_JPEG_CREATE_DECOMPRESS)
423 #endif
424   jpeg_create_decompress (pData->pJPEGdinfo);
425 
426   pData->bJPEGdecompress = MNG_TRUE;   /* indicate it's initialized */
427 
428   /* specify the source of the compressed data (eg, a file) */
429                                        /* no, not a file; we have buffered input */
430   pData->pJPEGdinfo->src = pData->pJPEGdsrc;
431                                        /* use the default handler */
432   pData->pJPEGdinfo->src->resync_to_restart = jpeg_resync_to_restart;
433                                        /* setup local source routine & parms */
434   pData->pJPEGdinfo->src->init_source       = mng_init_source;
435   pData->pJPEGdinfo->src->fill_input_buffer = mng_fill_input_buffer;
436   pData->pJPEGdinfo->src->skip_input_data   = mng_skip_input_data;
437   pData->pJPEGdinfo->src->term_source       = mng_term_source;
438   pData->pJPEGdinfo->src->next_input_byte   = pData->pJPEGcurrent;
439   pData->pJPEGdinfo->src->bytes_in_buffer   = pData->iJPEGbufremain;
440 
441 #endif /* MNG_INCLUDE_IJG6B */
442 
443 #ifdef MNG_SUPPORT_TRACE
444   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_END);
445 #endif
446 
447   return MNG_NOERROR;
448 }
449 #endif /* MNG_INCLUDE_JNG_READ */
450 
451 /* ************************************************************************** */
452 
453 #ifdef MNG_INCLUDE_JNG_READ
mngjpeg_decompressdata(mng_datap pData,mng_uint32 iRawsize,mng_uint8p pRawdata)454 mng_retcode mngjpeg_decompressdata (mng_datap  pData,
455                                     mng_uint32 iRawsize,
456                                     mng_uint8p pRawdata)
457 {
458   mng_retcode iRetcode;
459   mng_uint32  iRemain;
460   mng_uint8p  pWork;
461 
462 #ifdef MNG_SUPPORT_TRACE
463   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_START);
464 #endif
465 
466 #if defined (MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
467   iRetcode = setjmp (pData->sErrorbuf);/* initialize local JPEG error-recovery */
468   if (iRetcode != 0)                   /* got here from longjmp ? */
469     MNG_ERRORJ (pData, iRetcode);      /* then IJG-lib issued an error */
470 #endif
471 
472   pWork   = pRawdata;
473   iRemain = iRawsize;
474 
475   if (pData->iJPEGtoskip)              /* JPEG-lib told us to skip some more data ? */
476   {
477     if (iRemain > pData->iJPEGtoskip)  /* enough data in this buffer ? */
478     {
479       iRemain -= pData->iJPEGtoskip;   /* skip enough to access the next byte */
480       pWork   += pData->iJPEGtoskip;
481 
482       pData->iJPEGtoskip = 0;          /* no more to skip then */
483     }
484     else
485     {
486       pData->iJPEGtoskip -= iRemain;   /* skip all data in the buffer */
487       iRemain = 0;                     /* and indicate this accordingly */
488     }
489                                        /* the skip set current-pointer to NULL ! */
490     pData->pJPEGcurrent = pData->pJPEGbuf;
491   }
492 
493   while (iRemain)                      /* repeat until no more input-bytes */
494   {                                    /* need to shift anything ? */
495     if ((pData->pJPEGcurrent > pData->pJPEGbuf) &&
496         (pData->pJPEGcurrent - pData->pJPEGbuf + pData->iJPEGbufremain + iRemain > pData->iJPEGbufmax))
497     {
498       if (pData->iJPEGbufremain > 0)   /* then do so */
499         MNG_COPY (pData->pJPEGbuf, pData->pJPEGcurrent, pData->iJPEGbufremain);
500 
501       pData->pJPEGcurrent = pData->pJPEGbuf;
502     }
503                                        /* does the remaining input fit into the buffer ? */
504     if (pData->iJPEGbufremain + iRemain <= pData->iJPEGbufmax)
505     {                                  /* move the lot */
506       MNG_COPY ((pData->pJPEGcurrent + pData->iJPEGbufremain), pWork, iRemain);
507 
508       pData->iJPEGbufremain += iRemain;/* adjust remaining_bytes counter */
509       iRemain = 0;                     /* and indicate there's no input left */
510     }
511     else
512     {                                  /* calculate what does fit */
513       mng_uint32 iFits = pData->iJPEGbufmax - pData->iJPEGbufremain;
514 
515       if (iFits <= 0)                  /* no space is just bugger 'm all */
516         MNG_ERROR (pData, MNG_JPEGBUFTOOSMALL);
517                                        /* move that */
518       MNG_COPY ((pData->pJPEGcurrent + pData->iJPEGbufremain), pWork, iFits);
519 
520       pData->iJPEGbufremain += iFits;  /* adjust remain_bytes counter */
521       iRemain -= iFits;                /* and the input-parms */
522       pWork   += iFits;
523     }
524 
525 #ifdef MNG_INCLUDE_IJG6B
526     pData->pJPEGdinfo->src->next_input_byte = pData->pJPEGcurrent;
527     pData->pJPEGdinfo->src->bytes_in_buffer = pData->iJPEGbufremain;
528 
529     if (!pData->bJPEGhasheader)        /* haven't got the header yet ? */
530     {
531       /* call jpeg_read_header() to obtain image info */
532 #ifdef MNG_SUPPORT_TRACE
533       MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_READ_HEADER)
534 #endif
535       if (jpeg_read_header (pData->pJPEGdinfo, TRUE) != JPEG_SUSPENDED)
536       {                                /* indicate the header's oke */
537         pData->bJPEGhasheader = MNG_TRUE;
538                                        /* let's do some sanity checks ! */
539         if ((pData->pJPEGdinfo->image_width  != pData->iDatawidth ) ||
540             (pData->pJPEGdinfo->image_height != pData->iDataheight)    )
541           MNG_ERROR (pData, MNG_JPEGPARMSERR);
542 
543         if ( ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAY ) ||
544               (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA)    ) &&
545              (pData->pJPEGdinfo->jpeg_color_space != JCS_GRAYSCALE  )    )
546           MNG_ERROR (pData, MNG_JPEGPARMSERR);
547 
548         if ( ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLOR ) ||
549               (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA)    ) &&
550              (pData->pJPEGdinfo->jpeg_color_space != JCS_YCbCr       )    )
551           MNG_ERROR (pData, MNG_JPEGPARMSERR);
552                                        /* indicate whether or not it's progressive */
553         pData->bJPEGprogressive = (mng_bool)jpeg_has_multiple_scans (pData->pJPEGdinfo);
554                                        /* progressive+alpha can't display "on-the-fly"!! */
555         if ((pData->bJPEGprogressive) &&
556             ((pData->iJHDRcolortype == MNG_COLORTYPE_JPEGGRAYA ) ||
557              (pData->iJHDRcolortype == MNG_COLORTYPE_JPEGCOLORA)    ))
558           pData->fDisplayrow = MNG_NULL;
559                                        /* allocate a row of JPEG-samples */
560         if (pData->pJPEGdinfo->jpeg_color_space == JCS_YCbCr)
561           pData->iJPEGrowlen = pData->pJPEGdinfo->image_width * RGB_PIXELSIZE;
562         else
563           pData->iJPEGrowlen = pData->pJPEGdinfo->image_width;
564 
565         MNG_ALLOC (pData, pData->pJPEGrow, pData->iJPEGrowlen);
566 
567         pData->iJPEGrgbrow = 0;        /* quite empty up to now */
568       }
569 
570       pData->pJPEGcurrent   = (mng_uint8p)pData->pJPEGdinfo->src->next_input_byte;
571       pData->iJPEGbufremain = (mng_uint32)pData->pJPEGdinfo->src->bytes_in_buffer;
572     }
573                                        /* decompress not started ? */
574     if ((pData->bJPEGhasheader) && (!pData->bJPEGdecostarted))
575     {
576       /* set parameters for decompression */
577 
578       if (pData->bJPEGprogressive)     /* progressive display ? */
579         pData->pJPEGdinfo->buffered_image = TRUE;
580 
581       /* jpeg_start_decompress(...); */
582 #ifdef MNG_SUPPORT_TRACE
583       MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_START_DECOMPRESS)
584 #endif
585       if (jpeg_start_decompress (pData->pJPEGdinfo) == TRUE)
586                                        /* indicate it started */
587         pData->bJPEGdecostarted = MNG_TRUE;
588 
589       pData->pJPEGcurrent   = (mng_uint8p)pData->pJPEGdinfo->src->next_input_byte;
590       pData->iJPEGbufremain = (mng_uint32)pData->pJPEGdinfo->src->bytes_in_buffer;
591     }
592                                        /* process some scanlines ? */
593     if ((pData->bJPEGhasheader) && (pData->bJPEGdecostarted) &&
594 	    ((!jpeg_input_complete (pData->pJPEGdinfo)) ||
595          (pData->pJPEGdinfo->output_scanline < pData->pJPEGdinfo->output_height) ||
596          ((pData->bJPEGprogressive) && (pData->bJPEGscanending))))
597     {
598       mng_int32 iLines = 0;
599 
600       /* for (each output pass) */
601       do
602       {                                /* address the row output buffer */
603         JSAMPROW pRow = (JSAMPROW)pData->pJPEGrow;
604 
605                                        /* init new pass ? */
606         if ((pData->bJPEGprogressive) && (!pData->bJPEGscanstarted))
607         {
608           pData->bJPEGscanstarted = MNG_TRUE;
609 
610           /* adjust output decompression parameters if required */
611           /* nop */
612 
613           /* start a new output pass */
614 #ifdef MNG_SUPPORT_TRACE
615           MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_START_OUTPUT)
616 #endif
617           jpeg_start_output (pData->pJPEGdinfo, pData->pJPEGdinfo->input_scan_number);
618 
619           pData->iJPEGrow = 0;         /* start at row 0 in the image again */
620         }
621 
622         /* while (scan lines remain to be read) */
623         if ((!pData->bJPEGprogressive) || (!pData->bJPEGscanending))
624         {
625           do
626           {
627           /*   jpeg_read_scanlines(...); */
628 #ifdef MNG_SUPPORT_TRACE
629             MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_READ_SCANLINES)
630 #endif
631             iLines = jpeg_read_scanlines (pData->pJPEGdinfo, (JSAMPARRAY)&pRow, 1);
632 
633             pData->pJPEGcurrent   = (mng_uint8p)pData->pJPEGdinfo->src->next_input_byte;
634             pData->iJPEGbufremain = (mng_uint32)pData->pJPEGdinfo->src->bytes_in_buffer;
635 
636             if (iLines > 0)            /* got something ? */
637             {
638               if (pData->fStorerow2)   /* store in object ? */
639               {
640                 iRetcode = ((mng_storerow)pData->fStorerow2) (pData);
641 
642                 if (iRetcode)          /* on error bail out */
643                 return iRetcode;
644 
645               }
646             }
647           }
648           while ((pData->pJPEGdinfo->output_scanline < pData->pJPEGdinfo->output_height) &&
649                  (iLines > 0));        /* until end-of-image or not enough input-data */
650         }
651 
652         /* terminate output pass */
653         if ((pData->bJPEGprogressive) &&
654             (pData->pJPEGdinfo->output_scanline >= pData->pJPEGdinfo->output_height))
655         {
656 #ifdef MNG_SUPPORT_TRACE
657           MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_FINISH_OUTPUT)
658 #endif
659           if (jpeg_finish_output (pData->pJPEGdinfo) != JPEG_SUSPENDED)
660           {                            /* this scan has ended */
661             pData->bJPEGscanstarted = MNG_FALSE;
662             pData->bJPEGscanending  = MNG_FALSE;
663           }
664           else
665           {
666             pData->bJPEGscanending  = MNG_TRUE;
667           }
668         }
669       }
670       while ((!jpeg_input_complete (pData->pJPEGdinfo)) &&
671              (iLines > 0) && (!pData->bJPEGscanending));
672     }
673                                        /* end of image ? */
674     if ((pData->bJPEGhasheader) && (pData->bJPEGdecostarted) &&
675         (!pData->bJPEGscanending) && (jpeg_input_complete (pData->pJPEGdinfo)) &&
676         (pData->pJPEGdinfo->input_scan_number == pData->pJPEGdinfo->output_scan_number))
677     {
678       /* jpeg_finish_decompress(...); */
679 #ifdef MNG_SUPPORT_TRACE
680       MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_FINISH_DECOMPRESS)
681 #endif
682       if (jpeg_finish_decompress (pData->pJPEGdinfo) == TRUE)
683       {                                /* indicate it's done */
684         pData->bJPEGhasheader   = MNG_FALSE;
685         pData->bJPEGdecostarted = MNG_FALSE;
686         pData->pJPEGcurrent     = (mng_uint8p)pData->pJPEGdinfo->src->next_input_byte;
687         pData->iJPEGbufremain   = (mng_uint32)pData->pJPEGdinfo->src->bytes_in_buffer;
688                                        /* remaining fluff is an error ! */
689         if ((pData->iJPEGbufremain > 0) || (iRemain > 0))
690           MNG_ERROR (pData, MNG_TOOMUCHJDAT);
691       }
692     }
693 #endif /* MNG_INCLUDE_IJG6B */
694   }
695 
696 #ifdef MNG_SUPPORT_TRACE
697   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_END);
698 #endif
699 
700   return MNG_NOERROR;
701 }
702 #endif /* MNG_INCLUDE_JNG_READ */
703 
704 /* ************************************************************************** */
705 
706 #ifdef MNG_INCLUDE_JNG_READ
mngjpeg_decompressfree(mng_datap pData)707 mng_retcode mngjpeg_decompressfree (mng_datap pData)
708 {
709 #if defined(MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
710   mng_retcode iRetcode;
711 #endif
712 
713 #ifdef MNG_SUPPORT_TRACE
714   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_START);
715 #endif
716 
717 #ifdef MNG_INCLUDE_IJG6B
718 #ifdef MNG_USE_SETJMP
719   iRetcode = setjmp (pData->sErrorbuf);/* setup local JPEG error-recovery */
720   if (iRetcode != 0)                   /* got here from longjmp ? */
721     MNG_ERRORJ (pData, iRetcode);      /* then IJG-lib issued an error */
722 #endif
723                                        /* free the row of JPEG-samples*/
724   MNG_FREE (pData, pData->pJPEGrow, pData->iJPEGrowlen);
725 
726   /* release the JPEG decompression object */
727 #ifdef MNG_SUPPORT_TRACE
728   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_JPEG_DESTROY_DECOMPRESS)
729 #endif
730   jpeg_destroy_decompress (pData->pJPEGdinfo);
731 
732   pData->bJPEGdecompress = MNG_FALSE;  /* indicate it's done */
733 
734 #endif /* MNG_INCLUDE_IJG6B */
735 
736 #ifdef MNG_SUPPORT_TRACE
737   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_END);
738 #endif
739 
740   return MNG_NOERROR;
741 }
742 #endif /* MNG_INCLUDE_JNG_READ */
743 
744 /* ************************************************************************** */
745 /* *                                                                        * */
746 /* * JPEG decompression routines (JDAA)                                     * */
747 /* *                                                                        * */
748 /* ************************************************************************** */
749 
750 #ifdef MNG_INCLUDE_JNG_READ
mngjpeg_decompressinit2(mng_datap pData)751 mng_retcode mngjpeg_decompressinit2 (mng_datap pData)
752 {
753 #if defined(MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
754   mng_retcode iRetcode;
755 #endif
756 
757 #ifdef MNG_SUPPORT_TRACE
758   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_START);
759 #endif
760 
761 #ifdef MNG_INCLUDE_IJG6B
762   /* allocate and initialize a JPEG decompression object */
763   pData->pJPEGdinfo2->err = jpeg_std_error (pData->pJPEGderr2);
764 
765 #ifdef MNG_USE_SETJMP                  /* setup local JPEG error-routines */
766   pData->pJPEGderr2->error_exit     = mng_error_exit;
767   pData->pJPEGderr2->output_message = mng_output_message;
768 
769   iRetcode = setjmp (pData->sErrorbuf);/* setup local JPEG error-recovery */
770   if (iRetcode != 0)                   /* got here from longjmp ? */
771     MNG_ERRORJ (pData, iRetcode);      /* then IJG-lib issued an error */
772 #endif /* MNG_USE_SETJMP */
773 
774   /* allocate and initialize a JPEG decompression object (continued) */
775 #ifdef MNG_SUPPORT_TRACE
776   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_JPEG_CREATE_DECOMPRESS)
777 #endif
778   jpeg_create_decompress (pData->pJPEGdinfo2);
779 
780   pData->bJPEGdecompress2 = MNG_TRUE;  /* indicate it's initialized */
781 
782   /* specify the source of the compressed data (eg, a file) */
783                                        /* no, not a file; we have buffered input */
784   pData->pJPEGdinfo2->src = pData->pJPEGdsrc2;
785                                        /* use the default handler */
786   pData->pJPEGdinfo2->src->resync_to_restart = jpeg_resync_to_restart;
787                                        /* setup local source routine & parms */
788   pData->pJPEGdinfo2->src->init_source       = mng_init_source;
789   pData->pJPEGdinfo2->src->fill_input_buffer = mng_fill_input_buffer;
790   pData->pJPEGdinfo2->src->skip_input_data   = mng_skip_input_data2;
791   pData->pJPEGdinfo2->src->term_source       = mng_term_source;
792   pData->pJPEGdinfo2->src->next_input_byte   = pData->pJPEGcurrent2;
793   pData->pJPEGdinfo2->src->bytes_in_buffer   = pData->iJPEGbufremain2;
794 
795 #endif /* MNG_INCLUDE_IJG6B */
796 
797 #ifdef MNG_SUPPORT_TRACE
798   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSINIT, MNG_LC_END);
799 #endif
800 
801   return MNG_NOERROR;
802 }
803 #endif /* MNG_INCLUDE_JNG_READ */
804 
805 /* ************************************************************************** */
806 
807 #ifdef MNG_INCLUDE_JNG_READ
mngjpeg_decompressdata2(mng_datap pData,mng_uint32 iRawsize,mng_uint8p pRawdata)808 mng_retcode mngjpeg_decompressdata2 (mng_datap  pData,
809                                      mng_uint32 iRawsize,
810                                      mng_uint8p pRawdata)
811 {
812   mng_retcode iRetcode;
813   mng_uint32  iRemain;
814   mng_uint8p  pWork;
815 
816 #ifdef MNG_SUPPORT_TRACE
817   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_START);
818 #endif
819 
820 #if defined (MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
821   iRetcode = setjmp (pData->sErrorbuf);/* initialize local JPEG error-recovery */
822   if (iRetcode != 0)                   /* got here from longjmp ? */
823     MNG_ERRORJ (pData, iRetcode);      /* then IJG-lib issued an error */
824 #endif
825 
826   pWork   = pRawdata;
827   iRemain = iRawsize;
828 
829   if (pData->iJPEGtoskip2)             /* JPEG-lib told us to skip some more data ? */
830   {
831     if (iRemain > pData->iJPEGtoskip2) /* enough data in this buffer ? */
832     {
833       iRemain -= pData->iJPEGtoskip2;  /* skip enough to access the next byte */
834       pWork   += pData->iJPEGtoskip2;
835 
836       pData->iJPEGtoskip2 = 0;         /* no more to skip then */
837     }
838     else
839     {
840       pData->iJPEGtoskip2 -= iRemain;  /* skip all data in the buffer */
841       iRemain = 0;                     /* and indicate this accordingly */
842     }
843                                        /* the skip set current-pointer to NULL ! */
844     pData->pJPEGcurrent2 = pData->pJPEGbuf2;
845   }
846 
847   while (iRemain)                      /* repeat until no more input-bytes */
848   {                                    /* need to shift anything ? */
849     if ((pData->pJPEGcurrent2 > pData->pJPEGbuf2) &&
850         (pData->pJPEGcurrent2 - pData->pJPEGbuf2 + pData->iJPEGbufremain2 + iRemain > pData->iJPEGbufmax2))
851     {
852       if (pData->iJPEGbufremain2 > 0)  /* then do so */
853         MNG_COPY (pData->pJPEGbuf2, pData->pJPEGcurrent2, pData->iJPEGbufremain2);
854 
855       pData->pJPEGcurrent2 = pData->pJPEGbuf2;
856     }
857                                        /* does the remaining input fit into the buffer ? */
858     if (pData->iJPEGbufremain2 + iRemain <= pData->iJPEGbufmax2)
859     {                                  /* move the lot */
860       MNG_COPY ((pData->pJPEGcurrent2 + pData->iJPEGbufremain2), pWork, iRemain);
861                                        /* adjust remaining_bytes counter */
862       pData->iJPEGbufremain2 += iRemain;
863       iRemain = 0;                     /* and indicate there's no input left */
864     }
865     else
866     {                                  /* calculate what does fit */
867       mng_uint32 iFits = pData->iJPEGbufmax2 - pData->iJPEGbufremain2;
868 
869       if (iFits <= 0)                  /* no space is just bugger 'm all */
870         MNG_ERROR (pData, MNG_JPEGBUFTOOSMALL);
871                                        /* move that */
872       MNG_COPY ((pData->pJPEGcurrent2 + pData->iJPEGbufremain2), pWork, iFits);
873 
874       pData->iJPEGbufremain2 += iFits; /* adjust remain_bytes counter */
875       iRemain -= iFits;                /* and the input-parms */
876       pWork   += iFits;
877     }
878 
879 #ifdef MNG_INCLUDE_IJG6B
880     pData->pJPEGdinfo2->src->next_input_byte = pData->pJPEGcurrent2;
881     pData->pJPEGdinfo2->src->bytes_in_buffer = pData->iJPEGbufremain2;
882 
883     if (!pData->bJPEGhasheader2)       /* haven't got the header yet ? */
884     {
885       /* call jpeg_read_header() to obtain image info */
886 #ifdef MNG_SUPPORT_TRACE
887       MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_READ_HEADER)
888 #endif
889       if (jpeg_read_header (pData->pJPEGdinfo2, TRUE) != JPEG_SUSPENDED)
890       {                                /* indicate the header's oke */
891         pData->bJPEGhasheader2 = MNG_TRUE;
892                                        /* let's do some sanity checks ! */
893         if ((pData->pJPEGdinfo2->image_width  != pData->iDatawidth ) ||
894             (pData->pJPEGdinfo2->image_height != pData->iDataheight)    )
895           MNG_ERROR (pData, MNG_JPEGPARMSERR);
896 
897         if (pData->pJPEGdinfo2->jpeg_color_space != JCS_GRAYSCALE)
898           MNG_ERROR (pData, MNG_JPEGPARMSERR);
899                                        /* indicate whether or not it's progressive */
900         pData->bJPEGprogressive2 = (mng_bool)jpeg_has_multiple_scans (pData->pJPEGdinfo2);
901 
902         if (pData->bJPEGprogressive2)  /* progressive alphachannel not allowed !!! */
903           MNG_ERROR (pData, MNG_JPEGPARMSERR);
904                                        /* allocate a row of JPEG-samples */
905         if (pData->pJPEGdinfo2->jpeg_color_space == JCS_YCbCr)
906           pData->iJPEGrowlen2 = pData->pJPEGdinfo2->image_width * RGB_PIXELSIZE;
907         else
908           pData->iJPEGrowlen2 = pData->pJPEGdinfo2->image_width;
909 
910         MNG_ALLOC (pData, pData->pJPEGrow2, pData->iJPEGrowlen2);
911 
912         pData->iJPEGalpharow = 0;      /* quite empty up to now */
913       }
914 
915       pData->pJPEGcurrent2   = (mng_uint8p)pData->pJPEGdinfo2->src->next_input_byte;
916       pData->iJPEGbufremain2 = (mng_uint32)pData->pJPEGdinfo2->src->bytes_in_buffer;
917     }
918                                        /* decompress not started ? */
919     if ((pData->bJPEGhasheader2) && (!pData->bJPEGdecostarted2))
920     {
921       /* set parameters for decompression */
922 
923       if (pData->bJPEGprogressive2)    /* progressive display ? */
924         pData->pJPEGdinfo2->buffered_image = TRUE;
925 
926       /* jpeg_start_decompress(...); */
927 #ifdef MNG_SUPPORT_TRACE
928       MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_START_DECOMPRESS)
929 #endif
930       if (jpeg_start_decompress (pData->pJPEGdinfo2) == TRUE)
931                                        /* indicate it started */
932         pData->bJPEGdecostarted2 = MNG_TRUE;
933 
934       pData->pJPEGcurrent2   = (mng_uint8p)pData->pJPEGdinfo2->src->next_input_byte;
935       pData->iJPEGbufremain2 = (mng_uint32)pData->pJPEGdinfo2->src->bytes_in_buffer;
936     }
937                                        /* process some scanlines ? */
938     if ((pData->bJPEGhasheader2) && (pData->bJPEGdecostarted2) &&
939 	    ((!jpeg_input_complete (pData->pJPEGdinfo2)) ||
940          (pData->pJPEGdinfo2->output_scanline < pData->pJPEGdinfo2->output_height)))
941     {
942       mng_int32 iLines;
943 
944       /* for (each output pass) */
945       do
946       {                                /* address the row output buffer */
947         JSAMPROW pRow = (JSAMPROW)pData->pJPEGrow2;
948 
949                                        /* init new pass ? */
950         if ((pData->bJPEGprogressive2) &&
951             ((!pData->bJPEGscanstarted2) ||
952              (pData->pJPEGdinfo2->output_scanline >= pData->pJPEGdinfo2->output_height)))
953         {
954           pData->bJPEGscanstarted2 = MNG_TRUE;
955 
956           /* adjust output decompression parameters if required */
957           /* nop */
958 
959           /* start a new output pass */
960 #ifdef MNG_SUPPORT_TRACE
961           MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_START_OUTPUT)
962 #endif
963           jpeg_start_output (pData->pJPEGdinfo2, pData->pJPEGdinfo2->input_scan_number);
964 
965           pData->iJPEGrow = 0;         /* start at row 0 in the image again */
966         }
967 
968         /* while (scan lines remain to be read) */
969         do
970         {
971           /*   jpeg_read_scanlines(...); */
972 #ifdef MNG_SUPPORT_TRACE
973           MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_READ_SCANLINES)
974 #endif
975           iLines = jpeg_read_scanlines (pData->pJPEGdinfo2, (JSAMPARRAY)&pRow, 1);
976 
977           pData->pJPEGcurrent2   = (mng_uint8p)pData->pJPEGdinfo2->src->next_input_byte;
978           pData->iJPEGbufremain2 = (mng_uint32)pData->pJPEGdinfo2->src->bytes_in_buffer;
979 
980           if (iLines > 0)              /* got something ? */
981           {
982             if (pData->fStorerow3)     /* store in object ? */
983             {
984               iRetcode = ((mng_storerow)pData->fStorerow3) (pData);
985 
986               if (iRetcode)            /* on error bail out */
987                 return iRetcode;
988 
989             }
990           }
991         }
992         while ((pData->pJPEGdinfo2->output_scanline < pData->pJPEGdinfo2->output_height) &&
993                (iLines > 0));          /* until end-of-image or not enough input-data */
994 
995         /* terminate output pass */
996         if ((pData->bJPEGprogressive2) &&
997             (pData->pJPEGdinfo2->output_scanline >= pData->pJPEGdinfo2->output_height))
998         {
999 #ifdef MNG_SUPPORT_TRACE
1000           MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_FINISH_OUTPUT)
1001 #endif
1002           if (jpeg_finish_output (pData->pJPEGdinfo2) == JPEG_SUSPENDED)
1003             jpeg_finish_output (pData->pJPEGdinfo2);
1004                                        /* this scan has ended */
1005           pData->bJPEGscanstarted2 = MNG_FALSE;
1006         }
1007       }
1008       while ((!jpeg_input_complete (pData->pJPEGdinfo2)) && (iLines > 0));
1009     }
1010                                        /* end of image ? */
1011     if ((pData->bJPEGhasheader2) && (pData->bJPEGdecostarted2) &&
1012         (jpeg_input_complete (pData->pJPEGdinfo2)) &&
1013         (pData->pJPEGdinfo2->input_scan_number == pData->pJPEGdinfo2->output_scan_number))
1014     {
1015       /* jpeg_finish_decompress(...); */
1016 #ifdef MNG_SUPPORT_TRACE
1017       MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_JPEG_FINISH_DECOMPRESS)
1018 #endif
1019       if (jpeg_finish_decompress (pData->pJPEGdinfo2) == TRUE)
1020       {                                /* indicate it's done */
1021         pData->bJPEGhasheader2   = MNG_FALSE;
1022         pData->bJPEGdecostarted2 = MNG_FALSE;
1023         pData->pJPEGcurrent2     = (mng_uint8p)pData->pJPEGdinfo2->src->next_input_byte;
1024         pData->iJPEGbufremain2   = (mng_uint32)pData->pJPEGdinfo2->src->bytes_in_buffer;
1025                                        /* remaining fluff is an error ! */
1026         if ((pData->iJPEGbufremain2 > 0) || (iRemain > 0))
1027           MNG_ERROR (pData, MNG_TOOMUCHJDAT);
1028       }
1029     }
1030 #endif /* MNG_INCLUDE_IJG6B */
1031   }
1032 
1033 #ifdef MNG_SUPPORT_TRACE
1034   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSDATA, MNG_LC_END);
1035 #endif
1036 
1037   return MNG_NOERROR;
1038 }
1039 #endif /* MNG_INCLUDE_JNG_READ */
1040 
1041 /* ************************************************************************** */
1042 
1043 #ifdef MNG_INCLUDE_JNG_READ
mngjpeg_decompressfree2(mng_datap pData)1044 mng_retcode mngjpeg_decompressfree2 (mng_datap pData)
1045 {
1046 #if defined(MNG_INCLUDE_IJG6B) && defined(MNG_USE_SETJMP)
1047   mng_retcode iRetcode;
1048 #endif
1049 
1050 #ifdef MNG_SUPPORT_TRACE
1051   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_START);
1052 #endif
1053 
1054 #ifdef MNG_INCLUDE_IJG6B
1055 #ifdef MNG_USE_SETJMP
1056   iRetcode = setjmp (pData->sErrorbuf);/* setup local JPEG error-recovery */
1057   if (iRetcode != 0)                   /* got here from longjmp ? */
1058     MNG_ERRORJ (pData, iRetcode);      /* then IJG-lib issued an error */
1059 #endif
1060                                        /* free the row of JPEG-samples*/
1061   MNG_FREE (pData, pData->pJPEGrow2, pData->iJPEGrowlen2);
1062 
1063   /* release the JPEG decompression object */
1064 #ifdef MNG_SUPPORT_TRACE
1065   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_JPEG_DESTROY_DECOMPRESS)
1066 #endif
1067   jpeg_destroy_decompress (pData->pJPEGdinfo2);
1068 
1069   pData->bJPEGdecompress2 = MNG_FALSE; /* indicate it's done */
1070 
1071 #endif /* MNG_INCLUDE_IJG6B */
1072 
1073 #ifdef MNG_SUPPORT_TRACE
1074   MNG_TRACE (pData, MNG_FN_JPEG_DECOMPRESSFREE, MNG_LC_END);
1075 #endif
1076 
1077   return MNG_NOERROR;
1078 }
1079 #endif /* MNG_INCLUDE_JNG_READ */
1080 
1081 /* ************************************************************************** */
1082 
1083 #endif /* MNG_INCLUDE_JNG && MNG_INCLUDE_DISPLAY_PROCS */
1084 
1085 /* ************************************************************************** */
1086 /* * end of file                                                            * */
1087 /* ************************************************************************** */
1088 
1089