ae95d2149a6c9bc4782f08b6b63f2c6dc37dbe86
[xonotic/netradiant.git] / libs / jpeg6 / jdatasrc.cpp
1 /*\r
2  * jdatasrc.c\r
3  *\r
4  * Copyright (C) 1994, Thomas G. Lane.\r
5  * This file is part of the Independent JPEG Group's software.\r
6  * For conditions of distribution and use, see the accompanying README file.\r
7  *\r
8  * This file contains decompression data source routines for the case of\r
9  * reading JPEG data from a file (or any stdio stream).  While these routines\r
10  * are sufficient for most applications, some will want to use a different\r
11  * source manager.\r
12  * IMPORTANT: we assume that fread() will correctly transcribe an array of\r
13  * JOCTETs from 8-bit-wide elements on external storage.  If char is wider\r
14  * than 8 bits on your machine, you may need to do some tweaking.\r
15  */\r
16 \r
17 \r
18 /* this is not a core library module, so it doesn't define JPEG_INTERNALS */\r
19 #include "jinclude.h"\r
20 #include "radiant_jpeglib.h"\r
21 #include "jerror.h"\r
22 \r
23 //extern int leo_buf_size; // FIXME ? merged in from Alpha - replaced by my_source_mgr->src_size\r
24 \r
25 /* Expanded data source object for stdio input */\r
26 \r
27 typedef struct {\r
28   struct jpeg_source_mgr pub;   /* public fields */\r
29   int src_size; // FIXME ? merged from Alpha\r
30   unsigned char *infile;                /* source stream */\r
31   JOCTET * buffer;              /* start of buffer */\r
32   boolean start_of_file;        /* have we gotten any data yet? */\r
33 } my_source_mgr;\r
34 \r
35 typedef my_source_mgr * my_src_ptr;\r
36 \r
37 #define INPUT_BUF_SIZE  4096    /* choose an efficiently fread'able size */\r
38 \r
39 \r
40 /*\r
41  * Initialize source --- called by jpeg_read_header\r
42  * before any data is actually read.\r
43  */\r
44 \r
45 METHODDEF void\r
46 init_source (j_decompress_ptr cinfo)\r
47 {\r
48   my_src_ptr src = (my_src_ptr) cinfo->src;\r
49 \r
50   /* We reset the empty-input-file flag for each image,\r
51    * but we don't clear the input buffer.\r
52    * This is correct behavior for reading a series of images from one source.\r
53    */\r
54   src->start_of_file = TRUE;\r
55 }\r
56 \r
57 \r
58 /*\r
59  * Fill the input buffer --- called whenever buffer is emptied.\r
60  *\r
61  * In typical applications, this should read fresh data into the buffer\r
62  * (ignoring the current state of next_input_byte & bytes_in_buffer),\r
63  * reset the pointer & count to the start of the buffer, and return TRUE\r
64  * indicating that the buffer has been reloaded.  It is not necessary to\r
65  * fill the buffer entirely, only to obtain at least one more byte.\r
66  *\r
67  * There is no such thing as an EOF return.  If the end of the file has been\r
68  * reached, the routine has a choice of ERREXIT() or inserting fake data into\r
69  * the buffer.  In most cases, generating a warning message and inserting a\r
70  * fake EOI marker is the best course of action --- this will allow the\r
71  * decompressor to output however much of the image is there.  However,\r
72  * the resulting error message is misleading if the real problem is an empty\r
73  * input file, so we handle that case specially.\r
74  *\r
75  * In applications that need to be able to suspend compression due to input\r
76  * not being available yet, a FALSE return indicates that no more data can be\r
77  * obtained right now, but more may be forthcoming later.  In this situation,\r
78  * the decompressor will return to its caller (with an indication of the\r
79  * number of scanlines it has read, if any).  The application should resume\r
80  * decompression after it has loaded more data into the input buffer.  Note\r
81  * that there are substantial restrictions on the use of suspension --- see\r
82  * the documentation.\r
83  *\r
84  * When suspending, the decompressor will back up to a convenient restart point\r
85  * (typically the start of the current MCU). next_input_byte & bytes_in_buffer\r
86  * indicate where the restart point will be if the current call returns FALSE.\r
87  * Data beyond this point must be rescanned after resumption, so move it to\r
88  * the front of the buffer rather than discarding it.\r
89  */\r
90 \r
91 METHODDEF boolean\r
92 // FIXME ? merged in from Alpha\r
93 fill_input_buffer (j_decompress_ptr cinfo)\r
94 {\r
95   my_src_ptr src = (my_src_ptr) cinfo->src;\r
96   size_t nbytes;\r
97  \r
98   if (src->src_size > INPUT_BUF_SIZE)\r
99     nbytes = INPUT_BUF_SIZE;\r
100   else\r
101     nbytes = src->src_size;\r
102 \r
103   memcpy (src->buffer, src->infile, nbytes);\r
104 \r
105   src->infile += nbytes;\r
106   src->src_size -= nbytes;\r
107 \r
108   src->pub.next_input_byte = src->buffer;\r
109   src->pub.bytes_in_buffer = nbytes;\r
110   src->start_of_file = FALSE;\r
111 \r
112   return TRUE;\r
113 }\r
114 \r
115 \r
116 /*\r
117  * Skip data --- used to skip over a potentially large amount of\r
118  * uninteresting data (such as an APPn marker).\r
119  *\r
120  * Writers of suspendable-input applications must note that skip_input_data\r
121  * is not granted the right to give a suspension return.  If the skip extends\r
122  * beyond the data currently in the buffer, the buffer can be marked empty so\r
123  * that the next read will cause a fill_input_buffer call that can suspend.\r
124  * Arranging for additional bytes to be discarded before reloading the input\r
125  * buffer is the application writer's problem.\r
126  */\r
127 \r
128 METHODDEF void\r
129 skip_input_data (j_decompress_ptr cinfo, long num_bytes)\r
130 {\r
131   my_src_ptr src = (my_src_ptr) cinfo->src;\r
132 \r
133   /* Just a dumb implementation for now.  Could use fseek() except\r
134    * it doesn't work on pipes.  Not clear that being smart is worth\r
135    * any trouble anyway --- large skips are infrequent.\r
136    */\r
137   if (num_bytes > 0) {\r
138     while (num_bytes > (long) src->pub.bytes_in_buffer) {\r
139       num_bytes -= (long) src->pub.bytes_in_buffer;\r
140       (void) fill_input_buffer(cinfo);\r
141       /* note we assume that fill_input_buffer will never return FALSE,\r
142        * so suspension need not be handled.\r
143        */\r
144     }\r
145     src->pub.next_input_byte += (size_t) num_bytes;\r
146     src->pub.bytes_in_buffer -= (size_t) num_bytes;\r
147   }\r
148 }\r
149 \r
150 \r
151 /*\r
152  * An additional method that can be provided by data source modules is the\r
153  * resync_to_restart method for error recovery in the presence of RST markers.\r
154  * For the moment, this source module just uses the default resync method\r
155  * provided by the JPEG library.  That method assumes that no backtracking\r
156  * is possible.\r
157  */\r
158 \r
159 \r
160 /*\r
161  * Terminate source --- called by jpeg_finish_decompress\r
162  * after all data has been read.  Often a no-op.\r
163  *\r
164  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding\r
165  * application must deal with any cleanup that should happen even\r
166  * for error exit.\r
167  */\r
168 \r
169 METHODDEF void\r
170 term_source (j_decompress_ptr cinfo)\r
171 {\r
172   /* no work necessary here */\r
173 }\r
174 \r
175 \r
176 /*\r
177  * Prepare for input from a stdio stream.\r
178  * The caller must have already opened the stream, and is responsible\r
179  * for closing it after finishing decompression.\r
180  */\r
181 \r
182 GLOBAL void\r
183 jpeg_stdio_src (j_decompress_ptr cinfo, unsigned char *infile, int bufsize)\r
184 {\r
185   my_src_ptr src;\r
186 \r
187   /* The source object and input buffer are made permanent so that a series\r
188    * of JPEG images can be read from the same file by calling jpeg_stdio_src\r
189    * only before the first one.  (If we discarded the buffer at the end of\r
190    * one image, we'd likely lose the start of the next one.)\r
191    * This makes it unsafe to use this manager and a different source\r
192    * manager serially with the same JPEG object.  Caveat programmer.\r
193    */\r
194   if (cinfo->src == NULL) {     /* first time for this JPEG object? */\r
195     cinfo->src = (struct jpeg_source_mgr *)\r
196       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,\r
197                                   SIZEOF(my_source_mgr));\r
198     src = (my_src_ptr) cinfo->src;\r
199     src->buffer = (JOCTET *)\r
200       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,\r
201                                   INPUT_BUF_SIZE * SIZEOF(JOCTET));\r
202   }\r
203 \r
204   src = (my_src_ptr) cinfo->src;\r
205   src->pub.init_source = init_source;\r
206   src->pub.fill_input_buffer = fill_input_buffer;\r
207   src->pub.skip_input_data = skip_input_data;\r
208   src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */\r
209   src->pub.term_source = term_source;\r
210   src->infile = infile;\r
211   src->src_size = bufsize; // FIXME ? merged from Alpha\r
212   src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */\r
213   src->pub.next_input_byte = NULL; /* until buffer loaded */\r
214 }\r
215 \r