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