1 #include <cstdio>
2 #include <jpeglib.h>
3 #include <jerror.h>
4 #include "jpeg.h"
5
6 /*
7 * jdatasrc.c
8 *
9 * Copyright (C) 1994-1996, Thomas G. Lane.
10 * Modified 2009-2010 by Guido Vollbeding.
11 * This file is part of the Independent JPEG Group's software.
12 * For conditions of distribution and use, see the accompanying README file.
13 *
14 * This file contains decompression data source routines for the case of
15 * reading JPEG data from a file (or any stdio stream). While these routines
16 * are sufficient for most applications, some will want to use a different
17 * source manager.
18 * IMPORTANT: we assume that fread() will correctly transcribe an array of
19 * JOCTETs from 8-bit-wide elements on external storage. If char is wider
20 * than 8 bits on your machine, you may need to do some tweaking.
21 */
22
23 /* this is not a core library module, so it doesn't define JPEG_INTERNALS */
24 //#include "jinclude.h"
25
26 #define JFREAD(file,buf,sizeofbuf) \
27 ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
28 #define JFWRITE(file,buf,sizeofbuf) \
29 ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file)))
30
31
32
33
34 /* Expanded data source object for stdio input */
35 namespace
36 {
37
38 typedef struct {
39 struct jpeg_source_mgr pub; /* public fields */
40 jmp_buf error_jmp_buf; /* error handler for this instance */
41
42 FILE * infile; /* source stream */
43 JOCTET * buffer; /* start of buffer */
44 boolean start_of_file; /* have we gotten any data yet? */
45 } my_source_mgr;
46
47 typedef my_source_mgr * my_src_ptr;
48
49 }
50
51 #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
52
53
54 /*
55 * Initialize source --- called by jpeg_read_header
56 * before any data is actually read.
57 */
58
59 METHODDEF(void)
my_init_source(j_decompress_ptr cinfo)60 my_init_source (j_decompress_ptr cinfo)
61 {
62 my_src_ptr src = (my_src_ptr) cinfo->src;
63
64 /* We reset the empty-input-file flag for each image,
65 * but we don't clear the input buffer.
66 * This is correct behavior for reading a series of images from one source.
67 */
68 src->start_of_file = TRUE;
69 }
70
71
72 /*
73 * Fill the input buffer --- called whenever buffer is emptied.
74 *
75 * In typical applications, this should read fresh data into the buffer
76 * (ignoring the current state of next_input_byte & bytes_in_buffer),
77 * reset the pointer & count to the start of the buffer, and return TRUE
78 * indicating that the buffer has been reloaded. It is not necessary to
79 * fill the buffer entirely, only to obtain at least one more byte.
80 *
81 * There is no such thing as an EOF return. If the end of the file has been
82 * reached, the routine has a choice of ERREXIT() or inserting fake data into
83 * the buffer. In most cases, generating a warning message and inserting a
84 * fake EOI marker is the best course of action --- this will allow the
85 * decompressor to output however much of the image is there. However,
86 * the resulting error message is misleading if the real problem is an empty
87 * input file, so we handle that case specially.
88 *
89 * In applications that need to be able to suspend compression due to input
90 * not being available yet, a FALSE return indicates that no more data can be
91 * obtained right now, but more may be forthcoming later. In this situation,
92 * the decompressor will return to its caller (with an indication of the
93 * number of scanlines it has read, if any). The application should resume
94 * decompression after it has loaded more data into the input buffer. Note
95 * that there are substantial restrictions on the use of suspension --- see
96 * the documentation.
97 *
98 * When suspending, the decompressor will back up to a convenient restart point
99 * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
100 * indicate where the restart point will be if the current call returns FALSE.
101 * Data beyond this point must be rescanned after resumption, so move it to
102 * the front of the buffer rather than discarding it.
103 */
104
105 METHODDEF(boolean)
my_fill_input_buffer(j_decompress_ptr cinfo)106 my_fill_input_buffer (j_decompress_ptr cinfo)
107 {
108 my_src_ptr src = (my_src_ptr) cinfo->src;
109 size_t nbytes;
110
111 nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
112
113 if (nbytes == 0) {
114 if (src->start_of_file) { /* Treat empty input file as fatal error */
115 ERREXIT(cinfo, JERR_INPUT_EMPTY);
116 }
117
118 WARNMS(cinfo, JWRN_JPEG_EOF);
119 /* Insert a fake EOI marker */
120 src->buffer[0] = (JOCTET) 0xFF;
121 src->buffer[1] = (JOCTET) JPEG_EOI;
122 nbytes = 2;
123 }
124
125 if (src->start_of_file) {
126 src->buffer[0] = (JOCTET) 0xFF;
127 }
128
129 src->pub.next_input_byte = src->buffer;
130 src->pub.bytes_in_buffer = nbytes;
131 src->start_of_file = FALSE;
132
133 return TRUE;
134 }
135
136
137 /*
138 * Skip data --- used to skip over a potentially large amount of
139 * uninteresting data (such as an APPn marker).
140 *
141 * Writers of suspendable-input applications must note that skip_input_data
142 * is not granted the right to give a suspension return. If the skip extends
143 * beyond the data currently in the buffer, the buffer can be marked empty so
144 * that the next read will cause a fill_input_buffer call that can suspend.
145 * Arranging for additional bytes to be discarded before reloading the input
146 * buffer is the application writer's problem.
147 */
148
149 METHODDEF(void)
my_skip_input_data(j_decompress_ptr cinfo,long num_bytes)150 my_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
151 {
152 my_src_ptr src = (my_src_ptr) cinfo->src;
153
154 /* Just a dumb implementation for now. Could use fseek() except
155 * it doesn't work on pipes. Not clear that being smart is worth
156 * any trouble anyway --- large skips are infrequent.
157 */
158 if (num_bytes > 0) {
159 while (num_bytes > (long) src->pub.bytes_in_buffer) {
160 num_bytes -= (long) src->pub.bytes_in_buffer;
161 (void) my_fill_input_buffer(cinfo);
162 /* note we assume that fill_input_buffer will never return FALSE,
163 * so suspension need not be handled.
164 */
165 }
166
167 src->pub.next_input_byte += (size_t) num_bytes;
168 src->pub.bytes_in_buffer -= (size_t) num_bytes;
169 }
170 }
171
172
173 /*
174 * An additional method that can be provided by data source modules is the
175 * resync_to_restart method for error recovery in the presence of RST markers.
176 * For the moment, this source module just uses the default resync method
177 * provided by the JPEG library. That method assumes that no backtracking
178 * is possible.
179 */
180
181
182 /*
183 * Terminate source --- called by jpeg_finish_decompress
184 * after all data has been read. Often a no-op.
185 *
186 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
187 * application must deal with any cleanup that should happen even
188 * for error exit.
189 */
190
191 METHODDEF(void)
my_term_source(j_decompress_ptr cinfo)192 my_term_source (j_decompress_ptr cinfo)
193 {
194 /* no work necessary here */
195 }
196
197
198 /*
199 * Prepare for input from a stdio stream.
200 * The caller must have already opened the stream, and is responsible
201 * for closing it after finishing decompression.
202 */
203
204 GLOBAL(void)
my_jpeg_stdio_src(j_decompress_ptr cinfo,FILE * infile)205 my_jpeg_stdio_src (j_decompress_ptr cinfo, FILE * infile)
206 {
207 my_src_ptr src;
208
209 /* The source object and input buffer are made permanent so that a series
210 * of JPEG images can be read from the same file by calling jpeg_stdio_src
211 * only before the first one. (If we discarded the buffer at the end of
212 * one image, we'd likely lose the start of the next one.)
213 * This makes it unsafe to use this manager and a different source
214 * manager serially with the same JPEG object. Caveat programmer.
215 */
216 if (cinfo->src == nullptr) { /* first time for this JPEG object? */
217 cinfo->src = (struct jpeg_source_mgr *)
218 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
219 sizeof(my_source_mgr));
220 src = (my_src_ptr) cinfo->src;
221 src->buffer = (JOCTET *)
222 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
223 INPUT_BUF_SIZE * sizeof(JOCTET));
224 }
225
226 src = (my_src_ptr) cinfo->src;
227 src->pub.init_source = my_init_source;
228 src->pub.fill_input_buffer = my_fill_input_buffer;
229 src->pub.skip_input_data = my_skip_input_data;
230 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
231 src->pub.term_source = my_term_source;
232 src->infile = infile;
233 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
234 src->pub.next_input_byte = nullptr; /* until buffer loaded */
235 }
236
237 METHODDEF(void)
my_error_exit(j_common_ptr cinfo)238 my_error_exit (j_common_ptr cinfo)
239 {
240 /* Always display the message */
241 (*cinfo->err->output_message) (cinfo);
242
243 /* Let the memory manager delete any temp files before we die */
244 //jpeg_destroy(cinfo);
245
246 j_decompress_ptr dinfo = (j_decompress_ptr)cinfo;
247 // longjmp (((rt_jpeg_error_mgr*)(dinfo->src))->error_jmp_buf, 1);
248 #if defined( WIN32 ) && defined( __x86_64__ ) && !defined(__clang__)
249 __builtin_longjmp ((reinterpret_cast<rt_jpeg_error_mgr*>(dinfo->src)) ->error_jmp_buf, 1);
250 #else
251 longjmp ((reinterpret_cast<rt_jpeg_error_mgr*>(dinfo->src)) ->error_jmp_buf, 1);
252 #endif
253 }
254
255
256 //const char * const jpeg_std_message_table[] = {
257 //#include "jerror.h"
258 // NULL
259 //};
260 extern const char * const jpeg_std_message_table[];
261
262
263 /*
264 * Actual output of an error or trace message.
265 * Applications may override this method to send JPEG messages somewhere
266 * other than stderr.
267 *
268 * On Windows, printing to stderr is generally completely useless,
269 * so we provide optional code to produce an error-dialog popup.
270 * Most Windows applications will still prefer to override this routine,
271 * but if they don't, it'll do something at least marginally useful.
272 *
273 * NOTE: to use the library in an environment that doesn't support the
274 * C stdio library, you may have to delete the call to fprintf() entirely,
275 * not just not use this routine.
276 */
277
278 METHODDEF(void)
output_message(j_common_ptr cinfo)279 output_message (j_common_ptr cinfo)
280 {
281 char buffer[JMSG_LENGTH_MAX];
282
283 /* Create the message */
284 (*cinfo->err->format_message) (cinfo, buffer);
285
286 #ifdef USE_WINDOWS_MESSAGEBOX
287 /* Display it in a message dialog box */
288 MessageBox(GetActiveWindow(), buffer, "JPEG Library Error",
289 MB_OK | MB_ICONERROR);
290 #else
291 /* Send it to stderr, adding a newline */
292 fprintf(stderr, "%s\n", buffer);
293 #endif
294 }
295
296
297 /*
298 * Decide whether to emit a trace or warning message.
299 * msg_level is one of:
300 * -1: recoverable corrupt-data warning, may want to abort.
301 * 0: important advisory messages (always display to user).
302 * 1: first level of tracing detail.
303 * 2,3,...: successively more detailed tracing messages.
304 * An application might override this method if it wanted to abort on warnings
305 * or change the policy about which messages to display.
306 */
307
308 METHODDEF(void)
emit_message(j_common_ptr cinfo,int msg_level)309 emit_message (j_common_ptr cinfo, int msg_level)
310 {
311 struct jpeg_error_mgr * err = cinfo->err;
312
313 if (msg_level < 0) {
314 /* It's a warning message. Since corrupt files may generate many warnings,
315 * the policy implemented here is to show only the first warning,
316 * unless trace_level >= 3.
317 */
318 if (err->num_warnings == 0 || err->trace_level >= 3) {
319 (*err->output_message) (cinfo);
320 }
321
322 /* Always count warnings in num_warnings. */
323 err->num_warnings++;
324 } else {
325 /* It's a trace message. Show it if trace_level >= msg_level. */
326 if (err->trace_level >= msg_level) {
327 (*err->output_message) (cinfo);
328 }
329 }
330 }
331
332
333 /*
334 * Format a message string for the most recent JPEG error or message.
335 * The message is stored into buffer, which should be at least JMSG_LENGTH_MAX
336 * characters. Note that no '\n' character is added to the string.
337 * Few applications should need to override this method.
338 */
339
340 METHODDEF(void)
format_message(j_common_ptr cinfo,char * buffer)341 format_message (j_common_ptr cinfo, char * buffer)
342 {
343 struct jpeg_error_mgr * err = cinfo->err;
344 int msg_code = err->msg_code;
345 const char * msgtext = nullptr;
346 const char * msgptr;
347 char ch;
348 boolean isstring;
349
350 /* Look up message string in proper table */
351 if (msg_code > 0 && msg_code <= err->last_jpeg_message) {
352 msgtext = err->jpeg_message_table[msg_code];
353 } else if (err->addon_message_table != nullptr &&
354 msg_code >= err->first_addon_message &&
355 msg_code <= err->last_addon_message) {
356 msgtext = err->addon_message_table[msg_code - err->first_addon_message];
357 }
358
359 /* Defend against bogus message number */
360 if (msgtext == nullptr) {
361 err->msg_parm.i[0] = msg_code;
362 msgtext = err->jpeg_message_table[0];
363 }
364
365 /* Check for string parameter, as indicated by %s in the message text */
366 isstring = FALSE;
367 msgptr = msgtext;
368
369 while ((ch = *msgptr++) != '\0') {
370 if (ch == '%') {
371 if (*msgptr == 's') {
372 isstring = TRUE;
373 }
374
375 break;
376 }
377 }
378
379 /* Format the message into the passed buffer */
380 if (isstring) {
381 sprintf(buffer, msgtext, err->msg_parm.s);
382 } else
383 sprintf(buffer, msgtext,
384 err->msg_parm.i[0], err->msg_parm.i[1],
385 err->msg_parm.i[2], err->msg_parm.i[3],
386 err->msg_parm.i[4], err->msg_parm.i[5],
387 err->msg_parm.i[6], err->msg_parm.i[7]);
388 }
389
390
391 /*
392 * Reset error state variables at start of a new image.
393 * This is called during compression startup to reset trace/error
394 * processing to default state, without losing any application-specific
395 * method pointers. An application might possibly want to override
396 * this method if it has additional error processing state.
397 */
398
399 METHODDEF(void)
reset_error_mgr(j_common_ptr cinfo)400 reset_error_mgr (j_common_ptr cinfo)
401 {
402 cinfo->err->num_warnings = 0;
403 /* trace_level is not reset since it is an application-supplied parameter */
404 cinfo->err->msg_code = 0; /* may be useful as a flag for "no error" */
405 }
406
407
408 GLOBAL(struct jpeg_error_mgr *)
my_jpeg_std_error(struct jpeg_error_mgr * err)409 my_jpeg_std_error (struct jpeg_error_mgr * err)
410 {
411
412 err->error_exit = my_error_exit;
413 err->emit_message = emit_message;
414 err->output_message = output_message;
415 err->format_message = format_message;
416 err->reset_error_mgr = reset_error_mgr;
417
418 err->trace_level = 0; /* default = no tracing */
419 err->num_warnings = 0; /* no warnings emitted yet */
420 err->msg_code = 0; /* may be useful as a flag for "no error" */
421
422 /* Initialize message table pointers */
423 err->jpeg_message_table = jpeg_std_message_table;
424 err->last_jpeg_message = (int) JMSG_LASTMSGCODE - 1;
425
426 err->addon_message_table = nullptr;
427 err->first_addon_message = 0; /* for safety */
428 err->last_addon_message = 0;
429
430 return err;
431 }
432