1 /* |
1 /* |
2 * jdatadst.c |
2 * jdatadst.c |
3 * |
3 * |
4 * Copyright (C) 1994-1996, Thomas G. Lane. |
4 * Copyright (C) 1994-1996, Thomas G. Lane. |
|
5 * Modified 2009 by Guido Vollbeding. |
5 * This file is part of the Independent JPEG Group's software. |
6 * This file is part of the Independent JPEG Group's software. |
6 * For conditions of distribution and use, see the accompanying README file. |
7 * For conditions of distribution and use, see the accompanying README file. |
7 * |
8 * |
8 * This file contains compression data destination routines for the case of |
9 * This file contains compression data destination routines for the case of |
9 * emitting JPEG data to a file (or any stdio stream). While these routines |
10 * emitting JPEG data to memory or to a file (or any stdio stream). |
10 * are sufficient for most applications, some will want to use a different |
11 * While these routines are sufficient for most applications, |
11 * destination manager. |
12 * some will want to use a different destination manager. |
12 * IMPORTANT: we assume that fwrite() will correctly transcribe an array of |
13 * IMPORTANT: we assume that fwrite() will correctly transcribe an array of |
13 * JOCTETs into 8-bit-wide elements on external storage. If char is wider |
14 * JOCTETs into 8-bit-wide elements on external storage. If char is wider |
14 * than 8 bits on your machine, you may need to do some tweaking. |
15 * than 8 bits on your machine, you may need to do some tweaking. |
15 */ |
16 */ |
16 |
17 |
17 /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ |
18 /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ |
18 #include "jinclude.h" |
19 #include "jinclude.h" |
19 #include "jpeglib.h" |
20 #include "jpeglib.h" |
20 #include "jerror.h" |
21 #include "jerror.h" |
21 |
22 |
|
23 #ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */ |
|
24 extern void * malloc JPP((size_t size)); |
|
25 extern void free JPP((void *ptr)); |
|
26 #endif |
|
27 |
22 |
28 |
23 /* Expanded data destination object for stdio output */ |
29 /* Expanded data destination object for stdio output */ |
24 |
30 |
25 typedef struct { |
31 typedef struct { |
26 struct jpeg_destination_mgr pub; /* public fields */ |
32 struct jpeg_destination_mgr pub; /* public fields */ |
30 } my_destination_mgr; |
36 } my_destination_mgr; |
31 |
37 |
32 typedef my_destination_mgr * my_dest_ptr; |
38 typedef my_destination_mgr * my_dest_ptr; |
33 |
39 |
34 #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ |
40 #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ |
|
41 |
|
42 |
|
43 /* Expanded data destination object for memory output */ |
|
44 |
|
45 typedef struct { |
|
46 struct jpeg_destination_mgr pub; /* public fields */ |
|
47 |
|
48 unsigned char ** outbuffer; /* target buffer */ |
|
49 unsigned long * outsize; |
|
50 unsigned char * newbuffer; /* newly allocated buffer */ |
|
51 JOCTET * buffer; /* start of buffer */ |
|
52 size_t bufsize; |
|
53 } my_mem_destination_mgr; |
|
54 |
|
55 typedef my_mem_destination_mgr * my_mem_dest_ptr; |
35 |
56 |
36 |
57 |
37 /* |
58 /* |
38 * Initialize destination --- called by jpeg_start_compress |
59 * Initialize destination --- called by jpeg_start_compress |
39 * before any data is actually written. |
60 * before any data is actually written. |
49 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
70 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, |
50 OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); |
71 OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); |
51 |
72 |
52 dest->pub.next_output_byte = dest->buffer; |
73 dest->pub.next_output_byte = dest->buffer; |
53 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; |
74 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; |
|
75 } |
|
76 |
|
77 METHODDEF(void) |
|
78 init_mem_destination (j_compress_ptr cinfo) |
|
79 { |
|
80 /* no work necessary here */ |
54 } |
81 } |
55 |
82 |
56 |
83 |
57 /* |
84 /* |
58 * Empty the output buffer --- called whenever buffer fills up. |
85 * Empty the output buffer --- called whenever buffer fills up. |
90 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; |
117 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; |
91 |
118 |
92 return TRUE; |
119 return TRUE; |
93 } |
120 } |
94 |
121 |
|
122 METHODDEF(boolean) |
|
123 empty_mem_output_buffer (j_compress_ptr cinfo) |
|
124 { |
|
125 size_t nextsize; |
|
126 JOCTET * nextbuffer; |
|
127 my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; |
|
128 |
|
129 /* Try to allocate new buffer with double size */ |
|
130 nextsize = dest->bufsize * 2; |
|
131 nextbuffer = malloc(nextsize); |
|
132 |
|
133 if (nextbuffer == NULL) |
|
134 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); |
|
135 |
|
136 MEMCOPY(nextbuffer, dest->buffer, dest->bufsize); |
|
137 |
|
138 if (dest->newbuffer != NULL) |
|
139 free(dest->newbuffer); |
|
140 |
|
141 dest->newbuffer = nextbuffer; |
|
142 |
|
143 dest->pub.next_output_byte = nextbuffer + dest->bufsize; |
|
144 dest->pub.free_in_buffer = dest->bufsize; |
|
145 |
|
146 dest->buffer = nextbuffer; |
|
147 dest->bufsize = nextsize; |
|
148 |
|
149 return TRUE; |
|
150 } |
|
151 |
95 |
152 |
96 /* |
153 /* |
97 * Terminate destination --- called by jpeg_finish_compress |
154 * Terminate destination --- called by jpeg_finish_compress |
98 * after all data has been written. Usually needs to flush buffer. |
155 * after all data has been written. Usually needs to flush buffer. |
99 * |
156 * |
115 } |
172 } |
116 fflush(dest->outfile); |
173 fflush(dest->outfile); |
117 /* Make sure we wrote the output file OK */ |
174 /* Make sure we wrote the output file OK */ |
118 if (ferror(dest->outfile)) |
175 if (ferror(dest->outfile)) |
119 ERREXIT(cinfo, JERR_FILE_WRITE); |
176 ERREXIT(cinfo, JERR_FILE_WRITE); |
|
177 } |
|
178 |
|
179 METHODDEF(void) |
|
180 term_mem_destination (j_compress_ptr cinfo) |
|
181 { |
|
182 my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; |
|
183 |
|
184 *dest->outbuffer = dest->buffer; |
|
185 *dest->outsize = dest->bufsize - dest->pub.free_in_buffer; |
120 } |
186 } |
121 |
187 |
122 |
188 |
123 /* |
189 /* |
124 * Prepare for output to a stdio stream. |
190 * Prepare for output to a stdio stream. |
147 dest->pub.init_destination = init_destination; |
213 dest->pub.init_destination = init_destination; |
148 dest->pub.empty_output_buffer = empty_output_buffer; |
214 dest->pub.empty_output_buffer = empty_output_buffer; |
149 dest->pub.term_destination = term_destination; |
215 dest->pub.term_destination = term_destination; |
150 dest->outfile = outfile; |
216 dest->outfile = outfile; |
151 } |
217 } |
|
218 |
|
219 |
|
220 /* |
|
221 * Prepare for output to a memory buffer. |
|
222 * The caller may supply an own initial buffer with appropriate size. |
|
223 * Otherwise, or when the actual data output exceeds the given size, |
|
224 * the library adapts the buffer size as necessary. |
|
225 * The standard library functions malloc/free are used for allocating |
|
226 * larger memory, so the buffer is available to the application after |
|
227 * finishing compression, and then the application is responsible for |
|
228 * freeing the requested memory. |
|
229 */ |
|
230 |
|
231 GLOBAL(void) |
|
232 jpeg_mem_dest (j_compress_ptr cinfo, |
|
233 unsigned char ** outbuffer, unsigned long * outsize) |
|
234 { |
|
235 my_mem_dest_ptr dest; |
|
236 |
|
237 if (outbuffer == NULL || outsize == NULL) /* sanity check */ |
|
238 ERREXIT(cinfo, JERR_BUFFER_SIZE); |
|
239 |
|
240 /* The destination object is made permanent so that multiple JPEG images |
|
241 * can be written to the same buffer without re-executing jpeg_mem_dest. |
|
242 */ |
|
243 if (cinfo->dest == NULL) { /* first time for this JPEG object? */ |
|
244 cinfo->dest = (struct jpeg_destination_mgr *) |
|
245 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, |
|
246 SIZEOF(my_mem_destination_mgr)); |
|
247 } |
|
248 |
|
249 dest = (my_mem_dest_ptr) cinfo->dest; |
|
250 dest->pub.init_destination = init_mem_destination; |
|
251 dest->pub.empty_output_buffer = empty_mem_output_buffer; |
|
252 dest->pub.term_destination = term_mem_destination; |
|
253 dest->outbuffer = outbuffer; |
|
254 dest->outsize = outsize; |
|
255 dest->newbuffer = NULL; |
|
256 |
|
257 if (*outbuffer == NULL || *outsize == 0) { |
|
258 /* Allocate initial buffer */ |
|
259 dest->newbuffer = *outbuffer = malloc(OUTPUT_BUF_SIZE); |
|
260 if (dest->newbuffer == NULL) |
|
261 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); |
|
262 *outsize = OUTPUT_BUF_SIZE; |
|
263 } |
|
264 |
|
265 dest->pub.next_output_byte = dest->buffer = *outbuffer; |
|
266 dest->pub.free_in_buffer = dest->bufsize = *outsize; |
|
267 } |