1 /* 2 * jdatadst.c 3 * 4 * This file was part of the Independent JPEG Group's software: 5 * Copyright (C) 1994-1996, Thomas G. Lane. 6 * Modified 2009-2012 by Guido Vollbeding. 7 * libjpeg-turbo Modifications: 8 * Copyright (C) 2013, D. R. Commander. 9 * For conditions of distribution and use, see the accompanying README file. 10 * 11 * This file contains compression data destination routines for the case of 12 * emitting JPEG data to memory or to a file (or any stdio stream). 13 * While these routines are sufficient for most applications, 14 * some will want to use a different destination manager. 15 * IMPORTANT: we assume that fwrite() will correctly transcribe an array of 16 * JOCTETs into 8-bit-wide elements on external storage. If char is wider 17 * than 8 bits on your machine, you may need to do some tweaking. 18 */ 19 20 /* this is not a core library module, so it doesn't define JPEG_INTERNALS */ 21 #include "jinclude.h" 22 #include "jpeglib.h" 23 #include "jerror.h" 24 25 #ifndef HAVE_STDLIB_H /* <stdlib.h> should declare malloc(),free() */ 26 extern void * malloc JPP((size_t size)); 27 extern void free JPP((void *ptr)); 28 #endif 29 30 31 /* Expanded data destination object for stdio output */ 32 33 typedef struct { 34 struct jpeg_destination_mgr pub; /* public fields */ 35 36 FILE * outfile; /* target stream */ 37 JOCTET * buffer; /* start of buffer */ 38 } my_destination_mgr; 39 40 typedef my_destination_mgr * my_dest_ptr; 41 42 #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ 43 44 45 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) 46 /* Expanded data destination object for memory output */ 47 48 typedef struct { 49 struct jpeg_destination_mgr pub; /* public fields */ 50 51 unsigned char ** outbuffer; /* target buffer */ 52 unsigned long * outsize; 53 unsigned char * newbuffer; /* newly allocated buffer */ 54 JOCTET * buffer; /* start of buffer */ 55 size_t bufsize; 56 } my_mem_destination_mgr; 57 58 typedef my_mem_destination_mgr * my_mem_dest_ptr; 59 #endif 60 61 62 /* 63 * Initialize destination --- called by jpeg_start_compress 64 * before any data is actually written. 65 */ 66 67 METHODDEF(void) 68 init_destination (j_compress_ptr cinfo) 69 { 70 my_dest_ptr dest = (my_dest_ptr) cinfo->dest; 71 72 /* Allocate the output buffer --- it will be released when done with image */ 73 dest->buffer = (JOCTET *) 74 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, 75 OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); 76 77 dest->pub.next_output_byte = dest->buffer; 78 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; 79 } 80 81 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) 82 METHODDEF(void) 83 init_mem_destination (j_compress_ptr cinfo) 84 { 85 /* no work necessary here */ 86 } 87 #endif 88 89 90 /* 91 * Empty the output buffer --- called whenever buffer fills up. 92 * 93 * In typical applications, this should write the entire output buffer 94 * (ignoring the current state of next_output_byte & free_in_buffer), 95 * reset the pointer & count to the start of the buffer, and return TRUE 96 * indicating that the buffer has been dumped. 97 * 98 * In applications that need to be able to suspend compression due to output 99 * overrun, a FALSE return indicates that the buffer cannot be emptied now. 100 * In this situation, the compressor will return to its caller (possibly with 101 * an indication that it has not accepted all the supplied scanlines). The 102 * application should resume compression after it has made more room in the 103 * output buffer. Note that there are substantial restrictions on the use of 104 * suspension --- see the documentation. 105 * 106 * When suspending, the compressor will back up to a convenient restart point 107 * (typically the start of the current MCU). next_output_byte & free_in_buffer 108 * indicate where the restart point will be if the current call returns FALSE. 109 * Data beyond this point will be regenerated after resumption, so do not 110 * write it out when emptying the buffer externally. 111 */ 112 113 METHODDEF(boolean) 114 empty_output_buffer (j_compress_ptr cinfo) 115 { 116 my_dest_ptr dest = (my_dest_ptr) cinfo->dest; 117 118 if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != 119 (size_t) OUTPUT_BUF_SIZE) 120 ERREXIT(cinfo, JERR_FILE_WRITE); 121 122 dest->pub.next_output_byte = dest->buffer; 123 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; 124 125 return TRUE; 126 } 127 128 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) 129 METHODDEF(boolean) 130 empty_mem_output_buffer (j_compress_ptr cinfo) 131 { 132 size_t nextsize; 133 JOCTET * nextbuffer; 134 my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; 135 136 /* Try to allocate new buffer with double size */ 137 nextsize = dest->bufsize * 2; 138 nextbuffer = (JOCTET *) malloc(nextsize); 139 140 if (nextbuffer == NULL) 141 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); 142 143 MEMCOPY(nextbuffer, dest->buffer, dest->bufsize); 144 145 if (dest->newbuffer != NULL) 146 free(dest->newbuffer); 147 148 dest->newbuffer = nextbuffer; 149 150 dest->pub.next_output_byte = nextbuffer + dest->bufsize; 151 dest->pub.free_in_buffer = dest->bufsize; 152 153 dest->buffer = nextbuffer; 154 dest->bufsize = nextsize; 155 156 return TRUE; 157 } 158 #endif 159 160 161 /* 162 * Terminate destination --- called by jpeg_finish_compress 163 * after all data has been written. Usually needs to flush buffer. 164 * 165 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding 166 * application must deal with any cleanup that should happen even 167 * for error exit. 168 */ 169 170 METHODDEF(void) 171 term_destination (j_compress_ptr cinfo) 172 { 173 my_dest_ptr dest = (my_dest_ptr) cinfo->dest; 174 size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; 175 176 /* Write any data remaining in the buffer */ 177 if (datacount > 0) { 178 if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) 179 ERREXIT(cinfo, JERR_FILE_WRITE); 180 } 181 fflush(dest->outfile); 182 /* Make sure we wrote the output file OK */ 183 if (ferror(dest->outfile)) 184 ERREXIT(cinfo, JERR_FILE_WRITE); 185 } 186 187 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) 188 METHODDEF(void) 189 term_mem_destination (j_compress_ptr cinfo) 190 { 191 my_mem_dest_ptr dest = (my_mem_dest_ptr) cinfo->dest; 192 193 *dest->outbuffer = dest->buffer; 194 *dest->outsize = (unsigned long)(dest->bufsize - dest->pub.free_in_buffer); 195 } 196 #endif 197 198 199 /* 200 * Prepare for output to a stdio stream. 201 * The caller must have already opened the stream, and is responsible 202 * for closing it after finishing compression. 203 */ 204 205 GLOBAL(void) 206 jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) 207 { 208 my_dest_ptr dest; 209 210 /* The destination object is made permanent so that multiple JPEG images 211 * can be written to the same file without re-executing jpeg_stdio_dest. 212 * This makes it dangerous to use this manager and a different destination 213 * manager serially with the same JPEG object, because their private object 214 * sizes may be different. Caveat programmer. 215 */ 216 if (cinfo->dest == NULL) { /* first time for this JPEG object? */ 217 cinfo->dest = (struct jpeg_destination_mgr *) 218 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, 219 SIZEOF(my_destination_mgr)); 220 } 221 222 dest = (my_dest_ptr) cinfo->dest; 223 dest->pub.init_destination = init_destination; 224 dest->pub.empty_output_buffer = empty_output_buffer; 225 dest->pub.term_destination = term_destination; 226 dest->outfile = outfile; 227 } 228 229 230 #if JPEG_LIB_VERSION >= 80 || defined(MEM_SRCDST_SUPPORTED) 231 /* 232 * Prepare for output to a memory buffer. 233 * The caller may supply an own initial buffer with appropriate size. 234 * Otherwise, or when the actual data output exceeds the given size, 235 * the library adapts the buffer size as necessary. 236 * The standard library functions malloc/free are used for allocating 237 * larger memory, so the buffer is available to the application after 238 * finishing compression, and then the application is responsible for 239 * freeing the requested memory. 240 */ 241 242 GLOBAL(void) 243 jpeg_mem_dest (j_compress_ptr cinfo, 244 unsigned char ** outbuffer, unsigned long * outsize) 245 { 246 my_mem_dest_ptr dest; 247 248 if (outbuffer == NULL || outsize == NULL) /* sanity check */ 249 ERREXIT(cinfo, JERR_BUFFER_SIZE); 250 251 /* The destination object is made permanent so that multiple JPEG images 252 * can be written to the same buffer without re-executing jpeg_mem_dest. 253 */ 254 if (cinfo->dest == NULL) { /* first time for this JPEG object? */ 255 cinfo->dest = (struct jpeg_destination_mgr *) 256 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, 257 SIZEOF(my_mem_destination_mgr)); 258 } 259 260 dest = (my_mem_dest_ptr) cinfo->dest; 261 dest->pub.init_destination = init_mem_destination; 262 dest->pub.empty_output_buffer = empty_mem_output_buffer; 263 dest->pub.term_destination = term_mem_destination; 264 dest->outbuffer = outbuffer; 265 dest->outsize = outsize; 266 dest->newbuffer = NULL; 267 268 if (*outbuffer == NULL || *outsize == 0) { 269 /* Allocate initial buffer */ 270 dest->newbuffer = *outbuffer = (unsigned char *) malloc(OUTPUT_BUF_SIZE); 271 if (dest->newbuffer == NULL) 272 ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 10); 273 *outsize = OUTPUT_BUF_SIZE; 274 } 275 276 dest->pub.next_output_byte = dest->buffer = *outbuffer; 277 dest->pub.free_in_buffer = dest->bufsize = *outsize; 278 } 279 #endif 280