• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * memsrc.c
3 *
4 * Copyright (C) 1994-1996, Thomas G. Lane.
5 * This file is part of the Independent JPEG Group's software.
6 * For conditions of distribution and use, see the accompanying README file.
7 *
8 * This file contains decompression data source routines for the case of
9 * reading JPEG data from a memory buffer that is preloaded with the entire
10 * JPEG file. This would not seem especially useful at first sight, but
11 * a number of people have asked for it.
12 * This is really just a stripped-down version of jdatasrc.c. Comparison
13 * of this code with jdatasrc.c may be helpful in seeing how to make
14 * custom source managers for other purposes.
15 */
16 
17 /* this is not a core library module, so it doesn't define JPEG_INTERNALS */
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 
22 #ifdef HAVE_JPEG
23 #include <jpeglib.h>
24 #include <jerror.h>
25 #include "jpeg_memsrcdest.h"
26 
27 /* libjpeg8 and later come with their own (API compatible) memory source
28    and dest */
29 #if JPEG_LIB_VERSION < 80 && !defined(MEM_SRCDST_SUPPORTED)
30 
31 /* Expanded data source object for memory input */
32 
33 typedef struct {
34 	struct jpeg_source_mgr pub; /* public fields */
35 
36 	JOCTET eoi_buffer[2]; /* a place to put a dummy EOI */
37 } my_source_mgr;
38 
39 typedef my_source_mgr * my_src_ptr;
40 
41 
42 /*
43 * Initialize source --- called by jpeg_read_header
44 * before any data is actually read.
45 */
46 
47 METHODDEF(void)
init_source(j_decompress_ptr cinfo)48 init_source (j_decompress_ptr cinfo)
49 {
50 	/* No work, since jpeg_mem_src set up the buffer pointer and count.
51 	* Indeed, if we want to read multiple JPEG images from one buffer,
52 	* this *must* not do anything to the pointer.
53 	*/
54 }
55 
56 
57 /*
58 * Fill the input buffer --- called whenever buffer is emptied.
59 *
60 * In this application, this routine should never be called; if it is called,
61 * the decompressor has overrun the end of the input buffer, implying we
62 * supplied an incomplete or corrupt JPEG datastream. A simple error exit
63 * might be the most appropriate response.
64 *
65 * But what we choose to do in this code is to supply dummy EOI markers
66 * in order to force the decompressor to finish processing and supply
67 * some sort of output image, no matter how corrupted.
68 */
69 
70 METHODDEF(boolean)
fill_input_buffer(j_decompress_ptr cinfo)71 fill_input_buffer (j_decompress_ptr cinfo)
72 {
73 	my_src_ptr src = (my_src_ptr) cinfo->src;
74 
75 	WARNMS(cinfo, JWRN_JPEG_EOF);
76 
77 	/* Create a fake EOI marker */
78 	src->eoi_buffer[0] = (JOCTET) 0xFF;
79 	src->eoi_buffer[1] = (JOCTET) JPEG_EOI;
80 	src->pub.next_input_byte = src->eoi_buffer;
81 	src->pub.bytes_in_buffer = 2;
82 
83 	return TRUE;
84 }
85 
86 
87 /*
88 * Skip data --- used to skip over a potentially large amount of
89 * uninteresting data (such as an APPn marker).
90 *
91 * If we overrun the end of the buffer, we let fill_input_buffer deal with
92 * it. An extremely large skip could cause some time-wasting here, but
93 * it really isn't supposed to happen ... and the decompressor will never
94 * skip more than 64K anyway.
95 */
96 
97 METHODDEF(void)
skip_input_data(j_decompress_ptr cinfo,long num_bytes)98 skip_input_data (j_decompress_ptr cinfo, long num_bytes)
99 {
100 	my_src_ptr src = (my_src_ptr) cinfo->src;
101 
102 	if (num_bytes > 0) {
103 		while (num_bytes > (long) src->pub.bytes_in_buffer) {
104 			num_bytes -= (long) src->pub.bytes_in_buffer;
105 			(void) fill_input_buffer(cinfo);
106 			/* note we assume that fill_input_buffer will never
107 			* return FALSE, so suspension need not be handled.
108 			*/
109 		}
110 		src->pub.next_input_byte += (size_t) num_bytes;
111 		src->pub.bytes_in_buffer -= (size_t) num_bytes;
112 	}
113 }
114 
115 
116 /*
117 * An additional method that can be provided by data source modules is the
118 * resync_to_restart method for error recovery in the presence of RST markers.
119 * For the moment, this source module just uses the default resync method
120 * provided by the JPEG library. That method assumes that no backtracking
121 * is possible.
122 */
123 
124 
125 /*
126 * Terminate source --- called by jpeg_finish_decompress
127 * after all data has been read. Often a no-op.
128 *
129 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
130 * application must deal with any cleanup that should happen even
131 * for error exit.
132 */
133 
134 METHODDEF(void)
term_source(j_decompress_ptr cinfo)135 term_source (j_decompress_ptr cinfo)
136 {
137 	/* no work necessary here */
138 }
139 
140 
141 /*
142 * Prepare for input from a memory buffer.
143 */
144 
145 GLOBAL(void)
jpeg_mem_src(j_decompress_ptr cinfo,unsigned char * buffer,unsigned long bufsize)146 jpeg_mem_src (j_decompress_ptr cinfo, unsigned char * buffer,
147 	unsigned long bufsize)
148 {
149 	my_src_ptr src;
150 
151 	/* The source object is made permanent so that a series of JPEG images
152 	* can be read from a single buffer by calling jpeg_mem_src
153 	* only before the first one.
154 	* This makes it unsafe to use this manager and a different source
155 	* manager serially with the same JPEG object. Caveat programmer.
156 	*/
157 	if (cinfo->src == NULL) { /* first time for this JPEG object? */
158 		cinfo->src = (struct jpeg_source_mgr *)
159 			(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
160 						    JPOOL_PERMANENT,
161 						    sizeof(my_source_mgr));
162 	}
163 
164 	src = (my_src_ptr) cinfo->src;
165 	src->pub.init_source = init_source;
166 	src->pub.fill_input_buffer = fill_input_buffer;
167 	src->pub.skip_input_data = skip_input_data;
168 	src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
169 	src->pub.term_source = term_source;
170 
171 	src->pub.next_input_byte = buffer;
172 	src->pub.bytes_in_buffer = bufsize;
173 }
174 
175 
176 
177 /* Memory destination source modelled after Thomas G. Lane's memory source
178    support and jdatadst.c
179 
180    Copyright (C) 2010, Hans de Goede
181 
182    This code may be used under the same conditions as Thomas G. Lane's memory
183    source (see the copyright header at the top of this file).
184  */
185 
186 typedef struct {
187 	struct jpeg_destination_mgr pub; /* public fields */
188 
189 	JOCTET **buffer;              /* start of buffer */
190 	unsigned long buf_size, *outsize;
191 } my_destination_mgr;
192 
193 typedef my_destination_mgr * my_dest_ptr;
194 
195 #define OUTPUT_BUF_SIZE 32768   /* choose an efficiently fwrite'able size */
196 
197 
198 /*
199  * Initialize destination --- called by jpeg_start_compress
200  * before any data is actually written.
201  */
202 
203 METHODDEF(void)
init_destination(j_compress_ptr cinfo)204 init_destination (j_compress_ptr cinfo)
205 {
206 	/* No work, since jpeg_mem_dest set up the buffer pointer and count.
207 	* Indeed, if we want to write multiple JPEG images to one buffer,
208 	* this *must* not do anything to the pointer.
209 	*/
210 }
211 
212 /*
213  * Empty the output buffer --- called whenever buffer fills up.
214  *
215  * In typical applications, this should write the entire output buffer
216  * (ignoring the current state of next_output_byte & free_in_buffer),
217  * reset the pointer & count to the start of the buffer, and return TRUE
218  * indicating that the buffer has been dumped.
219  *
220  * In applications that need to be able to suspend compression due to output
221  * overrun, a FALSE return indicates that the buffer cannot be emptied now.
222  * In this situation, the compressor will return to its caller (possibly with
223  * an indication that it has not accepted all the supplied scanlines).  The
224  * application should resume compression after it has made more room in the
225  * output buffer.  Note that there are substantial restrictions on the use of
226  * suspension --- see the documentation.
227  *
228  * When suspending, the compressor will back up to a convenient restart point
229  * (typically the start of the current MCU). next_output_byte & free_in_buffer
230  * indicate where the restart point will be if the current call returns FALSE.
231  * Data beyond this point will be regenerated after resumption, so do not
232  * write it out when emptying the buffer externally.
233  */
234 
235 METHODDEF(boolean)
empty_output_buffer(j_compress_ptr cinfo)236 empty_output_buffer (j_compress_ptr cinfo)
237 {
238 	my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
239 
240 	*dest->buffer = realloc (*dest->buffer, dest->buf_size + OUTPUT_BUF_SIZE);
241 	if (!*dest->buffer)
242 		ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 0);
243 
244 	dest->pub.next_output_byte = *dest->buffer + dest->buf_size;
245 	dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
246 	dest->buf_size += OUTPUT_BUF_SIZE;
247 
248 	return TRUE;
249 }
250 
251 /*
252  * Terminate destination --- called by jpeg_finish_compress
253  * after all data has been written.  Usually needs to flush buffer.
254  *
255  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
256  * application must deal with any cleanup that should happen even
257  * for error exit.
258  */
259 
260 METHODDEF(void)
term_destination(j_compress_ptr cinfo)261 term_destination (j_compress_ptr cinfo)
262 {
263 	my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
264 
265 	*dest->outsize = dest->buf_size - dest->pub.free_in_buffer;
266 }
267 
268 GLOBAL(void)
jpeg_mem_dest(j_compress_ptr cinfo,unsigned char ** outbuffer,unsigned long * outsize)269 jpeg_mem_dest (j_compress_ptr cinfo, unsigned char ** outbuffer,
270 	unsigned long * outsize)
271 {
272 	my_dest_ptr dest;
273 
274 	/* The destination object is made permanent so that multiple JPEG images
275 	 * can be written to the same file without re-executing jpeg_stdio_dest.
276 	 * This makes it dangerous to use this manager and a different destination
277 	 * manager serially with the same JPEG object, because their private object
278 	 * sizes may be different.  Caveat programmer.
279 	 */
280 	if (cinfo->dest == NULL) {  /* first time for this JPEG object? */
281 		cinfo->dest = (struct jpeg_destination_mgr *)
282 			(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
283 						    JPOOL_PERMANENT,
284 						    sizeof(my_destination_mgr));
285 	}
286 
287 	dest = (my_dest_ptr) cinfo->dest;
288 	dest->pub.init_destination = init_destination;
289 	dest->pub.empty_output_buffer = empty_output_buffer;
290 	dest->pub.term_destination = term_destination;
291 	dest->buffer = outbuffer;
292 	dest->buf_size = *outsize;
293 	dest->outsize = outsize;
294 
295 	if (*dest->buffer == NULL || dest->buf_size == 0) {
296 		/* Allocate initial buffer */
297 		*dest->buffer = malloc(OUTPUT_BUF_SIZE);
298 		if (*dest->buffer == NULL)
299 			ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10);
300 		dest->buf_size = OUTPUT_BUF_SIZE;
301 	}
302 
303 	dest->pub.next_output_byte = *dest->buffer;
304 	dest->pub.free_in_buffer = dest->buf_size;
305 }
306 
307 #endif /* JPEG_LIB_VERSION < 80 && !defined(MEM_SRCDST_SUPPORTED) */
308 #endif /* HAVE_JPEG */
309