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