0718fb3b8c79555ce1336403d72042f23d911cb0
[xonotic/netradiant.git] / libs / jpeg6 / jdapistd.cpp
1 /*\r
2 \r
3  * jdapistd.c\r
4 \r
5  *\r
6 \r
7  * Copyright (C) 1994-1995, Thomas G. Lane.\r
8 \r
9  * This file is part of the Independent JPEG Group's software.\r
10 \r
11  * For conditions of distribution and use, see the accompanying README file.\r
12 \r
13  *\r
14 \r
15  * This file contains application interface code for the decompression half\r
16 \r
17  * of the JPEG library.  These are the "standard" API routines that are\r
18 \r
19  * used in the normal full-decompression case.  They are not used by a\r
20 \r
21  * transcoding-only application.  Note that if an application links in\r
22 \r
23  * jpeg_start_decompress, it will end up linking in the entire decompressor.\r
24 \r
25  * We thus must separate this file from jdapimin.c to avoid linking the\r
26 \r
27  * whole decompression library into a transcoder.\r
28 \r
29  */\r
30 \r
31 \r
32 \r
33 #define JPEG_INTERNALS\r
34 \r
35 #include "jinclude.h"\r
36 \r
37 #include "radiant_jpeglib.h"\r
38 \r
39 \r
40 \r
41 \r
42 \r
43 /* Forward declarations */\r
44 \r
45 LOCAL boolean output_pass_setup JPP((j_decompress_ptr cinfo));\r
46 \r
47 \r
48 \r
49 \r
50 \r
51 /*\r
52 \r
53  * Decompression initialization.\r
54 \r
55  * jpeg_read_header must be completed before calling this.\r
56 \r
57  *\r
58 \r
59  * If a multipass operating mode was selected, this will do all but the\r
60 \r
61  * last pass, and thus may take a great deal of time.\r
62 \r
63  *\r
64 \r
65  * Returns FALSE if suspended.  The return value need be inspected only if\r
66 \r
67  * a suspending data source is used.\r
68 \r
69  */\r
70 \r
71 \r
72 \r
73 GLOBAL boolean\r
74 \r
75 jpeg_start_decompress (j_decompress_ptr cinfo)\r
76 \r
77 {\r
78 \r
79   if (cinfo->global_state == DSTATE_READY) {\r
80 \r
81     /* First call: initialize master control, select active modules */\r
82 \r
83     jinit_master_decompress(cinfo);\r
84 \r
85     if (cinfo->buffered_image) {\r
86 \r
87       /* No more work here; expecting jpeg_start_output next */\r
88 \r
89       cinfo->global_state = DSTATE_BUFIMAGE;\r
90 \r
91       return TRUE;\r
92 \r
93     }\r
94 \r
95     cinfo->global_state = DSTATE_PRELOAD;\r
96 \r
97   }\r
98 \r
99   if (cinfo->global_state == DSTATE_PRELOAD) {\r
100 \r
101     /* If file has multiple scans, absorb them all into the coef buffer */\r
102 \r
103     if (cinfo->inputctl->has_multiple_scans) {\r
104 \r
105 #ifdef D_MULTISCAN_FILES_SUPPORTED\r
106 \r
107       for (;;) {\r
108 \r
109         int retcode;\r
110 \r
111         /* Call progress monitor hook if present */\r
112 \r
113         if (cinfo->progress != NULL)\r
114 \r
115           (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);\r
116 \r
117         /* Absorb some more input */\r
118 \r
119         retcode = (*cinfo->inputctl->consume_input) (cinfo);\r
120 \r
121         if (retcode == JPEG_SUSPENDED)\r
122 \r
123           return FALSE;\r
124 \r
125         if (retcode == JPEG_REACHED_EOI)\r
126 \r
127           break;\r
128 \r
129         /* Advance progress counter if appropriate */\r
130 \r
131         if (cinfo->progress != NULL &&\r
132 \r
133             (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) {\r
134 \r
135           if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) {\r
136 \r
137             /* jdmaster underestimated number of scans; ratchet up one scan */\r
138 \r
139             cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows;\r
140 \r
141           }\r
142 \r
143         }\r
144 \r
145       }\r
146 \r
147 #else\r
148 \r
149       ERREXIT(cinfo, JERR_NOT_COMPILED);\r
150 \r
151 #endif /* D_MULTISCAN_FILES_SUPPORTED */\r
152 \r
153     }\r
154 \r
155     cinfo->output_scan_number = cinfo->input_scan_number;\r
156 \r
157   } else if (cinfo->global_state != DSTATE_PRESCAN)\r
158 \r
159     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);\r
160 \r
161   /* Perform any dummy output passes, and set up for the final pass */\r
162 \r
163   return output_pass_setup(cinfo);\r
164 \r
165 }\r
166 \r
167 \r
168 \r
169 \r
170 \r
171 /*\r
172 \r
173  * Set up for an output pass, and perform any dummy pass(es) needed.\r
174 \r
175  * Common subroutine for jpeg_start_decompress and jpeg_start_output.\r
176 \r
177  * Entry: global_state = DSTATE_PRESCAN only if previously suspended.\r
178 \r
179  * Exit: If done, returns TRUE and sets global_state for proper output mode.\r
180 \r
181  *       If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN.\r
182 \r
183  */\r
184 \r
185 \r
186 \r
187 LOCAL boolean\r
188 \r
189 output_pass_setup (j_decompress_ptr cinfo)\r
190 \r
191 {\r
192 \r
193   if (cinfo->global_state != DSTATE_PRESCAN) {\r
194 \r
195     /* First call: do pass setup */\r
196 \r
197     (*cinfo->master->prepare_for_output_pass) (cinfo);\r
198 \r
199     cinfo->output_scanline = 0;\r
200 \r
201     cinfo->global_state = DSTATE_PRESCAN;\r
202 \r
203   }\r
204 \r
205   /* Loop over any required dummy passes */\r
206 \r
207   while (cinfo->master->is_dummy_pass) {\r
208 \r
209 #ifdef QUANT_2PASS_SUPPORTED\r
210 \r
211     /* Crank through the dummy pass */\r
212 \r
213     while (cinfo->output_scanline < cinfo->output_height) {\r
214 \r
215       JDIMENSION last_scanline;\r
216 \r
217       /* Call progress monitor hook if present */\r
218 \r
219       if (cinfo->progress != NULL) {\r
220 \r
221         cinfo->progress->pass_counter = (long) cinfo->output_scanline;\r
222 \r
223         cinfo->progress->pass_limit = (long) cinfo->output_height;\r
224 \r
225         (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);\r
226 \r
227       }\r
228 \r
229       /* Process some data */\r
230 \r
231       last_scanline = cinfo->output_scanline;\r
232 \r
233       (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL,\r
234 \r
235                                     &cinfo->output_scanline, (JDIMENSION) 0);\r
236 \r
237       if (cinfo->output_scanline == last_scanline)\r
238 \r
239         return FALSE;           /* No progress made, must suspend */\r
240 \r
241     }\r
242 \r
243     /* Finish up dummy pass, and set up for another one */\r
244 \r
245     (*cinfo->master->finish_output_pass) (cinfo);\r
246 \r
247     (*cinfo->master->prepare_for_output_pass) (cinfo);\r
248 \r
249     cinfo->output_scanline = 0;\r
250 \r
251 #else\r
252 \r
253     ERREXIT(cinfo, JERR_NOT_COMPILED);\r
254 \r
255 #endif /* QUANT_2PASS_SUPPORTED */\r
256 \r
257   }\r
258 \r
259   /* Ready for application to drive output pass through\r
260 \r
261    * jpeg_read_scanlines or jpeg_read_raw_data.\r
262 \r
263    */\r
264 \r
265   cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING;\r
266 \r
267   return TRUE;\r
268 \r
269 }\r
270 \r
271 \r
272 \r
273 \r
274 \r
275 /*\r
276 \r
277  * Read some scanlines of data from the JPEG decompressor.\r
278 \r
279  *\r
280 \r
281  * The return value will be the number of lines actually read.\r
282 \r
283  * This may be less than the number requested in several cases,\r
284 \r
285  * including bottom of image, data source suspension, and operating\r
286 \r
287  * modes that emit multiple scanlines at a time.\r
288 \r
289  *\r
290 \r
291  * Note: we warn about excess calls to jpeg_read_scanlines() since\r
292 \r
293  * this likely signals an application programmer error.  However,\r
294 \r
295  * an oversize buffer (max_lines > scanlines remaining) is not an error.\r
296 \r
297  */\r
298 \r
299 \r
300 \r
301 GLOBAL JDIMENSION\r
302 \r
303 jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines,\r
304 \r
305                      JDIMENSION max_lines)\r
306 \r
307 {\r
308 \r
309   JDIMENSION row_ctr;\r
310 \r
311 \r
312 \r
313   if (cinfo->global_state != DSTATE_SCANNING)\r
314 \r
315     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);\r
316 \r
317   if (cinfo->output_scanline >= cinfo->output_height) {\r
318 \r
319     WARNMS(cinfo, JWRN_TOO_MUCH_DATA);\r
320 \r
321     return 0;\r
322 \r
323   }\r
324 \r
325 \r
326 \r
327   /* Call progress monitor hook if present */\r
328 \r
329   if (cinfo->progress != NULL) {\r
330 \r
331     cinfo->progress->pass_counter = (long) cinfo->output_scanline;\r
332 \r
333     cinfo->progress->pass_limit = (long) cinfo->output_height;\r
334 \r
335     (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);\r
336 \r
337   }\r
338 \r
339 \r
340 \r
341   /* Process some data */\r
342 \r
343   row_ctr = 0;\r
344 \r
345   (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines);\r
346 \r
347   cinfo->output_scanline += row_ctr;\r
348 \r
349   return row_ctr;\r
350 \r
351 }\r
352 \r
353 \r
354 \r
355 \r
356 \r
357 /*\r
358 \r
359  * Alternate entry point to read raw data.\r
360 \r
361  * Processes exactly one iMCU row per call, unless suspended.\r
362 \r
363  */\r
364 \r
365 \r
366 \r
367 GLOBAL JDIMENSION\r
368 \r
369 jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data,\r
370 \r
371                     JDIMENSION max_lines)\r
372 \r
373 {\r
374 \r
375   JDIMENSION lines_per_iMCU_row;\r
376 \r
377 \r
378 \r
379   if (cinfo->global_state != DSTATE_RAW_OK)\r
380 \r
381     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);\r
382 \r
383   if (cinfo->output_scanline >= cinfo->output_height) {\r
384 \r
385     WARNMS(cinfo, JWRN_TOO_MUCH_DATA);\r
386 \r
387     return 0;\r
388 \r
389   }\r
390 \r
391 \r
392 \r
393   /* Call progress monitor hook if present */\r
394 \r
395   if (cinfo->progress != NULL) {\r
396 \r
397     cinfo->progress->pass_counter = (long) cinfo->output_scanline;\r
398 \r
399     cinfo->progress->pass_limit = (long) cinfo->output_height;\r
400 \r
401     (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo);\r
402 \r
403   }\r
404 \r
405 \r
406 \r
407   /* Verify that at least one iMCU row can be returned. */\r
408 \r
409   lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size;\r
410 \r
411   if (max_lines < lines_per_iMCU_row)\r
412 \r
413     ERREXIT(cinfo, JERR_BUFFER_SIZE);\r
414 \r
415 \r
416 \r
417   /* Decompress directly into user's buffer. */\r
418 \r
419   if (! (*cinfo->coef->decompress_data) (cinfo, data))\r
420 \r
421     return 0;                   /* suspension forced, can do nothing more */\r
422 \r
423 \r
424 \r
425   /* OK, we processed one iMCU row. */\r
426 \r
427   cinfo->output_scanline += lines_per_iMCU_row;\r
428 \r
429   return lines_per_iMCU_row;\r
430 \r
431 }\r
432 \r
433 \r
434 \r
435 \r
436 \r
437 /* Additional entry points for buffered-image mode. */\r
438 \r
439 \r
440 \r
441 #ifdef D_MULTISCAN_FILES_SUPPORTED\r
442 \r
443 \r
444 \r
445 /*\r
446 \r
447  * Initialize for an output pass in buffered-image mode.\r
448 \r
449  */\r
450 \r
451 \r
452 \r
453 GLOBAL boolean\r
454 \r
455 jpeg_start_output (j_decompress_ptr cinfo, int scan_number)\r
456 \r
457 {\r
458 \r
459   if (cinfo->global_state != DSTATE_BUFIMAGE &&\r
460 \r
461       cinfo->global_state != DSTATE_PRESCAN)\r
462 \r
463     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);\r
464 \r
465   /* Limit scan number to valid range */\r
466 \r
467   if (scan_number <= 0)\r
468 \r
469     scan_number = 1;\r
470 \r
471   if (cinfo->inputctl->eoi_reached &&\r
472 \r
473       scan_number > cinfo->input_scan_number)\r
474 \r
475     scan_number = cinfo->input_scan_number;\r
476 \r
477   cinfo->output_scan_number = scan_number;\r
478 \r
479   /* Perform any dummy output passes, and set up for the real pass */\r
480 \r
481   return output_pass_setup(cinfo);\r
482 \r
483 }\r
484 \r
485 \r
486 \r
487 \r
488 \r
489 /*\r
490 \r
491  * Finish up after an output pass in buffered-image mode.\r
492 \r
493  *\r
494 \r
495  * Returns FALSE if suspended.  The return value need be inspected only if\r
496 \r
497  * a suspending data source is used.\r
498 \r
499  */\r
500 \r
501 \r
502 \r
503 GLOBAL boolean\r
504 \r
505 jpeg_finish_output (j_decompress_ptr cinfo)\r
506 \r
507 {\r
508 \r
509   if ((cinfo->global_state == DSTATE_SCANNING ||\r
510 \r
511        cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) {\r
512 \r
513     /* Terminate this pass. */\r
514 \r
515     /* We do not require the whole pass to have been completed. */\r
516 \r
517     (*cinfo->master->finish_output_pass) (cinfo);\r
518 \r
519     cinfo->global_state = DSTATE_BUFPOST;\r
520 \r
521   } else if (cinfo->global_state != DSTATE_BUFPOST) {\r
522 \r
523     /* BUFPOST = repeat call after a suspension, anything else is error */\r
524 \r
525     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);\r
526 \r
527   }\r
528 \r
529   /* Read markers looking for SOS or EOI */\r
530 \r
531   while (cinfo->input_scan_number <= cinfo->output_scan_number &&\r
532 \r
533          ! cinfo->inputctl->eoi_reached) {\r
534 \r
535     if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED)\r
536 \r
537       return FALSE;             /* Suspend, come back later */\r
538 \r
539   }\r
540 \r
541   cinfo->global_state = DSTATE_BUFIMAGE;\r
542 \r
543   return TRUE;\r
544 \r
545 }\r
546 \r
547 \r
548 \r
549 #endif /* D_MULTISCAN_FILES_SUPPORTED */\r
550 \r